From b5532b1c43af07fc5cffb40f105c0e77cb439ad7 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 30 Mar 2021 16:32:25 +0200 Subject: [PATCH 001/308] [ANDROSDK-1310] Add tracker importer comparison JSON files --- .../tracker-importer/event-conflict-new.json | 20 +++++ .../tracker-importer/event-conflict-old.json | 70 +++++++++++++++ .../tracker-importer/event-ok-new.json | 76 ++++++++++++++++ .../tracker-importer/event-ok-old.json | 84 +++++++++++++++++ .../imports/tracker-importer/tei-new.json | 76 ++++++++++++++++ .../imports/tracker-importer/tei-old.json | 90 +++++++++++++++++++ 6 files changed, 416 insertions(+) create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/event-conflict-new.json create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/event-conflict-old.json create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/event-ok-new.json create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/event-ok-old.json create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/tei-new.json create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/tei-old.json diff --git a/core/src/sharedTest/resources/imports/tracker-importer/event-conflict-new.json b/core/src/sharedTest/resources/imports/tracker-importer/event-conflict-new.json new file mode 100644 index 0000000000..339e04b773 --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/event-conflict-new.json @@ -0,0 +1,20 @@ +{ + "status": "ERROR", + "validationReport": { + "errorReports": [ + { + "message": "Event OrganisationUnit: `OrganisationUnit (ABJTilhqOCW)`, and Program: `Program (q04UBOqq3rp)`, dont match.", + "errorCode": "E1029", + "trackerType": "EVENT", + "uid": "STPIK5YTi4f" + } + ] + }, + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 1, + "total": 1 + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/tracker-importer/event-conflict-old.json b/core/src/sharedTest/resources/imports/tracker-importer/event-conflict-old.json new file mode 100644 index 0000000000..9922148b08 --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/event-conflict-old.json @@ -0,0 +1,70 @@ +{ + "httpStatus": "Conflict", + "httpStatusCode": 409, + "status": "ERROR", + "message": "An error occurred, please check import summary.", + "response": { + "responseType": "ImportSummaries", + "status": "ERROR", + "imported": 0, + "updated": 0, + "deleted": 0, + "ignored": 2, + "importOptions": { + "idSchemes": {}, + "dryRun": false, + "async": false, + "importStrategy": "SYNC", + "mergeMode": "REPLACE", + "reportMode": "FULL", + "skipExistingCheck": false, + "sharing": false, + "skipNotifications": false, + "skipAudit": false, + "datasetAllowsPeriods": false, + "strictPeriods": false, + "strictDataElements": false, + "strictCategoryOptionCombos": false, + "strictAttributeOptionCombos": false, + "strictOrganisationUnits": false, + "requireCategoryOptionCombo": false, + "requireAttributeOptionCombo": false, + "skipPatternValidation": false, + "ignoreEmptyCollection": false, + "force": false, + "firstRowIsHeader": true, + "skipLastUpdated": false, + "mergeDataValues": false, + "skipCache": false + }, + "importSummaries": [ + { + "responseType": "ImportSummary", + "status": "ERROR", + "description": "Program is not assigned to this Organisation Unit: ABJTilhqOCW", + "importCount": { + "imported": 0, + "updated": 0, + "ignored": 1, + "deleted": 0 + }, + "conflicts": [], + "reference": "STPIK5YTi4f" + }, + { + "responseType": "ImportSummary", + "status": "ERROR", + "description": "Program is not assigned to this Organisation Unit: ABJTilhqOCW", + "importCount": { + "imported": 0, + "updated": 0, + "ignored": 1, + "deleted": 0 + }, + "conflicts": [], + "reference": "sjSyAZLTOfK" + } + ], + "total": 2 + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/tracker-importer/event-ok-new.json b/core/src/sharedTest/resources/imports/tracker-importer/event-ok-new.json new file mode 100644 index 0000000000..133f20fcfa --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/event-ok-new.json @@ -0,0 +1,76 @@ +{ + "status": "OK", + "validationReport": { + "errorReports": [] + }, + "stats": { + "created": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 1 + }, + "bundleReport": { + "status": "OK", + "typeReportMap": { + "EVENT": { + "trackerType": "EVENT", + "stats": { + "created": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 1 + }, + "objectReports": [ + { + "trackerType": "EVENT", + "uid": "Y8FRzr4y2jG", + "index": 0, + "errorReports": [] + } + ] + }, + "ENROLLMENT": { + "trackerType": "ENROLLMENT", + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 0 + }, + "objectReports": [] + }, + "RELATIONSHIP": { + "trackerType": "RELATIONSHIP", + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 0 + }, + "objectReports": [] + }, + "TRACKED_ENTITY": { + "trackerType": "TRACKED_ENTITY", + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 0 + }, + "objectReports": [] + } + }, + "stats": { + "created": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 1 + } + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/tracker-importer/event-ok-old.json b/core/src/sharedTest/resources/imports/tracker-importer/event-ok-old.json new file mode 100644 index 0000000000..413f3284cf --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/event-ok-old.json @@ -0,0 +1,84 @@ +{ + "httpStatus": "OK", + "httpStatusCode": 200, + "status": "OK", + "message": "Import was successful.", + "response": { + "responseType": "ImportSummaries", + "status": "SUCCESS", + "imported": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "importOptions": { + "idSchemes": {}, + "dryRun": false, + "async": false, + "importStrategy": "SYNC", + "mergeMode": "REPLACE", + "reportMode": "FULL", + "skipExistingCheck": false, + "sharing": false, + "skipNotifications": false, + "skipAudit": false, + "datasetAllowsPeriods": false, + "strictPeriods": false, + "strictDataElements": false, + "strictCategoryOptionCombos": false, + "strictAttributeOptionCombos": false, + "strictOrganisationUnits": false, + "requireCategoryOptionCombo": false, + "requireAttributeOptionCombo": false, + "skipPatternValidation": false, + "ignoreEmptyCollection": false, + "force": false, + "firstRowIsHeader": true, + "skipLastUpdated": false, + "mergeDataValues": false, + "skipCache": false + }, + "importSummaries": [ + { + "responseType": "ImportSummary", + "status": "SUCCESS", + "importOptions": { + "idSchemes": {}, + "dryRun": false, + "async": false, + "importStrategy": "SYNC", + "mergeMode": "REPLACE", + "reportMode": "FULL", + "skipExistingCheck": false, + "sharing": false, + "skipNotifications": false, + "skipAudit": false, + "datasetAllowsPeriods": false, + "strictPeriods": false, + "strictDataElements": false, + "strictCategoryOptionCombos": false, + "strictAttributeOptionCombos": false, + "strictOrganisationUnits": false, + "requireCategoryOptionCombo": false, + "requireAttributeOptionCombo": false, + "skipPatternValidation": false, + "ignoreEmptyCollection": false, + "force": false, + "firstRowIsHeader": true, + "skipLastUpdated": false, + "mergeDataValues": false, + "skipCache": false + }, + "importCount": { + "imported": 1, + "updated": 0, + "ignored": 0, + "deleted": 0 + }, + "conflicts": [], + "reference": "n62vX8eLI6R", + "href": "https://play.dhis2.org/android-dev/api/events/n62vX8eLI6R" + } + ], + "total": 1 + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/tracker-importer/tei-new.json b/core/src/sharedTest/resources/imports/tracker-importer/tei-new.json new file mode 100644 index 0000000000..0ccfb5a54d --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/tei-new.json @@ -0,0 +1,76 @@ +{ + "status": "OK", + "validationReport": { + "errorReports": [] + }, + "stats": { + "created": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 1 + }, + "bundleReport": { + "status": "OK", + "typeReportMap": { + "EVENT": { + "trackerType": "EVENT", + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 0 + }, + "objectReports": [] + }, + "ENROLLMENT": { + "trackerType": "ENROLLMENT", + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 0 + }, + "objectReports": [] + }, + "RELATIONSHIP": { + "trackerType": "RELATIONSHIP", + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 0 + }, + "objectReports": [] + }, + "TRACKED_ENTITY": { + "trackerType": "TRACKED_ENTITY", + "stats": { + "created": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 1 + }, + "objectReports": [ + { + "trackerType": "TRACKED_ENTITY", + "uid": "e34WObjXCwl", + "index": 0, + "errorReports": [] + } + ] + } + }, + "stats": { + "created": 1, + "updated": 0, + "deleted": 0, + "ignored": 0, + "total": 1 + } + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/tracker-importer/tei-old.json b/core/src/sharedTest/resources/imports/tracker-importer/tei-old.json new file mode 100644 index 0000000000..e9fce6315d --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/tei-old.json @@ -0,0 +1,90 @@ +{ + "httpStatus": "OK", + "httpStatusCode": 200, + "status": "OK", + "message": "Import was successful.", + "response": { + "responseType": "ImportSummaries", + "status": "SUCCESS", + "imported": 2, + "updated": 0, + "deleted": 0, + "ignored": 0, + "importOptions": { + "idSchemes": {}, + "dryRun": false, + "async": false, + "importStrategy": "SYNC", + "mergeMode": "REPLACE", + "reportMode": "FULL", + "skipExistingCheck": false, + "sharing": false, + "skipNotifications": false, + "skipAudit": false, + "datasetAllowsPeriods": false, + "strictPeriods": false, + "strictDataElements": false, + "strictCategoryOptionCombos": false, + "strictAttributeOptionCombos": false, + "strictOrganisationUnits": false, + "requireCategoryOptionCombo": false, + "requireAttributeOptionCombo": false, + "skipPatternValidation": false, + "ignoreEmptyCollection": false, + "force": false, + "firstRowIsHeader": true, + "skipLastUpdated": true, + "mergeDataValues": false, + "skipCache": false + }, + "importSummaries": [ + { + "responseType": "ImportSummary", + "status": "SUCCESS", + "importCount": { + "imported": 1, + "updated": 0, + "ignored": 0, + "deleted": 0 + }, + "conflicts": [], + "reference": "xiYp4jWt1Np", + "href": "https://play.dhis2.org/android-dev/api/trackedEntityInstances/xiYp4jWt1Np", + "enrollments": { + "responseType": "ImportSummaries", + "status": "SUCCESS", + "imported": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "importSummaries": [], + "total": 0 + } + }, + { + "responseType": "ImportSummary", + "status": "SUCCESS", + "importCount": { + "imported": 1, + "updated": 0, + "ignored": 0, + "deleted": 0 + }, + "conflicts": [], + "reference": "FkLXx3rin3r", + "href": "https://play.dhis2.org/android-dev/api/trackedEntityInstances/FkLXx3rin3r", + "enrollments": { + "responseType": "ImportSummaries", + "status": "SUCCESS", + "imported": 0, + "updated": 0, + "deleted": 0, + "ignored": 0, + "importSummaries": [], + "total": 0 + } + } + ], + "total": 2 + } +} \ No newline at end of file From 924aa8ca302c693c44e3cc3494c737aeb483f690 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 30 Mar 2021 16:44:02 +0200 Subject: [PATCH 002/308] [ANDROSDK-1310] Store errors for new importer -> events --- ...rImportConflictStoreIntegrationShould.java | 2 +- ...BaseMockIntegrationTestFullDispatcher.java | 6 +- .../wipe/WipeDBCallMockIntegrationShould.java | 4 +- .../internal/EnrollmentImportHandler.java | 6 +- .../event/internal/EventImportHandler.java | 47 +++--------- .../TrackerImporterEventHandlerHelper.kt | 75 +++++++++++++++++++ ...kerImportConflictCollectionRepository.java | 4 +- .../TrackerImportConflictEntityDIModule.java | 5 +- .../internal/TrackerImportConflictStore.kt | 35 +++++++++ ...va => TrackerImportConflictStoreImpl.java} | 36 +++++++-- .../TrackedEntityInstanceImportHandler.java | 6 +- .../tracker/importer/internal/JobQueryCall.kt | 6 +- .../importer/internal/JobReportHandler.kt | 63 ++++++++++++++++ .../EnrollmentImportHandlerShould.java | 5 +- .../internal/EventImportHandlerShould.java | 15 ++-- ...ckedEntityInstanceImportHandlerShould.java | 5 +- 16 files changed, 240 insertions(+), 80 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt rename core/src/main/java/org/hisp/dhis/android/core/imports/internal/{TrackerImportConflictStore.java => TrackerImportConflictStoreImpl.java} (61%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreIntegrationShould.java index e4ead93f47..832c3f1850 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreIntegrationShould.java @@ -41,7 +41,7 @@ public class TrackerImportConflictStoreIntegrationShould extends ObjectStoreAbstractIntegrationShould { public TrackerImportConflictStoreIntegrationShould() { - super(TrackerImportConflictStore.create(TestDatabaseAdapterFactory.get()), + super(TrackerImportConflictStoreImpl.create(TestDatabaseAdapterFactory.get()), TrackerImportConflictTableInfo.TABLE_INFO, TestDatabaseAdapterFactory.get()); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java b/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java index 70d6845144..576270b941 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java @@ -32,8 +32,8 @@ import org.hisp.dhis.android.core.data.imports.TrackerImportConflictSamples; import org.hisp.dhis.android.core.data.maintenance.D2ErrorSamples; import org.hisp.dhis.android.core.imports.ImportStatus; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStoreImpl; import org.hisp.dhis.android.core.maintenance.D2Error; import org.hisp.dhis.android.core.maintenance.D2ErrorCode; import org.hisp.dhis.android.core.maintenance.D2ErrorComponent; @@ -109,8 +109,8 @@ private static void storeSomeD2Errors() { } private static void storeSomeConflicts() { - ObjectStore trackerImportConflictStore = - TrackerImportConflictStore.create(databaseAdapter); + TrackerImportConflictStore trackerImportConflictStore = + TrackerImportConflictStoreImpl.create(databaseAdapter); trackerImportConflictStore.insert(TrackerImportConflictSamples.get().toBuilder() .trackedEntityInstance(null) .enrollment(null) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index d1b8e34f01..5c0a1bcf95 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -33,7 +33,7 @@ import org.hisp.dhis.android.core.fileresource.FileResource; import org.hisp.dhis.android.core.fileresource.internal.FileResourceStoreImpl; import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStoreImpl; import org.hisp.dhis.android.core.maintenance.D2Error; import org.hisp.dhis.android.core.maintenance.D2ErrorCode; import org.hisp.dhis.android.core.maintenance.internal.D2ErrorStore; @@ -85,7 +85,7 @@ private void givenOthersInDatabase() { .errorDescription("Sample error") .build()); - TrackerImportConflictStore.create(databaseAdapter).insert(TrackerImportConflict.builder().build()); + TrackerImportConflictStoreImpl.create(databaseAdapter).insert(TrackerImportConflict.builder().build()); FileResourceStoreImpl.create(databaseAdapter).insert(FileResource.builder().uid("uid").build()); TrackerJobStore.create(databaseAdapter).insert(StorableObjectWithUid.create("uid")); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java index 84510861d7..577d945b4a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java @@ -32,7 +32,6 @@ import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.DataColumns; @@ -46,6 +45,7 @@ import org.hisp.dhis.android.core.imports.internal.EventImportSummaries; import org.hisp.dhis.android.core.imports.internal.ImportConflict; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.note.Note; import org.hisp.dhis.android.core.note.NoteTableInfo; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; @@ -66,7 +66,7 @@ public class EnrollmentImportHandler { private final TrackedEntityInstanceStore trackedEntityInstanceStore; private final IdentifiableObjectStore noteStore; private final EventImportHandler eventImportHandler; - private final ObjectStore trackerImportConflictStore; + private final TrackerImportConflictStore trackerImportConflictStore; private final TrackerImportConflictParser trackerImportConflictParser; private final DataStatePropagator dataStatePropagator; @@ -75,7 +75,7 @@ public EnrollmentImportHandler(@NonNull EnrollmentStore enrollmentStore, @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, @NonNull IdentifiableObjectStore noteStore, @NonNull EventImportHandler eventImportHandler, - @NonNull ObjectStore trackerImportConflictStore, + @NonNull TrackerImportConflictStore trackerImportConflictStore, @NonNull TrackerImportConflictParser trackerImportConflictParser, @NonNull DataStatePropagator dataStatePropagator) { this.enrollmentStore = enrollmentStore; diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java index 0ae67ae660..1fb76e6b61 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java @@ -30,22 +30,15 @@ import androidx.annotation.NonNull; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; -import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; import org.hisp.dhis.android.core.event.EventTableInfo; import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.TrackerImportConflictTableInfo; import org.hisp.dhis.android.core.imports.internal.EventImportSummary; import org.hisp.dhis.android.core.imports.internal.ImportConflict; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.note.NoteTableInfo; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; import java.util.ArrayList; @@ -62,24 +55,24 @@ public class EventImportHandler { private final EventStore eventStore; private final EnrollmentStore enrollmentStore; - private final IdentifiableObjectStore noteStore; private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final ObjectStore trackerImportConflictStore; + private final TrackerImportConflictStore trackerImportConflictStore; private final TrackerImportConflictParser trackerImportConflictParser; + private final TrackerImporterEventHandlerHelper eventHandlerHelper; @Inject public EventImportHandler(@NonNull EventStore eventStore, @NonNull EnrollmentStore enrollmentStore, - @NonNull IdentifiableObjectStore noteStore, @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull ObjectStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser) { + @NonNull TrackerImportConflictStore trackerImportConflictStore, + @NonNull TrackerImportConflictParser trackerImportConflictParser, + TrackerImporterEventHandlerHelper eventHandlerHelper) { this.eventStore = eventStore; this.enrollmentStore = enrollmentStore; - this.noteStore = noteStore; this.trackedEntityInstanceStore = trackedEntityInstanceStore; this.trackerImportConflictStore = trackerImportConflictStore; this.trackerImportConflictParser = trackerImportConflictParser; + this.eventHandlerHelper = eventHandlerHelper; } public void handleEventImportSummaries(List eventImportSummaries, @@ -105,11 +98,11 @@ public void handleEventImportSummaries(List eventImportSumma parentState = parentState == State.ERROR ? State.ERROR : state; } - deleteEventConflicts(eventImportSummary.reference()); + trackerImportConflictStore.deleteEventConflicts(eventImportSummary.reference()); } if (handleAction != HandleAction.Delete) { - handleNoteImportSummary(eventImportSummary.reference(), state); + eventHandlerHelper.handleEventNotes(eventImportSummary.reference(), state); storeEventImportConflicts(eventImportSummary, teiUid, enrollmentUid); } @@ -154,28 +147,6 @@ private void updateParentState(State parentState, String teiUid, String enrollme } } - private void deleteEventConflicts(String eventUid) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(TrackerImportConflictTableInfo.Columns.EVENT, eventUid) - .appendKeyStringValue( - TrackerImportConflictTableInfo.Columns.TABLE_REFERENCE, - EventTableInfo.TABLE_INFO.name()) - .build(); - trackerImportConflictStore.deleteWhereIfExists(whereClause); - } - - private void handleNoteImportSummary(String eventUid, State state) { - State newNoteState = state.equals(State.SYNCED) ? State.SYNCED : State.TO_POST; - String whereClause = new WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) - .appendKeyStringValue(NoteTableInfo.Columns.EVENT, eventUid).build(); - List notes = noteStore.selectWhere(whereClause); - for (Note note : notes) { - noteStore.update(note.toBuilder().state(newNoteState).build()); - } - } - private TrackerImportConflict.Builder getConflictBuilder(String trackedEntityInstanceUid, String enrollmentUid, EventImportSummary eventImportSummary) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt new file mode 100644 index 0000000000..50c0c04520 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004-2019, 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.core.event.internal + +import dagger.Reusable +import java.util.Date +import javax.inject.Inject +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.common.DataColumns +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.event.EventTableInfo +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.TrackerImportConflict +import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.note.NoteTableInfo + +@Reusable +internal class TrackerImporterEventHandlerHelper @Inject internal constructor( + private val noteStore: IdentifiableObjectStore +) { + + fun handleEventNotes(eventUid: String, state: State) { + val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST + val whereClause = WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.STATE, State.uploadableStatesIncludingError().map { it.name } + ) + .appendKeyStringValue(NoteTableInfo.Columns.EVENT, eventUid).build() + val notes: List = noteStore.selectWhere(whereClause) + for (note in notes) { + noteStore.update(note.toBuilder().state(newNoteState).build()) + } + } + + fun getConflictBuilder( + trackedEntityUid: String?, + enrollmentUid: String?, + eventUid: String, + status: ImportStatus + ): TrackerImportConflict.Builder { + return TrackerImportConflict.builder() + .trackedEntityInstance(trackedEntityUid) + .enrollment(enrollmentUid) + .event(eventUid) + .tableReference(EventTableInfo.TABLE_INFO.name()) + .status(status) + .created(Date()) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/TrackerImportConflictCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/imports/TrackerImportConflictCollectionRepository.java index 838200d5c3..51a1d1aec3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/TrackerImportConflictCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/TrackerImportConflictCollectionRepository.java @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.imports; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnlyCollectionRepositoryImpl; import org.hisp.dhis.android.core.arch.repositories.filters.internal.DateFilterConnector; @@ -36,6 +35,7 @@ import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; import org.hisp.dhis.android.core.arch.repositories.filters.internal.StringFilterConnector; import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import java.util.Map; @@ -49,7 +49,7 @@ public final class TrackerImportConflictCollectionRepository @Inject TrackerImportConflictCollectionRepository( - final ObjectStore store, + final TrackerImportConflictStore store, final Map> childrenAppenders, final RepositoryScope scope) { super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictEntityDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictEntityDIModule.java index e1a2501be2..957f82beba 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictEntityDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictEntityDIModule.java @@ -29,7 +29,6 @@ package org.hisp.dhis.android.core.imports.internal; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; import org.hisp.dhis.android.core.imports.TrackerImportConflict; @@ -45,8 +44,8 @@ public final class TrackerImportConflictEntityDIModule { @Provides @Reusable - public ObjectStore store(DatabaseAdapter databaseAdapter) { - return TrackerImportConflictStore.create(databaseAdapter); + public TrackerImportConflictStore store(DatabaseAdapter databaseAdapter) { + return TrackerImportConflictStoreImpl.create(databaseAdapter); } @Provides diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt new file mode 100644 index 0000000000..2d9e40dc67 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2019, 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.core.imports.internal + +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore +import org.hisp.dhis.android.core.imports.TrackerImportConflict + +internal interface TrackerImportConflictStore : ObjectStore { + fun deleteEventConflicts(eventUid: String) +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java similarity index 61% rename from core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.java rename to core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java index 7a40d622f4..e012515f62 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java @@ -29,13 +29,17 @@ package org.hisp.dhis.android.core.imports.internal; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStoreImpl; +import org.hisp.dhis.android.core.event.EventTableInfo; import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.TrackerImportConflictTableInfo; +import org.jetbrains.annotations.NotNull; -public final class TrackerImportConflictStore { +public final class TrackerImportConflictStoreImpl extends ObjectStoreImpl + implements TrackerImportConflictStore { private static final StatementBinder BINDER = (o, w) -> { w.bind(1, o.conflict()); @@ -52,11 +56,29 @@ public final class TrackerImportConflictStore { w.bind(12, o.displayDescription()); }; - private TrackerImportConflictStore() { + private TrackerImportConflictStoreImpl(DatabaseAdapter databaseAdapter, + SQLStatementBuilderImpl builder) { + super(databaseAdapter, builder, BINDER, TrackerImportConflict::create); } - public static ObjectStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.objectStore(databaseAdapter, TrackerImportConflictTableInfo.TABLE_INFO, BINDER, - TrackerImportConflict::create); + public static TrackerImportConflictStore create(DatabaseAdapter databaseAdapter) { + SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl( + TrackerImportConflictTableInfo.TABLE_INFO.name(), + TrackerImportConflictTableInfo.TABLE_INFO.columns()); + + return new TrackerImportConflictStoreImpl(databaseAdapter, statementBuilder); + } + + @Override + public void deleteEventConflicts(@NotNull String eventUid) { + String whereClause = new WhereClauseBuilder() + .appendKeyStringValue(TrackerImportConflictTableInfo.Columns.EVENT, eventUid) + .appendKeyStringValue( + TrackerImportConflictTableInfo.Columns.TABLE_REFERENCE, + EventTableInfo.TABLE_INFO.name() + ) + .build(); + deleteWhereIfExists(whereClause); + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java index fd494ddfd1..46665ffdf1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java @@ -31,7 +31,6 @@ import androidx.annotation.NonNull; import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.internal.DataStatePropagator; @@ -42,6 +41,7 @@ import org.hisp.dhis.android.core.imports.internal.ImportConflict; import org.hisp.dhis.android.core.imports.internal.TEIImportSummary; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.relationship.Relationship; import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository; import org.hisp.dhis.android.core.relationship.RelationshipHelper; @@ -63,7 +63,7 @@ public final class TrackedEntityInstanceImportHandler { private final TrackedEntityInstanceStore trackedEntityInstanceStore; private final EnrollmentImportHandler enrollmentImportHandler; - private final ObjectStore trackerImportConflictStore; + private final TrackerImportConflictStore trackerImportConflictStore; private final TrackerImportConflictParser trackerImportConflictParser; private final RelationshipStore relationshipStore; private final DataStatePropagator dataStatePropagator; @@ -73,7 +73,7 @@ public final class TrackedEntityInstanceImportHandler { @Inject TrackedEntityInstanceImportHandler(@NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, @NonNull EnrollmentImportHandler enrollmentImportHandler, - @NonNull ObjectStore trackerImportConflictStore, + @NonNull TrackerImportConflictStore trackerImportConflictStore, @NonNull TrackerImportConflictParser trackerImportConflictParser, @NonNull RelationshipStore relationshipStore, @NonNull DataStatePropagator dataStatePropagator, diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index d65c4fb225..92eab7712a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -41,7 +41,8 @@ import org.hisp.dhis.android.core.common.StorableObjectWithUid internal class JobQueryCall @Inject internal constructor( private val service: TrackerImporterService, private val apiCallExecutor: APICallExecutor, - private val trackerJobStore: IdentifiableObjectStore + private val trackerJobStore: IdentifiableObjectStore, + private val handler: JobReportHandler ) { fun storeJob(jobId: String) { @@ -74,8 +75,7 @@ internal class JobQueryCall @Inject internal constructor( if (it) { val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) trackerJobStore.delete(jobId) - println(jobReport) - // TODO manage status + handler.handle(jobReport) } } .take(3) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt new file mode 100644 index 0000000000..e7f8d281ca --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2019, 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.core.tracker.importer.internal + +import dagger.Reusable +import javax.inject.Inject +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.event.internal.TrackerImporterEventHandlerHelper +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore + +@Reusable +internal class JobReportHandler @Inject internal constructor( + private val conflictStore: TrackerImportConflictStore, + private val eventHandlerHelper: TrackerImporterEventHandlerHelper +) { + + fun handle(o: JobReport) { + o.validationReport.errorReports.forEach { errorReport -> + if (errorReport.trackerType == "EVENT") { + conflictStore.deleteEventConflicts(errorReport.uid) + eventHandlerHelper.handleEventNotes(errorReport.uid, State.ERROR) + storeEventConflict(errorReport) + } + } + } + + private fun storeEventConflict(error: JobValidationError) { + conflictStore.insert( + eventHandlerHelper.getConflictBuilder(null, null, error.uid, ImportStatus.ERROR) + .conflict(error.message) + .displayDescription(error.message) + .value(error.uid) + .errorCode(error.errorCode) + .build() + ) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java index f9317670da..f065c29250 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java @@ -29,16 +29,15 @@ package org.hisp.dhis.android.core.enrollment.internal; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.event.internal.EventImportHandler; import org.hisp.dhis.android.core.imports.ImportStatus; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary; import org.hisp.dhis.android.core.imports.internal.EventImportSummaries; import org.hisp.dhis.android.core.imports.internal.EventImportSummary; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.note.Note; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; import org.junit.Before; @@ -84,7 +83,7 @@ public class EnrollmentImportHandlerShould { private EnrollmentImportSummary importSummary; @Mock - private ObjectStore trackerImportConflictStore; + private TrackerImportConflictStore trackerImportConflictStore; @Mock private TrackerImportConflictParser trackerImportConflictParser; diff --git a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java index de5f9f939c..6c4056bbb4 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java @@ -28,15 +28,12 @@ package org.hisp.dhis.android.core.event.internal; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; import org.hisp.dhis.android.core.imports.ImportStatus; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.internal.EventImportSummary; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.note.Note; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; import org.junit.Before; import org.junit.Test; @@ -66,13 +63,13 @@ public class EventImportHandlerShould { private EnrollmentStore enrollmentStore; @Mock - private IdentifiableObjectStore noteStore; + private TrackedEntityInstanceStore trackedEntityInstanceStore; @Mock - private TrackedEntityInstanceStore trackedEntityInstanceStore; + private TrackerImportConflictStore trackerImportConflictStore; @Mock - private ObjectStore trackerImportConflictStore; + private TrackerImporterEventHandlerHelper eventHandlerHelper; @Mock private TrackerImportConflictParser trackerImportConflictParser; @@ -86,8 +83,8 @@ public void setUp() throws Exception { when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); - eventImportHandler = new EventImportHandler(eventStore, enrollmentStore, noteStore, trackedEntityInstanceStore, - trackerImportConflictStore, trackerImportConflictParser); + eventImportHandler = new EventImportHandler(eventStore, enrollmentStore, trackedEntityInstanceStore, + trackerImportConflictStore, trackerImportConflictParser, eventHandlerHelper); } @Test diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java index 7ce62be8bd..68159f1f22 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java @@ -28,16 +28,15 @@ package org.hisp.dhis.android.core.trackedentity.internal; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler; import org.hisp.dhis.android.core.imports.ImportStatus; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummaries; import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary; import org.hisp.dhis.android.core.imports.internal.TEIImportSummary; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository; import org.hisp.dhis.android.core.relationship.internal.RelationshipDHISVersionManager; import org.hisp.dhis.android.core.relationship.internal.RelationshipStore; @@ -78,7 +77,7 @@ public class TrackedEntityInstanceImportHandlerShould { private EnrollmentImportSummaries importEnrollment; @Mock - private ObjectStore trackerImportConflictStore; + private TrackerImportConflictStore trackerImportConflictStore; @Mock private TrackerImportConflictParser trackerImportConflictParser; From 633f3aea378ba90acce855307943c7c02a9de770 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 30 Mar 2021 17:04:09 +0200 Subject: [PATCH 003/308] [ANDROSDK-1310] Store state for successful event imports --- .../importer/internal/JobReportHandler.kt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index e7f8d281ca..6d8562c2a9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.event.internal.TrackerImporterEventHandlerHelper import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore @@ -37,17 +38,29 @@ import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore @Reusable internal class JobReportHandler @Inject internal constructor( private val conflictStore: TrackerImportConflictStore, + private val eventStore: EventStore, private val eventHandlerHelper: TrackerImporterEventHandlerHelper ) { fun handle(o: JobReport) { o.validationReport.errorReports.forEach { errorReport -> if (errorReport.trackerType == "EVENT") { - conflictStore.deleteEventConflicts(errorReport.uid) - eventHandlerHelper.handleEventNotes(errorReport.uid, State.ERROR) + handleEvent(errorReport.uid, State.ERROR) storeEventConflict(errorReport) } } + + if (o.bundleReport != null) { + o.bundleReport.typeReportMap.event.objectReports.forEach { objectReport -> + handleEvent(objectReport.uid, State.SYNCED) + } + } + } + + private fun handleEvent(uid: String, state: State) { + eventStore.setState(uid, state) + conflictStore.deleteEventConflicts(uid) + eventHandlerHelper.handleEventNotes(uid, state) } private fun storeEventConflict(error: JobValidationError) { From 916b87faf5e4be20c744235e62b01eea83ad46cc Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 30 Mar 2021 17:28:46 +0200 Subject: [PATCH 004/308] [ANDROSDK-1310] Ktlint --- .../core/tracker/importer/internal/JobReportHandler.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 6d8562c2a9..caa87f4f01 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -49,14 +49,14 @@ internal class JobReportHandler @Inject internal constructor( storeEventConflict(errorReport) } } - + if (o.bundleReport != null) { o.bundleReport.typeReportMap.event.objectReports.forEach { objectReport -> handleEvent(objectReport.uid, State.SYNCED) } } } - + private fun handleEvent(uid: String, state: State) { eventStore.setState(uid, state) conflictStore.deleteEventConflicts(uid) From da2391a65175153ecd7c5ccb0efc558e055e97a5 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 31 Mar 2021 13:17:44 +0200 Subject: [PATCH 005/308] [ANDROSDK-1310-TEIS] Extract delete tei conflicts --- .../internal/TrackerImportConflictStore.kt | 1 + .../TrackerImportConflictStoreImpl.java | 23 +++++++++++++++---- .../TrackedEntityInstanceImportHandler.java | 14 +---------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt index 2d9e40dc67..c0ef0a0bc3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt @@ -32,4 +32,5 @@ import org.hisp.dhis.android.core.imports.TrackerImportConflict internal interface TrackerImportConflictStore : ObjectStore { fun deleteEventConflicts(eventUid: String) + fun deleteTrackedEntityConflicts(tackedEntityUid: String) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java index e012515f62..06490d6af1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java @@ -28,14 +28,18 @@ package org.hisp.dhis.android.core.imports.internal; +import androidx.annotation.NonNull; + import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStoreImpl; +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo; import org.hisp.dhis.android.core.event.EventTableInfo; import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.TrackerImportConflictTableInfo; +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo; import org.jetbrains.annotations.NotNull; public final class TrackerImportConflictStoreImpl extends ObjectStoreImpl @@ -71,14 +75,25 @@ public static TrackerImportConflictStore create(DatabaseAdapter databaseAdapter) @Override public void deleteEventConflicts(@NotNull String eventUid) { + deleteTypeConflicts(TrackerImportConflictTableInfo.Columns.EVENT, + EventTableInfo.TABLE_INFO, + eventUid); + } + + @Override + public void deleteTrackedEntityConflicts(@NonNull String teiUid) { + deleteTypeConflicts(TrackerImportConflictTableInfo.Columns.TRACKED_ENTITY_INSTANCE, + TrackedEntityInstanceTableInfo.TABLE_INFO, + teiUid); + } + + private void deleteTypeConflicts(String column, TableInfo tableInfo, String uid) { String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(TrackerImportConflictTableInfo.Columns.EVENT, eventUid) + .appendKeyStringValue(column, uid) .appendKeyStringValue( TrackerImportConflictTableInfo.Columns.TABLE_REFERENCE, - EventTableInfo.TABLE_INFO.name() - ) + tableInfo.name()) .build(); deleteWhereIfExists(whereClause); - } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java index 46665ffdf1..a7a63ea293 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java @@ -30,13 +30,11 @@ import androidx.annotation.NonNull; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler; import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.TrackerImportConflictTableInfo; import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummaries; import org.hisp.dhis.android.core.imports.internal.ImportConflict; import org.hisp.dhis.android.core.imports.internal.TEIImportSummary; @@ -112,7 +110,7 @@ public void handleTrackedEntityInstanceImportSummaries(List te setRelationshipsState(teiImportSummary.reference(), State.SYNCED); } - deleteTEIConflicts(teiImportSummary.reference()); + trackerImportConflictStore.deleteTrackedEntityConflicts(teiImportSummary.reference()); } if (handleAction != HandleAction.Delete) { @@ -151,16 +149,6 @@ private void storeTEIImportConflicts(TEIImportSummary teiImportSummary) { } } - private void deleteTEIConflicts(String teiUid) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(TrackerImportConflictTableInfo.Columns.TRACKED_ENTITY_INSTANCE, teiUid) - .appendKeyStringValue( - TrackerImportConflictTableInfo.Columns.TABLE_REFERENCE, - TrackedEntityInstanceTableInfo.TABLE_INFO.name()) - .build(); - trackerImportConflictStore.deleteWhereIfExists(whereClause); - } - private void setRelationshipsState(String trackedEntityInstanceUid, State state) { List dbRelationships = relationshipRepository.getByItem(RelationshipHelper.teiItem(trackedEntityInstanceUid), true); From b397f337b3bc372525c0bed6c9e147875f915959 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 31 Mar 2021 16:09:32 +0200 Subject: [PATCH 006/308] [ANDROSDK-1310-TEIS] Generalize JobReportHandler, add basic TEI support --- .../event/internal/EventImportHandler.java | 9 +-- .../internal/JobReportEventHandler.kt} | 44 +++++++------- .../importer/internal/JobReportHandler.kt | 42 +++++--------- .../internal/JobReportTrackedEntityHandler.kt | 58 +++++++++++++++++++ .../importer/internal/JobReportTypeHandler.kt | 45 ++++++++++++++ .../internal/TrackerConflictHelper.kt | 48 +++++++++++++++ .../internal/EventImportHandlerShould.java | 5 +- 7 files changed, 194 insertions(+), 57 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/{event/internal/TrackerImporterEventHandlerHelper.kt => tracker/importer/internal/JobReportEventHandler.kt} (71%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java index 1fb76e6b61..bba54f2035 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java @@ -40,6 +40,7 @@ import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; +import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEventHandler; import java.util.ArrayList; import java.util.Date; @@ -58,7 +59,7 @@ public class EventImportHandler { private final TrackedEntityInstanceStore trackedEntityInstanceStore; private final TrackerImportConflictStore trackerImportConflictStore; private final TrackerImportConflictParser trackerImportConflictParser; - private final TrackerImporterEventHandlerHelper eventHandlerHelper; + private final JobReportEventHandler jobReportEventHandler; @Inject public EventImportHandler(@NonNull EventStore eventStore, @@ -66,13 +67,13 @@ public EventImportHandler(@NonNull EventStore eventStore, @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, @NonNull TrackerImportConflictStore trackerImportConflictStore, @NonNull TrackerImportConflictParser trackerImportConflictParser, - TrackerImporterEventHandlerHelper eventHandlerHelper) { + JobReportEventHandler jobReportEventHandler) { this.eventStore = eventStore; this.enrollmentStore = enrollmentStore; this.trackedEntityInstanceStore = trackedEntityInstanceStore; this.trackerImportConflictStore = trackerImportConflictStore; this.trackerImportConflictParser = trackerImportConflictParser; - this.eventHandlerHelper = eventHandlerHelper; + this.jobReportEventHandler = jobReportEventHandler; } public void handleEventImportSummaries(List eventImportSummaries, @@ -102,7 +103,7 @@ public void handleEventImportSummaries(List eventImportSumma } if (handleAction != HandleAction.Delete) { - eventHandlerHelper.handleEventNotes(eventImportSummary.reference(), state); + jobReportEventHandler.handleEventNotes(eventImportSummary.reference(), state); storeEventImportConflicts(eventImportSummary, teiUid, enrollmentUid); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt similarity index 71% rename from core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index 50c0c04520..0baef8a166 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/TrackerImporterEventHandlerHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -25,25 +25,27 @@ * (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.event.internal +package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable -import java.util.Date import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.common.DataColumns import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.event.EventTableInfo -import org.hisp.dhis.android.core.imports.ImportStatus -import org.hisp.dhis.android.core.imports.TrackerImportConflict +import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.note.NoteTableInfo @Reusable -internal class TrackerImporterEventHandlerHelper @Inject internal constructor( - private val noteStore: IdentifiableObjectStore -) { +internal class JobReportEventHandler @Inject internal constructor( + private val noteStore: IdentifiableObjectStore, + private val conflictStore: TrackerImportConflictStore, + private val eventStore: EventStore, + private val conflictHelper: TrackerConflictHelper +) : JobReportTypeHandler() { fun handleEventNotes(eventUid: String, state: State) { val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST @@ -52,24 +54,22 @@ internal class TrackerImporterEventHandlerHelper @Inject internal constructor( DataColumns.STATE, State.uploadableStatesIncludingError().map { it.name } ) .appendKeyStringValue(NoteTableInfo.Columns.EVENT, eventUid).build() - val notes: List = noteStore.selectWhere(whereClause) - for (note in notes) { + for (note in noteStore.selectWhere(whereClause)) { noteStore.update(note.toBuilder().state(newNoteState).build()) } } - fun getConflictBuilder( - trackedEntityUid: String?, - enrollmentUid: String?, - eventUid: String, - status: ImportStatus - ): TrackerImportConflict.Builder { - return TrackerImportConflict.builder() - .trackedEntityInstance(trackedEntityUid) - .enrollment(enrollmentUid) - .event(eventUid) - .tableReference(EventTableInfo.TABLE_INFO.name()) - .status(status) - .created(Date()) + override fun handleObject(uid: String, state: State) { + eventStore.setState(uid, state) + conflictStore.deleteEventConflicts(uid) + handleEventNotes(uid, state) + } + + override fun storeConflict(errorReport: JobValidationError) { + conflictStore.insert( + conflictHelper.getConflictBuilder(errorReport) + .tableReference(EventTableInfo.TABLE_INFO.name()) + .event(errorReport.uid).build() + ) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index caa87f4f01..13df8691d9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -29,48 +29,32 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import javax.inject.Inject -import org.hisp.dhis.android.core.common.State -import org.hisp.dhis.android.core.event.internal.EventStore -import org.hisp.dhis.android.core.event.internal.TrackerImporterEventHandlerHelper -import org.hisp.dhis.android.core.imports.ImportStatus -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore @Reusable internal class JobReportHandler @Inject internal constructor( - private val conflictStore: TrackerImportConflictStore, - private val eventStore: EventStore, - private val eventHandlerHelper: TrackerImporterEventHandlerHelper + private val eventHandler: JobReportEventHandler, + private val trackedEntityHandler: JobReportTrackedEntityHandler ) { fun handle(o: JobReport) { o.validationReport.errorReports.forEach { errorReport -> - if (errorReport.trackerType == "EVENT") { - handleEvent(errorReport.uid, State.ERROR) - storeEventConflict(errorReport) + when (errorReport.trackerType) { + "EVENT" -> eventHandler.handleError(errorReport) + "TRACKED_ENTITY" -> eventHandler.handleError(errorReport) + else -> println("Unsupported type") // TODO } } if (o.bundleReport != null) { - o.bundleReport.typeReportMap.event.objectReports.forEach { objectReport -> - handleEvent(objectReport.uid, State.SYNCED) - } + val typeMap = o.bundleReport.typeReportMap + applySuccess(typeMap.event, eventHandler) + applySuccess(typeMap.trackedEntity, trackedEntityHandler) } } - private fun handleEvent(uid: String, state: State) { - eventStore.setState(uid, state) - conflictStore.deleteEventConflicts(uid) - eventHandlerHelper.handleEventNotes(uid, state) - } - - private fun storeEventConflict(error: JobValidationError) { - conflictStore.insert( - eventHandlerHelper.getConflictBuilder(null, null, error.uid, ImportStatus.ERROR) - .conflict(error.message) - .displayDescription(error.message) - .value(error.uid) - .errorCode(error.errorCode) - .build() - ) + private fun applySuccess(typeReport: JobTypeReport, typeHandler: JobReportTypeHandler) { + typeReport.objectReports.forEach { objectReport -> + typeHandler.handleSuccess(objectReport.uid) + } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt new file mode 100644 index 0000000000..6428073c99 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2019, 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.core.tracker.importer.internal + +import dagger.Reusable +import javax.inject.Inject +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore + +@Reusable +internal class JobReportTrackedEntityHandler @Inject internal constructor( + private val conflictStore: TrackerImportConflictStore, + private val trackedEntityStore: TrackedEntityInstanceStore, + private val conflictHelper: TrackerConflictHelper +) : JobReportTypeHandler() { + + override fun handleObject(uid: String, state: State) { + trackedEntityStore.setState(uid, state) + conflictStore.deleteTrackedEntityConflicts(uid) + // TODO setRelationshipsState?? + // TODO handle enrollments + } + + override fun storeConflict(errorReport: JobValidationError) { + conflictStore.insert( + conflictHelper.getConflictBuilder(errorReport) + .tableReference(TrackedEntityInstanceTableInfo.TABLE_INFO.name()) + .trackedEntityInstance(errorReport.uid).build() + ) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt new file mode 100644 index 0000000000..c927ef64e7 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004-2019, 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.core.tracker.importer.internal + +import org.hisp.dhis.android.core.common.State + +internal abstract class JobReportTypeHandler { + + fun handleSuccess(uid: String) { + handleObject(uid, State.SYNCED) + } + + fun handleError(errorReport: JobValidationError) { + handleObject(errorReport.uid, State.ERROR) + storeConflict(errorReport) + } + + abstract fun handleObject(uid: String, state: State) + abstract fun storeConflict(errorReport: JobValidationError) +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt new file mode 100644 index 0000000000..3fd0d2e8aa --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2019, 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.core.tracker.importer.internal + +import dagger.Reusable +import java.util.Date +import javax.inject.Inject +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.TrackerImportConflict + +@Reusable +internal class TrackerConflictHelper @Inject internal constructor() { + + fun getConflictBuilder(errorReport: JobValidationError): TrackerImportConflict.Builder { + return TrackerImportConflict.builder() + .conflict(errorReport.message) + .displayDescription(errorReport.message) + .value(errorReport.uid) + .errorCode(errorReport.errorCode) + .status(ImportStatus.ERROR) + .created(Date()) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java index 6c4056bbb4..df6649abcb 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java @@ -35,6 +35,7 @@ import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; +import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEventHandler; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -69,7 +70,7 @@ public class EventImportHandlerShould { private TrackerImportConflictStore trackerImportConflictStore; @Mock - private TrackerImporterEventHandlerHelper eventHandlerHelper; + private JobReportEventHandler jobReportEventHandler; @Mock private TrackerImportConflictParser trackerImportConflictParser; @@ -84,7 +85,7 @@ public void setUp() throws Exception { when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); eventImportHandler = new EventImportHandler(eventStore, enrollmentStore, trackedEntityInstanceStore, - trackerImportConflictStore, trackerImportConflictParser, eventHandlerHelper); + trackerImportConflictStore, trackerImportConflictParser, jobReportEventHandler); } @Test From fadbb672804db136a5cffe06463cb9957b568dfa Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 1 Apr 2021 13:20:16 +0200 Subject: [PATCH 007/308] fix: [TEI-UID-SERIALIZATION-WORKAROUND] Post TEI uid with field trackedEntity instead of uid --- .../core/trackedentity/NewTrackerImporterTrackedEntity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java index 2e0c657bd1..a8f5061ddf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java @@ -58,7 +58,7 @@ public abstract class NewTrackerImporterTrackedEntity extends BaseDeletableDataO implements ObjectWithUidInterface { @Override - @JsonProperty() + @JsonProperty("trackedEntity") public abstract String uid(); @Nullable @@ -119,7 +119,7 @@ public static NewTrackerImporterTrackedEntity create(Cursor cursor) { public abstract static class Builder extends BaseDeletableDataObject.Builder { public abstract Builder id(Long id); - @JsonProperty() + @JsonProperty("trackedEntity") public abstract Builder uid(String uid); public abstract Builder createdAt(Date created); From 1f3eafbe8de1222612a678b110a5d9bd76aa0351 Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 1 Apr 2021 16:18:17 +0200 Subject: [PATCH 008/308] feat: [ANDROSDK-1310] New tracker importer: persist enrollment state --- ...InstancePostCallRealIntegrationShould.java | 2 +- .../NewTrackerImporterEnrollment.java | 4 +- .../internal/EnrollmentImportHandler.java | 13 +--- .../internal/TrackerImportConflictStore.kt | 1 + .../TrackerImportConflictStoreImpl.java | 8 +++ ...porterTrackedEntityPostPayloadGenerator.kt | 2 +- .../internal/JobReportEnrollmentHandler.kt | 59 +++++++++++++++++++ .../importer/internal/JobReportHandler.kt | 3 + .../tei-with-enrollment-error-new.json | 20 +++++++ 9 files changed, 96 insertions(+), 16 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt create mode 100644 core/src/sharedTest/resources/imports/tracker-importer/tei-with-enrollment-error-new.json diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java index 35270c8532..c81a092f74 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java @@ -184,7 +184,7 @@ public void add_and_post_tei_using_repositories() throws Exception { .build()); // Enrollment module -> enroll the tracked entity instance to the program - d2.enrollmentModule().enrollments().add( + d2.enrollmentModule().enrollments().blockingAdd( EnrollmentCreateProjection.builder() .organisationUnit(organisationUnit.uid()) .program(program.uid()) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java index 80620d8131..3b628175f3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java @@ -62,7 +62,7 @@ public abstract class NewTrackerImporterEnrollment extends BaseDeletableDataObject implements ObjectWithUidInterface { @Override - @JsonProperty() + @JsonProperty("enrollment") public abstract String uid(); @Nullable @@ -157,7 +157,7 @@ public static NewTrackerImporterEnrollment create(Cursor cursor) { public abstract static class Builder extends BaseDeletableDataObject.Builder { public abstract Builder id(Long id); - @JsonProperty() + @JsonProperty("enrollment") public abstract Builder uid(String uid); public abstract Builder createdAt(Date createdAt); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java index 577d945b4a..38050c59d5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java @@ -40,7 +40,6 @@ import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; import org.hisp.dhis.android.core.event.internal.EventImportHandler; import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.TrackerImportConflictTableInfo; import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary; import org.hisp.dhis.android.core.imports.internal.EventImportSummaries; import org.hisp.dhis.android.core.imports.internal.ImportConflict; @@ -110,7 +109,7 @@ public void handleEnrollmentImportSummary(List enrollme dataStatePropagator.resetUploadingEventStates(enrollmentImportSummary.reference()); } - deleteEnrollmentConflicts(enrollmentImportSummary.reference()); + trackerImportConflictStore.deleteEnrollmentConflicts(enrollmentImportSummary.reference()); } if (handleAction != HandleAction.Delete) { @@ -183,16 +182,6 @@ private void updateParentState(State parentState, String teiUid) { } } - private void deleteEnrollmentConflicts(String enrollmentUid) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(TrackerImportConflictTableInfo.Columns.ENROLLMENT, enrollmentUid) - .appendKeyStringValue( - TrackerImportConflictTableInfo.Columns.TABLE_REFERENCE, - EnrollmentTableInfo.TABLE_INFO.name()) - .build(); - trackerImportConflictStore.deleteWhereIfExists(whereClause); - } - private TrackerImportConflict.Builder getConflictBuilder(String trackedEntityInstanceUid, EnrollmentImportSummary enrollmentImportSummary) { return TrackerImportConflict.builder() diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt index c0ef0a0bc3..c97e2db1ee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStore.kt @@ -32,5 +32,6 @@ import org.hisp.dhis.android.core.imports.TrackerImportConflict internal interface TrackerImportConflictStore : ObjectStore { fun deleteEventConflicts(eventUid: String) + fun deleteEnrollmentConflicts(enrollmentUid: String) fun deleteTrackedEntityConflicts(tackedEntityUid: String) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java index 06490d6af1..2ed3421245 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStoreImpl; import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo; +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; import org.hisp.dhis.android.core.event.EventTableInfo; import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.TrackerImportConflictTableInfo; @@ -80,6 +81,13 @@ public void deleteEventConflicts(@NotNull String eventUid) { eventUid); } + @Override + public void deleteEnrollmentConflicts(@NotNull String enrollmentUid) { + deleteTypeConflicts(TrackerImportConflictTableInfo.Columns.ENROLLMENT, + EnrollmentTableInfo.TABLE_INFO, + enrollmentUid); + } + @Override public void deleteTrackedEntityConflicts(@NonNull String teiUid) { deleteTypeConflicts(TrackerImportConflictTableInfo.Columns.TRACKED_ENTITY_INSTANCE, diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index bb322ae7c2..727ed6e4ce 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -142,7 +142,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter .notes(notes.filter { it.event() == event.uid() }) eventBuilder.build() } ?: emptyList() - NewTrackerImporterEnrollment.builder() + enrollment.toBuilder() .events(events) .notes(notes.filter { it.enrollment() == enrollment.uid() }) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt new file mode 100644 index 0000000000..22c1eb8507 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2019, 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.core.tracker.importer.internal + +import dagger.Reusable +import javax.inject.Inject +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore + +@Reusable +internal class JobReportEnrollmentHandler @Inject internal constructor( + private val enrollmentStore: EnrollmentStore, + private val conflictStore: TrackerImportConflictStore, + private val conflictHelper: TrackerConflictHelper +) : JobReportTypeHandler() { + + override fun handleObject(uid: String, state: State) { + enrollmentStore.setState(uid, state) + conflictStore.deleteEnrollmentConflicts(uid) + } + + override fun storeConflict(errorReport: JobValidationError) { + val enrollment = enrollmentStore.selectByUid(errorReport.uid) + conflictStore.insert( + conflictHelper.getConflictBuilder(errorReport) + .tableReference(EnrollmentTableInfo.TABLE_INFO.name()) + .enrollment(errorReport.uid) + .trackedEntityInstance(enrollment!!.trackedEntityInstance()) + .build() + ) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 13df8691d9..1bcf75a85c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -33,6 +33,7 @@ import javax.inject.Inject @Reusable internal class JobReportHandler @Inject internal constructor( private val eventHandler: JobReportEventHandler, + private val enrollmentHandler: JobReportEnrollmentHandler, private val trackedEntityHandler: JobReportTrackedEntityHandler ) { @@ -40,6 +41,7 @@ internal class JobReportHandler @Inject internal constructor( o.validationReport.errorReports.forEach { errorReport -> when (errorReport.trackerType) { "EVENT" -> eventHandler.handleError(errorReport) + "ENROLLMENT" -> enrollmentHandler.handleError(errorReport) "TRACKED_ENTITY" -> eventHandler.handleError(errorReport) else -> println("Unsupported type") // TODO } @@ -48,6 +50,7 @@ internal class JobReportHandler @Inject internal constructor( if (o.bundleReport != null) { val typeMap = o.bundleReport.typeReportMap applySuccess(typeMap.event, eventHandler) + applySuccess(typeMap.enrollment, enrollmentHandler) applySuccess(typeMap.trackedEntity, trackedEntityHandler) } } diff --git a/core/src/sharedTest/resources/imports/tracker-importer/tei-with-enrollment-error-new.json b/core/src/sharedTest/resources/imports/tracker-importer/tei-with-enrollment-error-new.json new file mode 100644 index 0000000000..41b34afea1 --- /dev/null +++ b/core/src/sharedTest/resources/imports/tracker-importer/tei-with-enrollment-error-new.json @@ -0,0 +1,20 @@ +{ + "status": "ERROR", + "validationReport": { + "errorReports": [ + { + "message": "Enrollment OrganisationUnit: `OrganisationUnit (ABJTilhqOCW)`, and Program: `Program (IpHINAT79UW)`, dont match.", + "errorCode": "E1041", + "trackerType": "ENROLLMENT", + "uid": "XJPm2lZzxtq" + } + ] + }, + "stats": { + "created": 0, + "updated": 0, + "deleted": 0, + "ignored": 2, + "total": 2 + } +} \ No newline at end of file From 1f86981ad2e57720ef164ade9d7c758ede259ca0 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 6 Apr 2021 13:52:41 +0200 Subject: [PATCH 009/308] [ANDROSDK-1350-DEV] Update copyright notice --- .../TrackerImportConflictStoreImpl.java | 44 +++++++++---------- .../internal/JobReportEnrollmentHandler.kt | 44 +++++++++---------- .../internal/JobReportEventHandler.kt | 44 +++++++++---------- .../importer/internal/JobReportHandler.kt | 44 +++++++++---------- .../internal/JobReportTrackedEntityHandler.kt | 44 +++++++++---------- .../importer/internal/JobReportTypeHandler.kt | 44 +++++++++---------- .../internal/TrackerConflictHelper.kt | 44 +++++++++---------- 7 files changed, 154 insertions(+), 154 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java index 2ed3421245..a330535812 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TrackerImportConflictStoreImpl.java @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.imports.internal; diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt index 22c1eb8507..a28d828f4f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.tracker.importer.internal diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index 0baef8a166..1ccec87d9d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.tracker.importer.internal diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 1bcf75a85c..afd35d18ad 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.tracker.importer.internal diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt index 6428073c99..51c0c0aaf4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.tracker.importer.internal diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt index c927ef64e7..de8bf9ef90 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.tracker.importer.internal diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt index 3fd0d2e8aa..2aad915126 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerConflictHelper.kt @@ -1,29 +1,29 @@ /* - * Copyright (c) 2004-2019, University of Oslo - * All rights reserved. + * Copyright (c) 2004-2021, 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. + * 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. + * 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. + * 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.core.tracker.importer.internal From 87697b3fcba45d5f95b2dc8ba19b093dd9eba14d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 6 Apr 2021 13:54:58 +0200 Subject: [PATCH 010/308] [ANDROSDK-1350-DEV] Update android test copyright notice --- .../android/core/EventWithLimitCallMockIntegrationShould.kt | 6 +++--- .../dbgeneration/LocalAnalyticsDataGenerator.kt | 6 +++--- .../dbgeneration/LocalAnalyticsDatabaseFiller.kt | 6 +++--- .../dbgeneration/LocalAnalyticsMetadataGenerator.kt | 6 +++--- .../localanalytics/dbgeneration/LocalAnalyticsParams.kt | 6 +++--- .../BaseLocalAnalyticsDatabaseSizeMockIntegrationShould.kt | 6 +++--- ...LocalAnalyticsSuperLargeDatabaseMockIntegrationShould.kt | 6 +++--- .../BaseLocalAnalyticsAggregatedMockIntegrationShould.kt | 6 +++--- .../android/localanalytics/tests/BaseLocalAnalyticsTest.kt | 6 +++--- .../tests/BaseLocalAnalyticsTrackerMockIntegrationShould.kt | 6 +++--- ...alAnalyticsAggregatedDefaultDataMockIntegrationShould.kt | 6 +++--- ...ocalAnalyticsAggregatedLargeDataMockIntegrationShould.kt | 6 +++--- ...nalyticsAggregatedSuperLargeDataMockIntegrationShould.kt | 6 +++--- .../LocalAnalyticsTrackerDefaultMockIntegrationShould.kt | 6 +++--- .../LocalAnalyticsTrackerLargeMockIntegrationShould.kt | 6 +++--- .../LocalAnalyticsTrackerSuperLargeMockIntegrationShould.kt | 6 +++--- .../testapp/arch/helpers/FileResizerHelperShould.java | 6 +++--- .../CategoryCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...egoryComboCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../category/CategoryModuleMockIntegrationShould.java | 6 +++--- ...ptionComboCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../CategoryOptionRepositoryMockIntegrationShould.java | 6 +++--- .../ConstantCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...taApprovalCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ataElementCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../DataSetCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...gistrationCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...teRegistrationObjectRepositoryMockIntegrationShould.java | 6 +++--- ...etInstanceCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...nceSummaryCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../testapp/dataset/DataSetModuleMockIntegrationShould.java | 6 +++--- .../SectionCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../DataValueCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../DataValueObjectRepositoryMockIntegrationShould.java | 6 +++--- ...EnrollmentCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../EnrollmentObjectRepositoryMockIntegrationShould.java | 6 +++--- .../EventCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ventFilterCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../event/EventObjectRepositoryMockIntegrationShould.java | 6 +++--- ...EventQueryCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...leResourceCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...rtConflictCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../IndicatorCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...icatorTypeCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../LegendCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../LegendSetCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../D2ErrorCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...yViolationCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../maintenance/MaintenanceMockIntegrationShould.java | 6 +++--- .../note/NoteCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../OptionCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ptionGroupCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../OptionSetCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...sationUnitCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...nUnitGroupCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...nUnitLevelCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../PeriodCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../ProgramCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...mIndicatorCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...RuleActionCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...rogramRuleCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...leVariableCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ramSectionCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ogramStageCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ataElementCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ageSectionCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...yAttributeCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...lyticsSettingsObjectRepositoryMockIntegrationShould.java | 6 +++--- ...TeiSettingCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...aranceSettingsObjectRepositoryMockIntegrationShould.java | 6 +++--- ...DataSetSettingObjectRepositoryMockIntegrationShould.java | 6 +++--- ...eneralSettingsObjectRepositoryMockIntegrationShould.java | 6 +++--- ...ProgramSettingObjectRepositoryMockIntegrationShould.java | 6 +++--- ...izationSettingObjectRepositoryMockIntegrationShould.java | 6 +++--- .../UserSettingsObjectRepositoryMockIntegrationShould.java | 6 +++--- .../android/testapp/sms/SmsModuleMockIntegrationShould.java | 6 +++--- ...yAttributeCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ibuteValueCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...AttributeValueObjectRepositoryMockIntegrationShould.java | 6 +++--- ...ckedEntityCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...yDataValueCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...ntityDataValueObjectRepositoryMockIntegrationShould.java | 6 +++--- ...tyInstanceCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...anceFilterCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...EntityInstanceObjectRepositoryMockIntegrationShould.java | 6 +++--- ...eAttributeCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...tanceQueryCollectionRepositoryMockIntegrationShould.java | 6 +++--- .../AuthorityCollectionRepositoryMockIntegrationShould.java | 6 +++--- ...serCredentialsObjectRepositoryMockIntegrationShould.java | 6 +++--- .../user/UserObjectRepositoryMockIntegrationShould.java | 6 +++--- .../ValidationRuleRepositoryMockIntegrationShould.java | 6 +++--- 91 files changed, 273 insertions(+), 273 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/EventWithLimitCallMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/EventWithLimitCallMockIntegrationShould.kt index a28c654219..ace96396b3 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/EventWithLimitCallMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/EventWithLimitCallMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDataGenerator.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDataGenerator.kt index ad48678312..d992ad0b09 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDataGenerator.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDataGenerator.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDatabaseFiller.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDatabaseFiller.kt index c15c4e1ed1..cc390cf8b0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDatabaseFiller.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsDatabaseFiller.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsMetadataGenerator.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsMetadataGenerator.kt index c907c7ef47..63d9c8d986 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsMetadataGenerator.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsMetadataGenerator.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsParams.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsParams.kt index a6303e5d10..1018f964a5 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsParams.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbgeneration/LocalAnalyticsParams.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/BaseLocalAnalyticsDatabaseSizeMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/BaseLocalAnalyticsDatabaseSizeMockIntegrationShould.kt index 930cfdd4c3..bc058d2453 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/BaseLocalAnalyticsDatabaseSizeMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/BaseLocalAnalyticsDatabaseSizeMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/LocalAnalyticsSuperLargeDatabaseMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/LocalAnalyticsSuperLargeDatabaseMockIntegrationShould.kt index e4cf23ccaf..b01a52cddf 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/LocalAnalyticsSuperLargeDatabaseMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/dbtests/LocalAnalyticsSuperLargeDatabaseMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsAggregatedMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsAggregatedMockIntegrationShould.kt index 371824e0c8..3ff629db87 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsAggregatedMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsAggregatedMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTest.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTest.kt index 90cfb1022c..6769a46b1f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTest.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTest.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTrackerMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTrackerMockIntegrationShould.kt index 190a1dc137..93523a9557 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTrackerMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/BaseLocalAnalyticsTrackerMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedDefaultDataMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedDefaultDataMockIntegrationShould.kt index 72aef1a7b2..48979a49ce 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedDefaultDataMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedDefaultDataMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedLargeDataMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedLargeDataMockIntegrationShould.kt index e8c0e8f83f..5a27775958 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedLargeDataMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedLargeDataMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedSuperLargeDataMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedSuperLargeDataMockIntegrationShould.kt index b554574b00..e8ce6ed5f8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedSuperLargeDataMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsAggregatedSuperLargeDataMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerDefaultMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerDefaultMockIntegrationShould.kt index 9f13e98f4b..1c2e6a08cc 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerDefaultMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerDefaultMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerLargeMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerLargeMockIntegrationShould.kt index 136301a14d..0d78bf217d 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerLargeMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerLargeMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerSuperLargeMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerSuperLargeMockIntegrationShould.kt index 9ad98d25dd..579ba119ef 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerSuperLargeMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/localanalytics/tests/LocalAnalyticsTrackerSuperLargeMockIntegrationShould.kt @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/arch/helpers/FileResizerHelperShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/arch/helpers/FileResizerHelperShould.java index 520961ec61..8352464458 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/arch/helpers/FileResizerHelperShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/arch/helpers/FileResizerHelperShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryCollectionRepositoryMockIntegrationShould.java index a286fca2a3..ce36785f97 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryComboCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryComboCollectionRepositoryMockIntegrationShould.java index 08a4d370db..a67c83712c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryComboCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryComboCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryModuleMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryModuleMockIntegrationShould.java index 3b1cf00142..ed66204187 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryModuleMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryModuleMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionComboCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionComboCollectionRepositoryMockIntegrationShould.java index cc3ade3933..ea94bcc637 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionComboCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionComboCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionRepositoryMockIntegrationShould.java index 0138db1c05..c3de878c85 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/category/CategoryOptionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/constant/ConstantCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/constant/ConstantCollectionRepositoryMockIntegrationShould.java index 7b020c12ce..b84e4a394f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/constant/ConstantCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/constant/ConstantCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataapproval/DataApprovalCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataapproval/DataApprovalCollectionRepositoryMockIntegrationShould.java index 0c9fe0f515..64790365dc 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataapproval/DataApprovalCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataapproval/DataApprovalCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataelement/DataElementCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataelement/DataElementCollectionRepositoryMockIntegrationShould.java index 18b0ed996f..afebb996c3 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataelement/DataElementCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataelement/DataElementCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCollectionRepositoryMockIntegrationShould.java index a5621fcd2b..40196ef8b2 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationCollectionRepositoryMockIntegrationShould.java index dfc96a13e7..73c2451b02 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java index 5e29fa7250..aa0b8fb1d2 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceCollectionRepositoryMockIntegrationShould.java index 74e7afb12e..f07df18a5b 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceSummaryCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceSummaryCollectionRepositoryMockIntegrationShould.java index a3fd8a0e84..ec5b1fcdfb 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceSummaryCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetInstanceSummaryCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetModuleMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetModuleMockIntegrationShould.java index 4e996bda8a..4c87247482 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetModuleMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetModuleMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/SectionCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/SectionCollectionRepositoryMockIntegrationShould.java index be81bb88ad..628a702e64 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/SectionCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/SectionCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java index ff6076c45b..5487539d3d 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java index d314b92e5d..6f971f4b29 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java index 057724e4ae..609680cf49 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentObjectRepositoryMockIntegrationShould.java index 2ad9e6b34f..bb2a934c4e 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java index 8fc8db8b4a..9783f9eea7 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventFilterCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventFilterCollectionRepositoryMockIntegrationShould.java index 72fa139cab..e43b76fa35 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventFilterCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventFilterCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventObjectRepositoryMockIntegrationShould.java index 9bc4ffa5b8..36d98c59f0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/search/EventQueryCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/search/EventQueryCollectionRepositoryMockIntegrationShould.java index 66733bd4ff..c4f5833bda 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/search/EventQueryCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/search/EventQueryCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java index 9fad2b08a6..6133d83f6a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/imports/TrackerImportConflictCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/imports/TrackerImportConflictCollectionRepositoryMockIntegrationShould.java index 228de14c31..f7ff0a90ae 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/imports/TrackerImportConflictCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/imports/TrackerImportConflictCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorCollectionRepositoryMockIntegrationShould.java index 41eb50e990..03903afa90 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorTypeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorTypeCollectionRepositoryMockIntegrationShould.java index edf9f3961b..14e5e94383 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorTypeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/indicator/IndicatorTypeCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendCollectionRepositoryMockIntegrationShould.java index 081a7324cc..a4dff9f1e9 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendSetCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendSetCollectionRepositoryMockIntegrationShould.java index 3cfdf36609..91b75215f8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendSetCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/legendset/LegendSetCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/D2ErrorCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/D2ErrorCollectionRepositoryMockIntegrationShould.java index b7a8bac574..9812f08f05 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/D2ErrorCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/D2ErrorCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/ForeignKeyViolationCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/ForeignKeyViolationCollectionRepositoryMockIntegrationShould.java index d22a63715b..c1a97190d1 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/ForeignKeyViolationCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/ForeignKeyViolationCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/MaintenanceMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/MaintenanceMockIntegrationShould.java index 7fbeeb88fe..08994bdd59 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/MaintenanceMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/maintenance/MaintenanceMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java index e72e532342..f2757892c8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionCollectionRepositoryMockIntegrationShould.java index 9424983b2e..23afb585a3 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionGroupCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionGroupCollectionRepositoryMockIntegrationShould.java index 5a104a07ee..b89ca9c9b5 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionGroupCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionGroupCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionSetCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionSetCollectionRepositoryMockIntegrationShould.java index 544957c016..5b72687541 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionSetCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/option/OptionSetCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitCollectionRepositoryMockIntegrationShould.java index e0186c02f1..7c655a04c9 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitGroupCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitGroupCollectionRepositoryMockIntegrationShould.java index 6fdfe34e87..abb11f8dbe 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitGroupCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitGroupCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitLevelCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitLevelCollectionRepositoryMockIntegrationShould.java index a8980545a0..d331daedf2 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitLevelCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/organisationunit/OrganisationUnitLevelCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/period/PeriodCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/period/PeriodCollectionRepositoryMockIntegrationShould.java index ae623efbd7..40b72de3f6 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/period/PeriodCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/period/PeriodCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramCollectionRepositoryMockIntegrationShould.java index a4a7187a09..d9b7c730ab 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramIndicatorCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramIndicatorCollectionRepositoryMockIntegrationShould.java index 39fda78266..56d791ec16 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramIndicatorCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramIndicatorCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleActionCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleActionCollectionRepositoryMockIntegrationShould.java index 6cc70ea834..82549eadbe 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleActionCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleActionCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleCollectionRepositoryMockIntegrationShould.java index d103d41747..f712c70eab 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleVariableCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleVariableCollectionRepositoryMockIntegrationShould.java index 71c6d960f8..f705c00d08 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleVariableCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramRuleVariableCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramSectionCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramSectionCollectionRepositoryMockIntegrationShould.java index 5dc5f3c62a..b9cb7a66e7 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramSectionCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramSectionCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java index 4e479feae5..e9ffad0203 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageDataElementCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageDataElementCollectionRepositoryMockIntegrationShould.java index 7e44c5e667..29b2893c28 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageDataElementCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageDataElementCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageSectionCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageSectionCollectionRepositoryMockIntegrationShould.java index b11f9495fc..1579e97567 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageSectionCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageSectionCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramTrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramTrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java index 036c40fdb8..5f8590c31f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramTrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramTrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java index ad1eb2ee40..769f258410 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsTeiSettingCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsTeiSettingCollectionRepositoryMockIntegrationShould.java index 400e539045..6d45585ca3 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsTeiSettingCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsTeiSettingCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AppearanceSettingsObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AppearanceSettingsObjectRepositoryMockIntegrationShould.java index 13867b708a..914d46d9d8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AppearanceSettingsObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AppearanceSettingsObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/DataSetSettingObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/DataSetSettingObjectRepositoryMockIntegrationShould.java index 6a8f546bd1..8597dd4880 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/DataSetSettingObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/DataSetSettingObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java index 27db9b8942..29c9079cec 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/ProgramSettingObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/ProgramSettingObjectRepositoryMockIntegrationShould.java index 1be6f3f739..e912ffc480 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/ProgramSettingObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/ProgramSettingObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/SynchronizationSettingObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/SynchronizationSettingObjectRepositoryMockIntegrationShould.java index 82020a0106..a989707cfd 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/SynchronizationSettingObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/SynchronizationSettingObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/UserSettingsObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/UserSettingsObjectRepositoryMockIntegrationShould.java index 0180f3fa98..18ae4789f2 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/UserSettingsObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/UserSettingsObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java index 3e80302062..e617360931 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java index 5cb9d0b4e8..d2b13e872d 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueCollectionRepositoryMockIntegrationShould.java index 8def1caee7..ed9d2c84af 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueObjectRepositoryMockIntegrationShould.java index 520b46e7fe..85cf70faa6 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityAttributeValueObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java index 34186dbc56..43abad1b09 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueCollectionRepositoryMockIntegrationShould.java index cf57064c32..fdaab33b9b 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueObjectRepositoryMockIntegrationShould.java index dec5748097..4f62ae1017 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityDataValueObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceCollectionRepositoryMockIntegrationShould.java index dba384f1ab..cbbf46449c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceFilterCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceFilterCollectionRepositoryMockIntegrationShould.java index 870529c633..05e3edf1a7 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceFilterCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceFilterCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceObjectRepositoryMockIntegrationShould.java index 95ee947959..86fd92ed47 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityInstanceObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityTypeAttributeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityTypeAttributeCollectionRepositoryMockIntegrationShould.java index bd320e9347..d4bcf86b2d 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityTypeAttributeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityTypeAttributeCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/search/TrackedEntityInstanceQueryCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/search/TrackedEntityInstanceQueryCollectionRepositoryMockIntegrationShould.java index c9f6fa2e9f..236505df37 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/search/TrackedEntityInstanceQueryCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/search/TrackedEntityInstanceQueryCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/AuthorityCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/AuthorityCollectionRepositoryMockIntegrationShould.java index 265e1f78f6..b02db8f6f9 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/AuthorityCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/AuthorityCollectionRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserCredentialsObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserCredentialsObjectRepositoryMockIntegrationShould.java index 3d4c4b9ee5..9cf30cb494 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserCredentialsObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserCredentialsObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserObjectRepositoryMockIntegrationShould.java index 888f750a9a..84984563c8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/user/UserObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/validation/ValidationRuleRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/validation/ValidationRuleRepositoryMockIntegrationShould.java index 396637de8f..7141eb0bac 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/validation/ValidationRuleRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/validation/ValidationRuleRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 From 8e3d334fa7c85aba09d8606edd66b4853c33ad71 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 15:58:31 +0200 Subject: [PATCH 011/308] [androsdk-1334] Add Result sealed class --- .../dhis/android/core/arch/helpers/Result.kt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt new file mode 100644 index 0000000000..ec378a3eba --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +sealed class Result { + data class Success(val value: S) : Result() + data class Failure(val failure: F) : Result() + + val succeeded: Boolean get() = this is Success && value != null + + fun fold(onSuccess: (S) -> Unit, onFailure: (F) -> Unit) { + when (this) { + is Success -> onSuccess(value) + is Failure -> onFailure(failure) + } + } + + override fun toString(): String { + return when (this) { + is Success -> "Success[value=$value]" + is Failure -> "Failure[failure=$failure]" + } + } +} From afb5438fa401ccf47a849beca31726e24e42f3d4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 15:58:49 +0200 Subject: [PATCH 012/308] [androsdk-1334] Add ValueTypeValidator --- .../core/arch/helpers/ValueTypeValidator.kt | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt new file mode 100644 index 0000000000..c8c46d3184 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +import org.hisp.dhis.android.core.common.ValueType + +object ValueTypeValidator { + + @JvmStatic + fun validate(value: String, valueType: ValueType): Result { + return Result.Success(value) + } +} \ No newline at end of file From d720693d0277f64cb43ca46713bb9b4170ff3c78 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 17:16:03 +0200 Subject: [PATCH 013/308] [androsdk-1334] Add when architecture to ValueTypeValidator --- .../dhis/android/core/arch/helpers/Result.kt | 100 ++++++++--------- .../core/arch/helpers/ValueTypeValidator.kt | 103 +++++++++++------- 2 files changed, 115 insertions(+), 88 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt index ec378a3eba..1763371869 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/Result.kt @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.helpers - -sealed class Result { - data class Success(val value: S) : Result() - data class Failure(val failure: F) : Result() - - val succeeded: Boolean get() = this is Success && value != null - - fun fold(onSuccess: (S) -> Unit, onFailure: (F) -> Unit) { - when (this) { - is Success -> onSuccess(value) - is Failure -> onFailure(failure) - } - } - - override fun toString(): String { - return when (this) { - is Success -> "Success[value=$value]" - is Failure -> "Failure[failure=$failure]" - } - } -} +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +sealed class Result { + data class Success(val value: S) : Result() + data class Failure(val failure: F) : Result() + + val succeeded: Boolean get() = this is Success && value != null + + fun fold(onSuccess: (S) -> Unit, onFailure: (F) -> Unit) { + when (this) { + is Success -> onSuccess(value) + is Failure -> onFailure(failure) + } + } + + override fun toString(): String { + return when (this) { + is Success -> "Success[value=$value]" + is Failure -> "Failure[failure=$failure]" + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt index c8c46d3184..f6b8071d6c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt @@ -1,39 +1,66 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.helpers - -import org.hisp.dhis.android.core.common.ValueType - -object ValueTypeValidator { - - @JvmStatic - fun validate(value: String, valueType: ValueType): Result { - return Result.Success(value) - } +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +import org.hisp.dhis.android.core.common.ValueType +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator + +object ValueTypeValidator { + + @JvmStatic + fun validate(value: String, valueType: ValueType): Result { + return when (valueType) { + ValueType.TEXT -> TODO() + ValueType.LONG_TEXT -> TODO() + ValueType.LETTER -> TODO() + ValueType.BOOLEAN -> TODO() + ValueType.TRUE_ONLY -> TODO() + ValueType.DATE -> TODO() + ValueType.DATETIME -> TODO() + ValueType.TIME -> TODO() + ValueType.NUMBER -> TODO() + ValueType.UNIT_INTERVAL -> TODO() + ValueType.PERCENTAGE -> TODO() + ValueType.INTEGER -> TODO() + ValueType.INTEGER_POSITIVE -> IntegerPositiveValidator.validate(value) + ValueType.INTEGER_NEGATIVE -> TODO() + ValueType.INTEGER_ZERO_OR_POSITIVE -> TODO() + ValueType.FILE_RESOURCE -> TODO() + ValueType.COORDINATE -> TODO() + ValueType.PHONE_NUMBER -> TODO() + ValueType.EMAIL -> TODO() + ValueType.USERNAME -> TODO() + ValueType.ORGANISATION_UNIT -> TODO() + ValueType.TRACKER_ASSOCIATE -> TODO() + ValueType.AGE -> TODO() + ValueType.URL -> TODO() + ValueType.IMAGE -> TODO() + } + } } \ No newline at end of file From e61a7e9b67098910caee77aec638f61f14840131 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 17:16:23 +0200 Subject: [PATCH 014/308] [androsdk-1334] Add IntegerPositiveFailure.kt --- .../failures/IntegerPositiveFailure.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt new file mode 100644 index 0000000000..e8dc35ecd2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class IntegerPositiveFailure : Throwable() { + object NumberFormatException : IntegerPositiveFailure() + object ValueIsZero : IntegerPositiveFailure() + object ValueIsNegative : IntegerPositiveFailure() +} From b5a9d130e8d9da8575fd4507d6241e3fab8be581 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 17:16:59 +0200 Subject: [PATCH 015/308] [androsdk-1334] Add IntegerPositiveValidator.kt --- .../validators/IntegerPositiveValidator.kt | 53 +++++++++++++++++++ .../validators/ValueTypeValidator.kt | 36 +++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt new file mode 100644 index 0000000000..788c914bef --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure + +object IntegerPositiveValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + val convertedValue = value.toInt() + when { + convertedValue == 0 -> { + Result.Failure(IntegerPositiveFailure.ValueIsZero) + } + convertedValue < 0 -> { + Result.Failure(IntegerPositiveFailure.ValueIsNegative) + } + else -> { + Result.Success(value) + } + } + } catch (e: Throwable) { + Result.Failure(IntegerPositiveFailure.NumberFormatException) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt new file mode 100644 index 0000000000..dfec8d979e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure + +interface ValueTypeValidator { + fun validate(value: String): Result +} \ No newline at end of file From 2f2e2e3b090a0c3a1615770ba6201291743b2d86 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 17:18:00 +0200 Subject: [PATCH 016/308] [androsdk-1334] Add ValueTypeValidatorShould.kt --- .../arch/helpers/ValueTypeValidatorShould.kt | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt diff --git a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt new file mode 100644 index 0000000000..893b6ef84d --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.common.ValueType +import org.junit.Assert.fail +import org.junit.Test + +class ValueTypeValidatorShould { + + private val valueTypeValidator = ValueTypeValidator + + @Test + fun `Should return the same value when succeeding using when`() { + val value = "5" + when (val result = valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + @Test + fun `Should return the same value when succeeding using fold`() { + val value = "5" + valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE).fold( + onSuccess = { + Truth.assertThat(it).isEqualTo(value) + }, + onFailure = { + fail() + }) + } + + @Test + fun `Should succeed when entering the right value`() { + Truth.assertThat(valueTypeValidator.validate("5", ValueType.INTEGER_POSITIVE).succeeded).isTrue() + } +} From 9290a67d11c981eea2f928a6f8b27eba58a7411a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Apr 2021 17:19:20 +0200 Subject: [PATCH 017/308] [androsdk-1334] Fix line separator --- .../failures/IntegerPositiveFailure.kt | 70 +++++----- .../validators/IntegerPositiveValidator.kt | 106 +++++++-------- .../validators/ValueTypeValidator.kt | 70 +++++----- .../arch/helpers/ValueTypeValidatorShould.kt | 128 +++++++++--------- 4 files changed, 187 insertions(+), 187 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt index e8dc35ecd2..310c66ac35 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt @@ -1,35 +1,35 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures - -sealed class IntegerPositiveFailure : Throwable() { - object NumberFormatException : IntegerPositiveFailure() - object ValueIsZero : IntegerPositiveFailure() - object ValueIsNegative : IntegerPositiveFailure() -} +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class IntegerPositiveFailure : Throwable() { + object NumberFormatException : IntegerPositiveFailure() + object ValueIsZero : IntegerPositiveFailure() + object ValueIsNegative : IntegerPositiveFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt index 788c914bef..2845e78a60 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators - -import org.hisp.dhis.android.core.arch.helpers.Result -import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure - -object IntegerPositiveValidator : ValueTypeValidator { - override fun validate(value: String): Result { - return try { - val convertedValue = value.toInt() - when { - convertedValue == 0 -> { - Result.Failure(IntegerPositiveFailure.ValueIsZero) - } - convertedValue < 0 -> { - Result.Failure(IntegerPositiveFailure.ValueIsNegative) - } - else -> { - Result.Success(value) - } - } - } catch (e: Throwable) { - Result.Failure(IntegerPositiveFailure.NumberFormatException) - } - } -} +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure + +object IntegerPositiveValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + val convertedValue = value.toInt() + when { + convertedValue == 0 -> { + Result.Failure(IntegerPositiveFailure.ValueIsZero) + } + convertedValue < 0 -> { + Result.Failure(IntegerPositiveFailure.ValueIsNegative) + } + else -> { + Result.Success(value) + } + } + } catch (e: Throwable) { + Result.Failure(IntegerPositiveFailure.NumberFormatException) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt index dfec8d979e..c95dcd5daf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt @@ -1,36 +1,36 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators - -import org.hisp.dhis.android.core.arch.helpers.Result -import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure - -interface ValueTypeValidator { - fun validate(value: String): Result +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure + +interface ValueTypeValidator { + fun validate(value: String): Result } \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt index 893b6ef84d..78aa8dc8d9 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt @@ -1,64 +1,64 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.helpers - -import com.google.common.truth.Truth -import org.hisp.dhis.android.core.common.ValueType -import org.junit.Assert.fail -import org.junit.Test - -class ValueTypeValidatorShould { - - private val valueTypeValidator = ValueTypeValidator - - @Test - fun `Should return the same value when succeeding using when`() { - val value = "5" - when (val result = valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE)) { - is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) - is Result.Failure -> fail() - } - } - - @Test - fun `Should return the same value when succeeding using fold`() { - val value = "5" - valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE).fold( - onSuccess = { - Truth.assertThat(it).isEqualTo(value) - }, - onFailure = { - fail() - }) - } - - @Test - fun `Should succeed when entering the right value`() { - Truth.assertThat(valueTypeValidator.validate("5", ValueType.INTEGER_POSITIVE).succeeded).isTrue() - } -} +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.common.ValueType +import org.junit.Assert.fail +import org.junit.Test + +class ValueTypeValidatorShould { + + private val valueTypeValidator = ValueTypeValidator + + @Test + fun `Should return the same value when succeeding using when`() { + val value = "5" + when (val result = valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + @Test + fun `Should return the same value when succeeding using fold`() { + val value = "5" + valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE).fold( + onSuccess = { + Truth.assertThat(it).isEqualTo(value) + }, + onFailure = { + fail() + }) + } + + @Test + fun `Should succeed when entering the right value`() { + Truth.assertThat(valueTypeValidator.validate("5", ValueType.INTEGER_POSITIVE).succeeded).isTrue() + } +} From 72f2b24aa264ec076fedc551a7c885e116ed0db3 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 09:19:45 +0200 Subject: [PATCH 018/308] [androsdk-1334] Detekt --- core/config/detekt.yml | 2 +- .../android/core/arch/helpers/ValueTypeValidator.kt | 2 +- .../validators/IntegerPositiveValidator.kt | 2 +- .../validation/validators/ValueTypeValidator.kt | 2 +- .../core/arch/helpers/ValueTypeValidatorShould.kt | 13 +++++++------ 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/core/config/detekt.yml b/core/config/detekt.yml index e8b670d0e1..59cf0ede2b 100644 --- a/core/config/detekt.yml +++ b/core/config/detekt.yml @@ -68,7 +68,7 @@ complexity: ComplexMethod: active: true threshold: 15 - ignoreSingleWhenExpression: false + ignoreSingleWhenExpression: true ignoreSimpleWhenEntries: false ignoreNestingFunctions: false nestingFunctions: [run, let, apply, with, also, use, forEach, isNotNull, ifNull] diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt index f6b8071d6c..ab2224733e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt @@ -63,4 +63,4 @@ object ValueTypeValidator { ValueType.IMAGE -> TODO() } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt index 2845e78a60..84d9821a14 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt @@ -46,7 +46,7 @@ object IntegerPositiveValidator : ValueTypeValidator { Result.Success(value) } } - } catch (e: Throwable) { + } catch (e: NumberFormatException) { Result.Failure(IntegerPositiveFailure.NumberFormatException) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt index c95dcd5daf..7537f41511 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt @@ -33,4 +33,4 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPo interface ValueTypeValidator { fun validate(value: String): Result -} \ No newline at end of file +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt index 78aa8dc8d9..c45f3b5538 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt @@ -49,12 +49,13 @@ class ValueTypeValidatorShould { fun `Should return the same value when succeeding using fold`() { val value = "5" valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE).fold( - onSuccess = { - Truth.assertThat(it).isEqualTo(value) - }, - onFailure = { - fail() - }) + onSuccess = { + Truth.assertThat(it).isEqualTo(value) + }, + onFailure = { + fail() + } + ) } @Test From 08bb5ff5a1d343e047fc0e3ee8ea103560f188f4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 09:39:33 +0200 Subject: [PATCH 019/308] [androsdk-1334] Add IntegerNegativeValidator --- .../core/arch/helpers/ValueTypeValidator.kt | 3 +- .../failures/IntegerNegativeFailure.kt | 35 ++++++++++++ .../validators/IntegerNegativeValidator.kt | 53 +++++++++++++++++++ .../validators/ValueTypeValidator.kt | 3 +- 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt index ab2224733e..ce4c50aa37 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.arch.helpers import org.hisp.dhis.android.core.common.ValueType +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerNegativeValidator import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator object ValueTypeValidator { @@ -49,7 +50,7 @@ object ValueTypeValidator { ValueType.PERCENTAGE -> TODO() ValueType.INTEGER -> TODO() ValueType.INTEGER_POSITIVE -> IntegerPositiveValidator.validate(value) - ValueType.INTEGER_NEGATIVE -> TODO() + ValueType.INTEGER_NEGATIVE -> IntegerNegativeValidator.validate(value) ValueType.INTEGER_ZERO_OR_POSITIVE -> TODO() ValueType.FILE_RESOURCE -> TODO() ValueType.COORDINATE -> TODO() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt new file mode 100644 index 0000000000..3c3e8dec3c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class IntegerNegativeFailure : Throwable() { + object NumberFormatException : IntegerNegativeFailure() + object ValueIsZero : IntegerNegativeFailure() + object ValueIsPositive : IntegerNegativeFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt new file mode 100644 index 0000000000..288668d6f4 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure + +object IntegerNegativeValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + val convertedValue = value.toInt() + when { + convertedValue == 0 -> { + Result.Failure(IntegerNegativeFailure.ValueIsZero) + } + convertedValue > 0 -> { + Result.Failure(IntegerNegativeFailure.ValueIsPositive) + } + else -> { + Result.Success(value) + } + } + } catch (e: NumberFormatException) { + Result.Failure(IntegerNegativeFailure.NumberFormatException) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt index 7537f41511..08194f6b11 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt @@ -29,8 +29,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result -import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure interface ValueTypeValidator { - fun validate(value: String): Result + fun validate(value: String): Result } From 1951a740752799c50936ae93422431b44f3352ee Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 09:39:42 +0200 Subject: [PATCH 020/308] [androsdk-1334] Add IntegerNegativeValidator test --- .../IntegerNegativeValidatorShould.kt | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt new file mode 100644 index 0000000000..0383511b1b --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure +import org.junit.Assert.fail +import org.junit.Test + +class IntegerNegativeValidatorShould { + + private val validator = IntegerNegativeValidator + + @Test + fun `Should return the same value when succeeding`() { + val value = "-15" + when (val result = validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + @Test + fun `Should fail with a value is positive exception when value is positive`() { + val value = "5" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsPositive) + } + } + + @Test + fun `Should fail with a value is zero exception when value is zero`() { + val value = "0" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsZero) + } + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + val value = "5fe2" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.NumberFormatException) + } + } +} From 64d7bc92c8ac3d73a01ffe9631059d90190cd108 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 09:40:54 +0200 Subject: [PATCH 021/308] [androsdk-1334] Fix line separator --- .../IntegerNegativeValidatorShould.kt | 152 +++++++++--------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt index 0383511b1b..658e61a1e6 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt @@ -1,76 +1,76 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators - -import com.google.common.truth.Truth -import org.hisp.dhis.android.core.arch.helpers.Result -import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure -import org.junit.Assert.fail -import org.junit.Test - -class IntegerNegativeValidatorShould { - - private val validator = IntegerNegativeValidator - - @Test - fun `Should return the same value when succeeding`() { - val value = "-15" - when (val result = validator.validate(value)) { - is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) - is Result.Failure -> fail() - } - } - - @Test - fun `Should fail with a value is positive exception when value is positive`() { - val value = "5" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsPositive) - } - } - - @Test - fun `Should fail with a value is zero exception when value is zero`() { - val value = "0" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsZero) - } - } - - @Test - fun `Should fail with a number format exception when value is malformed`() { - val value = "5fe2" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.NumberFormatException) - } - } -} +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure +import org.junit.Assert.fail +import org.junit.Test + +class IntegerNegativeValidatorShould { + + private val validator = IntegerNegativeValidator + + @Test + fun `Should return the same value when succeeding`() { + val value = "-15" + when (val result = validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + @Test + fun `Should fail with a value is positive exception when value is positive`() { + val value = "5" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsPositive) + } + } + + @Test + fun `Should fail with a value is zero exception when value is zero`() { + val value = "0" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsZero) + } + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + val value = "5fe2" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.NumberFormatException) + } + } +} From 1c28f30c5b43cfc1f0bea478b24d48c3b572a1ac Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 10:52:47 +0200 Subject: [PATCH 022/308] [androsdk-1334] Rename .java to .kt --- .../dhis/android/core/common/{ValueType.java => ValueType.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/common/{ValueType.java => ValueType.kt} (100%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.java b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt similarity index 100% rename from core/src/main/java/org/hisp/dhis/android/core/common/ValueType.java rename to core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt From 62232597c16cb94edf8a4d6e09d0d57581394a92 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 10:52:48 +0200 Subject: [PATCH 023/308] [androsdk-1334] Convert ValueType to Kotlin --- .../dhis/android/core/common/ValueType.kt | 162 +++++++----------- .../validation/validators/DefaultValidator.kt | 37 ++++ 2 files changed, 99 insertions(+), 100 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index f582323734..0da3bf9603 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -25,104 +25,66 @@ * (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.common; - -import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; - -import java.util.Arrays; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -public enum ValueType { - TEXT(String.class), - LONG_TEXT(String.class), - LETTER(String.class), - BOOLEAN(Boolean.class), - TRUE_ONLY(Boolean.class), - DATE(Date.class), - DATETIME(Date.class), - TIME(String.class), - NUMBER(Double.class), - UNIT_INTERVAL(Double.class), - PERCENTAGE(Double.class), - INTEGER(Integer.class), - INTEGER_POSITIVE(Integer.class), - INTEGER_NEGATIVE(Integer.class), - INTEGER_ZERO_OR_POSITIVE(Integer.class), - FILE_RESOURCE(String.class), - COORDINATE(String.class), - - // TODO: Categorize - PHONE_NUMBER(String.class), - EMAIL(String.class), - USERNAME(String.class), - - // TODO: Implement later - ORGANISATION_UNIT(OrganisationUnit.class), - TRACKER_ASSOCIATE(TrackedEntityInstance.class), - - //New values: - AGE(Date.class), - URL(String.class), - - IMAGE(String.class); - - private static final Set INTEGER_TYPES = new HashSet<>(Arrays.asList(INTEGER, - INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE)); - - private static final Set NUMERIC_TYPES = new HashSet<>(Arrays.asList(INTEGER, NUMBER, - INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE, UNIT_INTERVAL, PERCENTAGE)); - - private static final Set BOOLEAN_TYPES = new HashSet<>(Arrays.asList(BOOLEAN, - TRUE_ONLY)); - - private static final Set TEXT_TYPES = new HashSet<>(Arrays.asList(TEXT, LONG_TEXT, - LETTER, COORDINATE, TIME, IMAGE)); - - private static final Set DATE_TYPES = new HashSet<>(Arrays.asList(DATE, DATETIME)); - - private final Class javaClass; - - ValueType() { - this.javaClass = null; - } - - ValueType(Class javaClass) { - this.javaClass = javaClass; - } - - public Class getJavaClass() { - return javaClass; - } - - public boolean isInteger() { - return INTEGER_TYPES.contains(this); - } - - public boolean isNumeric() { - return NUMERIC_TYPES.contains(this); - } - - public boolean isBoolean() { - return BOOLEAN_TYPES.contains(this); - } - - public boolean isText() { - return TEXT_TYPES.contains(this); - } - - public boolean isDate() { - return DATE_TYPES.contains(this); - } - - public boolean isFile() { - return this == FILE_RESOURCE; - } - - public boolean isCoordinate() { - return this == COORDINATE; +package org.hisp.dhis.android.core.common + +import org.hisp.dhis.android.core.common.valuetype.validation.validators.DefaultValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerNegativeValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.ValueTypeValidator +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import java.util.* + +enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { + TEXT(String::class.java, DefaultValidator), + LONG_TEXT(String::class.java, DefaultValidator), + LETTER(String::class.java, DefaultValidator), + BOOLEAN(Boolean::class.java, DefaultValidator), + TRUE_ONLY(Boolean::class.java, DefaultValidator), + DATE(Date::class.java, DefaultValidator), + DATETIME(Date::class.java, DefaultValidator), + TIME(String::class.java, DefaultValidator), + NUMBER(Double::class.java, DefaultValidator), + UNIT_INTERVAL(Double::class.java, DefaultValidator), + PERCENTAGE(Double::class.java, DefaultValidator), + INTEGER(Int::class.java, DefaultValidator), + INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), + INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), + INTEGER_ZERO_OR_POSITIVE(Int::class.java, DefaultValidator), + FILE_RESOURCE(String::class.java, DefaultValidator), + COORDINATE(String::class.java, DefaultValidator), + PHONE_NUMBER(String::class.java, DefaultValidator), + EMAIL(String::class.java, DefaultValidator), + USERNAME(String::class.java, DefaultValidator), + ORGANISATION_UNIT(OrganisationUnit::class.java, DefaultValidator), + TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, DefaultValidator), + AGE(Date::class.java, DefaultValidator), + URL(String::class.java, DefaultValidator), + IMAGE(String::class.java, DefaultValidator); + + val isInteger: Boolean + get() = INTEGER_TYPES.contains(this) + val isNumeric: Boolean + get() = NUMERIC_TYPES.contains(this) + val isBoolean: Boolean + get() = BOOLEAN_TYPES.contains(this) + val isText: Boolean + get() = TEXT_TYPES.contains(this) + val isDate: Boolean + get() = DATE_TYPES.contains(this) + val isFile: Boolean + get() = this == FILE_RESOURCE + val isCoordinate: Boolean + get() = this == COORDINATE + + companion object { + private val INTEGER_TYPES: Set = + HashSet(listOf(INTEGER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE)) + private val NUMERIC_TYPES: Set = + HashSet(listOf(INTEGER, NUMBER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE, + UNIT_INTERVAL, PERCENTAGE)) + private val BOOLEAN_TYPES: Set = HashSet(listOf(BOOLEAN, TRUE_ONLY)) + private val TEXT_TYPES: Set = HashSet(listOf(TEXT, LONG_TEXT, LETTER, COORDINATE, TIME, IMAGE)) + private val DATE_TYPES: Set = HashSet(listOf(DATE, DATETIME)) } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt new file mode 100644 index 0000000000..897eac07b9 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result + +object DefaultValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return Result.Success(value) + } +} From bdc9e6cf54f27bdc510685fb10d4568fd9db07cc Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 10:53:46 +0200 Subject: [PATCH 024/308] [androsdk-1334] Add ResultShould.kt and ValueTypeValidatorGetterShould.kt --- ...TypeValidatorShould.kt => ResultShould.kt} | 140 ++++++++++-------- .../ValueTypeValidatorGetterShould.kt} | 116 ++++++--------- 2 files changed, 124 insertions(+), 132 deletions(-) rename core/src/test/java/org/hisp/dhis/android/core/arch/helpers/{ValueTypeValidatorShould.kt => ResultShould.kt} (75%) rename core/src/{main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt => test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt} (50%) diff --git a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt similarity index 75% rename from core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt rename to core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt index c45f3b5538..e8acfe2533 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt @@ -1,65 +1,75 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.helpers - -import com.google.common.truth.Truth -import org.hisp.dhis.android.core.common.ValueType -import org.junit.Assert.fail -import org.junit.Test - -class ValueTypeValidatorShould { - - private val valueTypeValidator = ValueTypeValidator - - @Test - fun `Should return the same value when succeeding using when`() { - val value = "5" - when (val result = valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE)) { - is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) - is Result.Failure -> fail() - } - } - - @Test - fun `Should return the same value when succeeding using fold`() { - val value = "5" - valueTypeValidator.validate(value, ValueType.INTEGER_POSITIVE).fold( - onSuccess = { - Truth.assertThat(it).isEqualTo(value) - }, - onFailure = { - fail() - } - ) - } - - @Test - fun `Should succeed when entering the right value`() { - Truth.assertThat(valueTypeValidator.validate("5", ValueType.INTEGER_POSITIVE).succeeded).isTrue() - } -} +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator +import org.junit.Assert.fail +import org.junit.Test + +class ResultShould { + + private val validator = IntegerPositiveValidator + + @Test + fun `Should return the same value when succeeding using when`() { + val value = "5" + when (val result = validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + @Test + fun `Should return a failure when the validator fails`() { + val value = "-5" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerPositiveFailure.ValueIsNegative) + } + } + + @Test + fun `Should return the same value when succeeding using fold`() { + val value = "5" + validator.validate(value).fold( + onSuccess = { + Truth.assertThat(it).isEqualTo(value) + }, + onFailure = { + fail() + } + ) + } + + @Test + fun `Should succeed when entering the right value`() { + Truth.assertThat(validator.validate("5").succeeded).isTrue() + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt similarity index 50% rename from core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt rename to core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt index ce4c50aa37..41c20b4d7a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/ValueTypeValidator.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt @@ -1,67 +1,49 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.helpers - -import org.hisp.dhis.android.core.common.ValueType -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerNegativeValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator - -object ValueTypeValidator { - - @JvmStatic - fun validate(value: String, valueType: ValueType): Result { - return when (valueType) { - ValueType.TEXT -> TODO() - ValueType.LONG_TEXT -> TODO() - ValueType.LETTER -> TODO() - ValueType.BOOLEAN -> TODO() - ValueType.TRUE_ONLY -> TODO() - ValueType.DATE -> TODO() - ValueType.DATETIME -> TODO() - ValueType.TIME -> TODO() - ValueType.NUMBER -> TODO() - ValueType.UNIT_INTERVAL -> TODO() - ValueType.PERCENTAGE -> TODO() - ValueType.INTEGER -> TODO() - ValueType.INTEGER_POSITIVE -> IntegerPositiveValidator.validate(value) - ValueType.INTEGER_NEGATIVE -> IntegerNegativeValidator.validate(value) - ValueType.INTEGER_ZERO_OR_POSITIVE -> TODO() - ValueType.FILE_RESOURCE -> TODO() - ValueType.COORDINATE -> TODO() - ValueType.PHONE_NUMBER -> TODO() - ValueType.EMAIL -> TODO() - ValueType.USERNAME -> TODO() - ValueType.ORGANISATION_UNIT -> TODO() - ValueType.TRACKER_ASSOCIATE -> TODO() - ValueType.AGE -> TODO() - ValueType.URL -> TODO() - ValueType.IMAGE -> TODO() - } - } -} +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.ValueType +import org.junit.Assert.fail +import org.junit.Test + +class ValueTypeValidatorGetterShould { + + private val valueType = ValueType.INTEGER_POSITIVE + + @Test + fun `Should return a valid value type validator`() { + val value = "5" + when (val result = valueType.validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } +} From 16c4e501bd93cbb635fea5893ff112042cba0462 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Apr 2021 10:54:41 +0200 Subject: [PATCH 025/308] [androsdk-1334] Fix line separators --- .../dhis/android/core/common/ValueType.kt | 180 +++++++++--------- .../validation/validators/DefaultValidator.kt | 74 +++---- .../android/core/arch/helpers/ResultShould.kt | 150 +++++++-------- .../ValueTypeValidatorGetterShould.kt | 98 +++++----- 4 files changed, 251 insertions(+), 251 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 0da3bf9603..eaef7f3871 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -1,90 +1,90 @@ -/* - * Copyright (c) 2004-2021, 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.core.common - -import org.hisp.dhis.android.core.common.valuetype.validation.validators.DefaultValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerNegativeValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.ValueTypeValidator -import org.hisp.dhis.android.core.organisationunit.OrganisationUnit -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import java.util.* - -enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { - TEXT(String::class.java, DefaultValidator), - LONG_TEXT(String::class.java, DefaultValidator), - LETTER(String::class.java, DefaultValidator), - BOOLEAN(Boolean::class.java, DefaultValidator), - TRUE_ONLY(Boolean::class.java, DefaultValidator), - DATE(Date::class.java, DefaultValidator), - DATETIME(Date::class.java, DefaultValidator), - TIME(String::class.java, DefaultValidator), - NUMBER(Double::class.java, DefaultValidator), - UNIT_INTERVAL(Double::class.java, DefaultValidator), - PERCENTAGE(Double::class.java, DefaultValidator), - INTEGER(Int::class.java, DefaultValidator), - INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), - INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), - INTEGER_ZERO_OR_POSITIVE(Int::class.java, DefaultValidator), - FILE_RESOURCE(String::class.java, DefaultValidator), - COORDINATE(String::class.java, DefaultValidator), - PHONE_NUMBER(String::class.java, DefaultValidator), - EMAIL(String::class.java, DefaultValidator), - USERNAME(String::class.java, DefaultValidator), - ORGANISATION_UNIT(OrganisationUnit::class.java, DefaultValidator), - TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, DefaultValidator), - AGE(Date::class.java, DefaultValidator), - URL(String::class.java, DefaultValidator), - IMAGE(String::class.java, DefaultValidator); - - val isInteger: Boolean - get() = INTEGER_TYPES.contains(this) - val isNumeric: Boolean - get() = NUMERIC_TYPES.contains(this) - val isBoolean: Boolean - get() = BOOLEAN_TYPES.contains(this) - val isText: Boolean - get() = TEXT_TYPES.contains(this) - val isDate: Boolean - get() = DATE_TYPES.contains(this) - val isFile: Boolean - get() = this == FILE_RESOURCE - val isCoordinate: Boolean - get() = this == COORDINATE - - companion object { - private val INTEGER_TYPES: Set = - HashSet(listOf(INTEGER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE)) - private val NUMERIC_TYPES: Set = - HashSet(listOf(INTEGER, NUMBER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE, - UNIT_INTERVAL, PERCENTAGE)) - private val BOOLEAN_TYPES: Set = HashSet(listOf(BOOLEAN, TRUE_ONLY)) - private val TEXT_TYPES: Set = HashSet(listOf(TEXT, LONG_TEXT, LETTER, COORDINATE, TIME, IMAGE)) - private val DATE_TYPES: Set = HashSet(listOf(DATE, DATETIME)) - } -} +/* + * Copyright (c) 2004-2021, 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.core.common + +import org.hisp.dhis.android.core.common.valuetype.validation.validators.DefaultValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerNegativeValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.ValueTypeValidator +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import java.util.* + +enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { + TEXT(String::class.java, DefaultValidator), + LONG_TEXT(String::class.java, DefaultValidator), + LETTER(String::class.java, DefaultValidator), + BOOLEAN(Boolean::class.java, DefaultValidator), + TRUE_ONLY(Boolean::class.java, DefaultValidator), + DATE(Date::class.java, DefaultValidator), + DATETIME(Date::class.java, DefaultValidator), + TIME(String::class.java, DefaultValidator), + NUMBER(Double::class.java, DefaultValidator), + UNIT_INTERVAL(Double::class.java, DefaultValidator), + PERCENTAGE(Double::class.java, DefaultValidator), + INTEGER(Int::class.java, DefaultValidator), + INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), + INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), + INTEGER_ZERO_OR_POSITIVE(Int::class.java, DefaultValidator), + FILE_RESOURCE(String::class.java, DefaultValidator), + COORDINATE(String::class.java, DefaultValidator), + PHONE_NUMBER(String::class.java, DefaultValidator), + EMAIL(String::class.java, DefaultValidator), + USERNAME(String::class.java, DefaultValidator), + ORGANISATION_UNIT(OrganisationUnit::class.java, DefaultValidator), + TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, DefaultValidator), + AGE(Date::class.java, DefaultValidator), + URL(String::class.java, DefaultValidator), + IMAGE(String::class.java, DefaultValidator); + + val isInteger: Boolean + get() = INTEGER_TYPES.contains(this) + val isNumeric: Boolean + get() = NUMERIC_TYPES.contains(this) + val isBoolean: Boolean + get() = BOOLEAN_TYPES.contains(this) + val isText: Boolean + get() = TEXT_TYPES.contains(this) + val isDate: Boolean + get() = DATE_TYPES.contains(this) + val isFile: Boolean + get() = this == FILE_RESOURCE + val isCoordinate: Boolean + get() = this == COORDINATE + + companion object { + private val INTEGER_TYPES: Set = + HashSet(listOf(INTEGER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE)) + private val NUMERIC_TYPES: Set = + HashSet(listOf(INTEGER, NUMBER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE, + UNIT_INTERVAL, PERCENTAGE)) + private val BOOLEAN_TYPES: Set = HashSet(listOf(BOOLEAN, TRUE_ONLY)) + private val TEXT_TYPES: Set = HashSet(listOf(TEXT, LONG_TEXT, LETTER, COORDINATE, TIME, IMAGE)) + private val DATE_TYPES: Set = HashSet(listOf(DATE, DATETIME)) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt index 897eac07b9..87ad66a1bf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt @@ -1,37 +1,37 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators - -import org.hisp.dhis.android.core.arch.helpers.Result - -object DefaultValidator : ValueTypeValidator { - override fun validate(value: String): Result { - return Result.Success(value) - } -} +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result + +object DefaultValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return Result.Success(value) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt index e8acfe2533..00ceb74819 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/arch/helpers/ResultShould.kt @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.helpers - -import com.google.common.truth.Truth -import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator -import org.junit.Assert.fail -import org.junit.Test - -class ResultShould { - - private val validator = IntegerPositiveValidator - - @Test - fun `Should return the same value when succeeding using when`() { - val value = "5" - when (val result = validator.validate(value)) { - is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) - is Result.Failure -> fail() - } - } - - @Test - fun `Should return a failure when the validator fails`() { - val value = "-5" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerPositiveFailure.ValueIsNegative) - } - } - - @Test - fun `Should return the same value when succeeding using fold`() { - val value = "5" - validator.validate(value).fold( - onSuccess = { - Truth.assertThat(it).isEqualTo(value) - }, - onFailure = { - fail() - } - ) - } - - @Test - fun `Should succeed when entering the right value`() { - Truth.assertThat(validator.validate("5").succeeded).isTrue() - } -} +/* + * Copyright (c) 2004-2021, 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.core.arch.helpers + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure +import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator +import org.junit.Assert.fail +import org.junit.Test + +class ResultShould { + + private val validator = IntegerPositiveValidator + + @Test + fun `Should return the same value when succeeding using when`() { + val value = "5" + when (val result = validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + @Test + fun `Should return a failure when the validator fails`() { + val value = "-5" + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerPositiveFailure.ValueIsNegative) + } + } + + @Test + fun `Should return the same value when succeeding using fold`() { + val value = "5" + validator.validate(value).fold( + onSuccess = { + Truth.assertThat(it).isEqualTo(value) + }, + onFailure = { + fail() + } + ) + } + + @Test + fun `Should succeed when entering the right value`() { + Truth.assertThat(validator.validate("5").succeeded).isTrue() + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt index 41c20b4d7a..0e993ffb1f 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidatorGetterShould.kt @@ -1,49 +1,49 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators - -import com.google.common.truth.Truth -import org.hisp.dhis.android.core.arch.helpers.Result -import org.hisp.dhis.android.core.common.ValueType -import org.junit.Assert.fail -import org.junit.Test - -class ValueTypeValidatorGetterShould { - - private val valueType = ValueType.INTEGER_POSITIVE - - @Test - fun `Should return a valid value type validator`() { - val value = "5" - when (val result = valueType.validator.validate(value)) { - is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) - is Result.Failure -> fail() - } - } -} +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.ValueType +import org.junit.Assert.fail +import org.junit.Test + +class ValueTypeValidatorGetterShould { + + private val valueType = ValueType.INTEGER_POSITIVE + + @Test + fun `Should return a valid value type validator`() { + val value = "5" + when (val result = valueType.validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } +} From f34507b9487a62f5d397dabb5b2cc191a3d1b1e2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Apr 2021 13:49:23 +0200 Subject: [PATCH 026/308] [androsdk-1334] Refactor tests and Add IntegerZeroOrPositiveValidator --- .../dhis/android/core/common/ValueType.kt | 7 +-- .../failures/IntegerZeroOrPositiveFailure.kt | 34 ++++++++++++ .../IntegerZeroOrPositiveValidator.kt | 50 +++++++++++++++++ .../IntegerNegativeValidatorShould.kt | 31 ++--------- .../IntegerPositiveValidatorShould.kt | 55 +++++++++++++++++++ .../IntegerZeroOrPositiveValidatorShould.kt | 55 +++++++++++++++++++ .../validators/ValidatorShouldHelper.kt | 52 ++++++++++++++++++ 7 files changed, 253 insertions(+), 31 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index eaef7f3871..c7983ab0a5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -27,10 +27,7 @@ */ package org.hisp.dhis.android.core.common -import org.hisp.dhis.android.core.common.valuetype.validation.validators.DefaultValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerNegativeValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.IntegerPositiveValidator -import org.hisp.dhis.android.core.common.valuetype.validation.validators.ValueTypeValidator +import org.hisp.dhis.android.core.common.valuetype.validation.validators.* import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import java.util.* @@ -50,7 +47,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { INTEGER(Int::class.java, DefaultValidator), INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), - INTEGER_ZERO_OR_POSITIVE(Int::class.java, DefaultValidator), + INTEGER_ZERO_OR_POSITIVE(Int::class.java, IntegerZeroOrPositiveValidator), FILE_RESOURCE(String::class.java, DefaultValidator), COORDINATE(String::class.java, DefaultValidator), PHONE_NUMBER(String::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt new file mode 100644 index 0000000000..516f193adf --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class IntegerZeroOrPositiveFailure : Throwable() { + object NumberFormatException : IntegerZeroOrPositiveFailure() + object ValueIsNegative : IntegerZeroOrPositiveFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt new file mode 100644 index 0000000000..faeda55376 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerZeroOrPositiveFailure + +object IntegerZeroOrPositiveValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + val convertedValue = value.toInt() + when { + convertedValue < 0 -> { + Result.Failure(IntegerZeroOrPositiveFailure.ValueIsNegative) + } + else -> { + Result.Success(value) + } + } + } catch (e: NumberFormatException) { + Result.Failure(IntegerZeroOrPositiveFailure.NumberFormatException) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt index 658e61a1e6..7eba26b340 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt @@ -28,49 +28,28 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators -import com.google.common.truth.Truth -import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure -import org.junit.Assert.fail import org.junit.Test -class IntegerNegativeValidatorShould { - - private val validator = IntegerNegativeValidator +class IntegerNegativeValidatorShould : ValidatorShouldHelper(IntegerNegativeValidator) { @Test fun `Should return the same value when succeeding`() { - val value = "-15" - when (val result = validator.validate(value)) { - is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) - is Result.Failure -> fail() - } + valueShouldSuccess("-15") } @Test fun `Should fail with a value is positive exception when value is positive`() { - val value = "5" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsPositive) - } + valueShouldFail("5", IntegerNegativeFailure.ValueIsPositive) } @Test fun `Should fail with a value is zero exception when value is zero`() { - val value = "0" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.ValueIsZero) - } + valueShouldFail("0", IntegerNegativeFailure.ValueIsZero) } @Test fun `Should fail with a number format exception when value is malformed`() { - val value = "5fe2" - when (val result = validator.validate(value)) { - is Result.Success -> fail() - is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(IntegerNegativeFailure.NumberFormatException) - } + valueShouldFail("5fe2", IntegerNegativeFailure.NumberFormatException) } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt new file mode 100644 index 0000000000..b08acd045d --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure +import org.junit.Test + +class IntegerPositiveValidatorShould : ValidatorShouldHelper(IntegerPositiveValidator) { + + @Test + fun `Should return the same value when succeeding`() { + valueShouldSuccess("15") + } + + @Test + fun `Should fail with a value is negative exception when value is negative`() { + valueShouldFail("-5", IntegerPositiveFailure.ValueIsNegative) + } + + @Test + fun `Should fail with a value is zero exception when value is zero`() { + valueShouldFail("0", IntegerPositiveFailure.ValueIsZero) + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + valueShouldFail("5fe2", IntegerPositiveFailure.NumberFormatException) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt new file mode 100644 index 0000000000..2ec21d6d48 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerZeroOrPositiveFailure +import org.junit.Test + +class IntegerZeroOrPositiveValidatorShould : ValidatorShouldHelper(IntegerZeroOrPositiveValidator) { + + @Test + fun `Should success when passing a positive integer`() { + valueShouldSuccess("15") + } + + @Test + fun `Should success when passing a zero`() { + valueShouldSuccess("0") + } + + @Test + fun `Should fail with a value is negative exception when value is negative`() { + valueShouldFail("-5", IntegerZeroOrPositiveFailure.ValueIsNegative) + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + valueShouldFail("5fe2", IntegerZeroOrPositiveFailure.NumberFormatException) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt new file mode 100644 index 0000000000..3e813c8cab --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import com.google.common.truth.Truth +import org.hisp.dhis.android.core.arch.helpers.Result +import org.junit.Assert.fail + +open class ValidatorShouldHelper(v: ValueTypeValidator) { + + private val validator = v + + fun valueShouldSuccess(value: String) { + when (val result = validator.validate(value)) { + is Result.Success -> Truth.assertThat(result.value).isEqualTo(value) + is Result.Failure -> fail() + } + } + + fun valueShouldFail(value: String, failure: Throwable) { + when (val result = validator.validate(value)) { + is Result.Success -> fail() + is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(failure) + } + } +} From 48b3af04542962f081ccdf08f1f74845b3750b63 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Apr 2021 14:03:15 +0200 Subject: [PATCH 027/308] [androsdk-1334] Add IntegerValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/IntegerFailure.kt | 33 +++++++++++++ .../validation/validators/IntegerValidator.kt | 43 +++++++++++++++++ .../IntegerNegativeValidatorShould.kt | 2 +- .../IntegerPositiveValidatorShould.kt | 2 +- .../validators/IntegerValidatorShould.kt | 48 +++++++++++++++++++ .../IntegerZeroOrPositiveValidatorShould.kt | 6 +-- 7 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index c7983ab0a5..976ef046c3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -44,7 +44,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { NUMBER(Double::class.java, DefaultValidator), UNIT_INTERVAL(Double::class.java, DefaultValidator), PERCENTAGE(Double::class.java, DefaultValidator), - INTEGER(Int::class.java, DefaultValidator), + INTEGER(Int::class.java, IntegerValidator), INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), INTEGER_ZERO_OR_POSITIVE(Int::class.java, IntegerZeroOrPositiveValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt new file mode 100644 index 0000000000..5715da7d43 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class IntegerFailure : Throwable() { + object NumberFormatException : IntegerFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt new file mode 100644 index 0000000000..137f6592da --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerFailure + +object IntegerValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + value.toInt() + Result.Success(value) + } catch (e: NumberFormatException) { + Result.Failure(IntegerFailure.NumberFormatException) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt index 7eba26b340..e73d7f53eb 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt @@ -34,7 +34,7 @@ import org.junit.Test class IntegerNegativeValidatorShould : ValidatorShouldHelper(IntegerNegativeValidator) { @Test - fun `Should return the same value when succeeding`() { + fun `Should success when passing valid values`() { valueShouldSuccess("-15") } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt index b08acd045d..2f14620004 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt @@ -34,7 +34,7 @@ import org.junit.Test class IntegerPositiveValidatorShould : ValidatorShouldHelper(IntegerPositiveValidator) { @Test - fun `Should return the same value when succeeding`() { + fun `Should success when passing valid values`() { valueShouldSuccess("15") } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt new file mode 100644 index 0000000000..f762688a9c --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerFailure +import org.junit.Test + +class IntegerValidatorShould : ValidatorShouldHelper(IntegerValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("15") + valueShouldSuccess("-15") + valueShouldSuccess("0") + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + valueShouldFail("5fe2", IntegerFailure.NumberFormatException) + valueShouldFail("15.3", IntegerFailure.NumberFormatException) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt index 2ec21d6d48..a134dcede6 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt @@ -34,12 +34,8 @@ import org.junit.Test class IntegerZeroOrPositiveValidatorShould : ValidatorShouldHelper(IntegerZeroOrPositiveValidator) { @Test - fun `Should success when passing a positive integer`() { + fun `Should success when passing valid values`() { valueShouldSuccess("15") - } - - @Test - fun `Should success when passing a zero`() { valueShouldSuccess("0") } From 06604474983c121a94256511780ef43a5cc033f5 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Apr 2021 15:20:26 +0200 Subject: [PATCH 028/308] [androsdk-1334] Add PercentageValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/PercentageFailure.kt | 35 +++++++++++ .../validators/PercentageValidator.kt | 53 ++++++++++++++++ .../validators/PercentageValidatorShould.kt | 61 +++++++++++++++++++ 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PercentageFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 976ef046c3..1d4f8c7e7f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -43,7 +43,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { TIME(String::class.java, DefaultValidator), NUMBER(Double::class.java, DefaultValidator), UNIT_INTERVAL(Double::class.java, DefaultValidator), - PERCENTAGE(Double::class.java, DefaultValidator), + PERCENTAGE(Double::class.java, PercentageValidator), INTEGER(Int::class.java, IntegerValidator), INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PercentageFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PercentageFailure.kt new file mode 100644 index 0000000000..9aceb4e551 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PercentageFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class PercentageFailure : Throwable() { + object NumberFormatException : PercentageFailure() + object ValueGreaterThan100 : PercentageFailure() + object ValueIsNegative : PercentageFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt new file mode 100644 index 0000000000..916e2e654c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.PercentageFailure + +object PercentageValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + val convertedValue = value.toInt() + when { + convertedValue > 100 -> { + Result.Failure(PercentageFailure.ValueGreaterThan100) + } + convertedValue < 0 -> { + Result.Failure(PercentageFailure.ValueIsNegative) + } + else -> { + Result.Success(value) + } + } + } catch (e: NumberFormatException) { + Result.Failure(PercentageFailure.NumberFormatException) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt new file mode 100644 index 0000000000..f26f3e484c --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.PercentageFailure +import org.junit.Test + +class PercentageValidatorShould : ValidatorShouldHelper(PercentageValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("0") + valueShouldSuccess("3") + valueShouldSuccess("35") + valueShouldSuccess("100") + } + + @Test + fun `Should fail when the value is greater than 100`() { + valueShouldFail("101", PercentageFailure.ValueGreaterThan100) + valueShouldFail("345", PercentageFailure.ValueGreaterThan100) + } + + @Test + fun `Should fail with a value is zero exception when value is zero`() { + valueShouldFail("-12", PercentageFailure.ValueIsNegative) + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + valueShouldFail("sdf", PercentageFailure.NumberFormatException) + valueShouldFail("23,4", PercentageFailure.NumberFormatException) + valueShouldFail("23.4", PercentageFailure.NumberFormatException) + } +} From 1b9dd4162905cee68830c2d74053bd88a1e988d6 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Apr 2021 15:51:51 +0200 Subject: [PATCH 029/308] [androsdk-1334] Add TextValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/TextFailure.kt | 33 +++++++++++ .../validation/validators/TextValidator.kt | 42 ++++++++++++++ .../validators/TextValidatorShould.kt | 57 +++++++++++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TextFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 1d4f8c7e7f..555b330363 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -33,7 +33,7 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import java.util.* enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { - TEXT(String::class.java, DefaultValidator), + TEXT(String::class.java, TextValidator), LONG_TEXT(String::class.java, DefaultValidator), LETTER(String::class.java, DefaultValidator), BOOLEAN(Boolean::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TextFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TextFailure.kt new file mode 100644 index 0000000000..d9c05df377 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TextFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class TextFailure : Throwable() { + object TooLargeTextException : TextFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt new file mode 100644 index 0000000000..99e43ffb3b --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.TextFailure + +object TextValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return if (value.count() > 50000) { + Result.Failure(TextFailure.TooLargeTextException) + } else { + Result.Success(value) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt new file mode 100644 index 0000000000..1d99cc3ab9 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.TextFailure +import org.junit.Test + +class TextValidatorShould : ValidatorShouldHelper(TextValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("15") + valueShouldSuccess("0") + } + + @Test + fun `Should success when the string has exactly 50000 chars`() { + valueShouldSuccess(buildStringWithLength(50000)) + } + + @Test + fun `Should fail when the string has more than 50000 chars`() { + valueShouldFail(buildStringWithLength(50001), TextFailure.TooLargeTextException) + } + + private fun buildStringWithLength(stringLength: Int): String { + val builder = StringBuilder() + repeat(stringLength) { builder.append("a") } + return builder.toString() + } +} From c6406fa885138c263654f39013731fa3fc6de384 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Apr 2021 16:07:46 +0200 Subject: [PATCH 030/308] [androsdk-1334] Add LongTextValidator --- .../dhis/android/core/common/ValueType.kt | 12 ++++-- .../validation/failures/LongTextFailure.kt | 33 ++++++++++++++++ .../validators/LongTextValidator.kt | 38 ++++++++++++++++++ .../validators/LongTextValidatorShould.kt | 39 +++++++++++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LongTextFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 555b330363..f7215a6496 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -34,7 +34,7 @@ import java.util.* enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { TEXT(String::class.java, TextValidator), - LONG_TEXT(String::class.java, DefaultValidator), + LONG_TEXT(String::class.java, LongTextValidator), LETTER(String::class.java, DefaultValidator), BOOLEAN(Boolean::class.java, DefaultValidator), TRUE_ONLY(Boolean::class.java, DefaultValidator), @@ -76,10 +76,14 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { companion object { private val INTEGER_TYPES: Set = - HashSet(listOf(INTEGER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE)) + HashSet(listOf(INTEGER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE)) private val NUMERIC_TYPES: Set = - HashSet(listOf(INTEGER, NUMBER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE, - UNIT_INTERVAL, PERCENTAGE)) + HashSet( + listOf( + INTEGER, NUMBER, INTEGER_POSITIVE, INTEGER_NEGATIVE, INTEGER_ZERO_OR_POSITIVE, + UNIT_INTERVAL, PERCENTAGE + ) + ) private val BOOLEAN_TYPES: Set = HashSet(listOf(BOOLEAN, TRUE_ONLY)) private val TEXT_TYPES: Set = HashSet(listOf(TEXT, LONG_TEXT, LETTER, COORDINATE, TIME, IMAGE)) private val DATE_TYPES: Set = HashSet(listOf(DATE, DATETIME)) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LongTextFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LongTextFailure.kt new file mode 100644 index 0000000000..adba1bb8d6 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LongTextFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class LongTextFailure : Throwable() { + // Long texts do not need validation and cannot produce errors +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt new file mode 100644 index 0000000000..5a993d8454 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.LongTextFailure + +object LongTextValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return Result.Success(value) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt new file mode 100644 index 0000000000..82ade9b425 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.junit.Test + +class LongTextValidatorShould : ValidatorShouldHelper(LongTextValidator) { + + @Test + fun `Should success when passing any value`() { + valueShouldSuccess("This is a long text") + } +} From 00e727e1a7ac62fa54e57584319058a421e4f539 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Apr 2021 16:43:10 +0200 Subject: [PATCH 031/308] [androsdk-1334] Add LetterValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/LetterFailure.kt | 35 +++++++++++ .../validation/validators/LetterValidator.kt | 55 ++++++++++++++++++ .../validators/LetterValidatorShould.kt | 58 +++++++++++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LetterFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index f7215a6496..1eafae2c50 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -35,7 +35,7 @@ import java.util.* enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { TEXT(String::class.java, TextValidator), LONG_TEXT(String::class.java, LongTextValidator), - LETTER(String::class.java, DefaultValidator), + LETTER(String::class.java, LetterValidator), BOOLEAN(Boolean::class.java, DefaultValidator), TRUE_ONLY(Boolean::class.java, DefaultValidator), DATE(Date::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LetterFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LetterFailure.kt new file mode 100644 index 0000000000..f04b65f447 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/LetterFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class LetterFailure : Throwable() { + object StringIsNotALetterException : LetterFailure() + object MoreThanOneLetterException : LetterFailure() + object EmptyStringException : LetterFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt new file mode 100644 index 0000000000..975bcd1960 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.LetterFailure + +object LetterValidator : ValueTypeValidator { + + private val LETTER_PATTERN = "[a-zA-Z]".toRegex() + + override fun validate(value: String): Result { + val charArray = value.toCharArray() + return when { + charArray.isEmpty() -> { + Result.Failure(LetterFailure.EmptyStringException) + } + charArray.size > 1 -> { + Result.Failure(LetterFailure.MoreThanOneLetterException) + } + value.matches(LETTER_PATTERN) -> { + Result.Success(value) + } + else -> { + Result.Failure(LetterFailure.StringIsNotALetterException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt new file mode 100644 index 0000000000..c932b1ae67 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.LetterFailure +import org.junit.Test + +class LetterValidatorShould : ValidatorShouldHelper(LetterValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("a") + valueShouldSuccess("Z") + } + + @Test + fun `Should fail when passing an empty string`() { + valueShouldFail("", LetterFailure.EmptyStringException) + } + + @Test + fun `Should fail when passing a string with more than one char`() { + valueShouldFail("as", LetterFailure.MoreThanOneLetterException) + } + + @Test + fun `Should fail when passing chars that are not letters`() { + valueShouldFail("4", LetterFailure.StringIsNotALetterException) + valueShouldFail("ñ", LetterFailure.StringIsNotALetterException) + valueShouldFail("Á", LetterFailure.StringIsNotALetterException) + } +} From c9ee97d1979d1f00b1848f807b1569e80cd34e60 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Apr 2021 08:50:53 +0200 Subject: [PATCH 032/308] [androsdk-1334] Add BooleanValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/BooleanFailure.kt | 35 +++++++++++ .../validation/validators/BooleanValidator.kt | 52 +++++++++++++++++ .../validators/BooleanValidatorShould.kt | 58 +++++++++++++++++++ .../IntegerNegativeValidatorShould.kt | 2 +- .../IntegerPositiveValidatorShould.kt | 2 +- .../validators/IntegerValidatorShould.kt | 2 +- .../IntegerZeroOrPositiveValidatorShould.kt | 3 +- .../validators/LetterValidatorShould.kt | 2 +- .../validators/LongTextValidatorShould.kt | 3 +- .../validators/PercentageValidatorShould.kt | 2 +- .../validators/TextValidatorShould.kt | 2 +- .../validators/ValidatorShouldHelper.kt | 4 +- 13 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/BooleanFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 1eafae2c50..d4161623f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -36,7 +36,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { TEXT(String::class.java, TextValidator), LONG_TEXT(String::class.java, LongTextValidator), LETTER(String::class.java, LetterValidator), - BOOLEAN(Boolean::class.java, DefaultValidator), + BOOLEAN(Boolean::class.java, BooleanValidator), TRUE_ONLY(Boolean::class.java, DefaultValidator), DATE(Date::class.java, DefaultValidator), DATETIME(Date::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/BooleanFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/BooleanFailure.kt new file mode 100644 index 0000000000..4e7f786b18 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/BooleanFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class BooleanFailure : Throwable() { + object OneIsNotTrueException : BooleanFailure() + object ZeroIsNotFalseException : BooleanFailure() + object BooleanMalformedException : BooleanFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt new file mode 100644 index 0000000000..734a04238a --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.BooleanFailure + +object BooleanValidator : ValueTypeValidator { + + override fun validate(value: String): Result { + return when (value) { + "0" -> { + Result.Failure(BooleanFailure.ZeroIsNotFalseException) + } + "1" -> { + Result.Failure(BooleanFailure.OneIsNotTrueException) + } + "true", "false" -> { + Result.Success(value) + } + else -> { + Result.Failure(BooleanFailure.BooleanMalformedException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt new file mode 100644 index 0000000000..cf7f7e703f --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.BooleanFailure +import org.junit.Test + +class BooleanValidatorShould : ValidatorShouldHelper(BooleanValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("true") + valueShouldSuccess("false") + } + + @Test + fun `Should fail when passing zero as string`() { + valueShouldFail("0", BooleanFailure.ZeroIsNotFalseException) + } + + @Test + fun `Should fail when passing one as string`() { + valueShouldFail("1", BooleanFailure.OneIsNotTrueException) + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("asg", BooleanFailure.BooleanMalformedException) + valueShouldFail("", BooleanFailure.BooleanMalformedException) + } + +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt index e73d7f53eb..6735ca7a17 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidatorShould.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure import org.junit.Test -class IntegerNegativeValidatorShould : ValidatorShouldHelper(IntegerNegativeValidator) { +class IntegerNegativeValidatorShould : ValidatorShouldHelper(IntegerNegativeValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt index 2f14620004..d6856582b5 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidatorShould.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure import org.junit.Test -class IntegerPositiveValidatorShould : ValidatorShouldHelper(IntegerPositiveValidator) { +class IntegerPositiveValidatorShould : ValidatorShouldHelper(IntegerPositiveValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt index f762688a9c..6b096d4002 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorShould.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerFailure import org.junit.Test -class IntegerValidatorShould : ValidatorShouldHelper(IntegerValidator) { +class IntegerValidatorShould : ValidatorShouldHelper(IntegerValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt index a134dcede6..f042e21508 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt @@ -31,7 +31,8 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerZeroOrPositiveFailure import org.junit.Test -class IntegerZeroOrPositiveValidatorShould : ValidatorShouldHelper(IntegerZeroOrPositiveValidator) { +class IntegerZeroOrPositiveValidatorShould : + ValidatorShouldHelper(IntegerZeroOrPositiveValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt index c932b1ae67..2796694a74 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidatorShould.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.LetterFailure import org.junit.Test -class LetterValidatorShould : ValidatorShouldHelper(LetterValidator) { +class LetterValidatorShould : ValidatorShouldHelper(LetterValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt index 82ade9b425..a0b5a71def 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidatorShould.kt @@ -28,9 +28,10 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators +import org.hisp.dhis.android.core.common.valuetype.validation.failures.LongTextFailure import org.junit.Test -class LongTextValidatorShould : ValidatorShouldHelper(LongTextValidator) { +class LongTextValidatorShould : ValidatorShouldHelper(LongTextValidator) { @Test fun `Should success when passing any value`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt index f26f3e484c..f14d90d040 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidatorShould.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.PercentageFailure import org.junit.Test -class PercentageValidatorShould : ValidatorShouldHelper(PercentageValidator) { +class PercentageValidatorShould : ValidatorShouldHelper(PercentageValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt index 1d99cc3ab9..d69433066a 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidatorShould.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.common.valuetype.validation.failures.TextFailure import org.junit.Test -class TextValidatorShould : ValidatorShouldHelper(TextValidator) { +class TextValidatorShould : ValidatorShouldHelper(TextValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt index 3e813c8cab..c70ea2070d 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt @@ -32,7 +32,7 @@ import com.google.common.truth.Truth import org.hisp.dhis.android.core.arch.helpers.Result import org.junit.Assert.fail -open class ValidatorShouldHelper(v: ValueTypeValidator) { +open class ValidatorShouldHelper(v: ValueTypeValidator) { private val validator = v @@ -43,7 +43,7 @@ open class ValidatorShouldHelper(v: ValueTypeValidator) { } } - fun valueShouldFail(value: String, failure: Throwable) { + fun valueShouldFail(value: String, failure: F) { when (val result = validator.validate(value)) { is Result.Success -> fail() is Result.Failure -> Truth.assertThat(result.failure).isEqualTo(failure) From b36502592c2c3099eb98ecfcafb849a2d8568882 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Apr 2021 08:56:11 +0200 Subject: [PATCH 033/308] [androsdk-1334] Add TrueOnlyValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/TrueOnlyFailure.kt | 35 ++++++++++++ .../validators/TrueOnlyValidator.kt | 52 +++++++++++++++++ .../validators/BooleanValidatorShould.kt | 1 - .../IntegerZeroOrPositiveValidatorShould.kt | 2 +- .../validators/TrueOnlyValidatorShould.kt | 56 +++++++++++++++++++ .../validators/ValidatorShouldHelper.kt | 2 +- 7 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TrueOnlyFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index d4161623f1..3c3e05fb93 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -37,7 +37,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { LONG_TEXT(String::class.java, LongTextValidator), LETTER(String::class.java, LetterValidator), BOOLEAN(Boolean::class.java, BooleanValidator), - TRUE_ONLY(Boolean::class.java, DefaultValidator), + TRUE_ONLY(Boolean::class.java, TrueOnlyValidator), DATE(Date::class.java, DefaultValidator), DATETIME(Date::class.java, DefaultValidator), TIME(String::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TrueOnlyFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TrueOnlyFailure.kt new file mode 100644 index 0000000000..1112c01fff --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TrueOnlyFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class TrueOnlyFailure : Throwable() { + object OneIsNotTrueException : TrueOnlyFailure() + object FalseIsNotAValidValueException : TrueOnlyFailure() + object BooleanMalformedException : TrueOnlyFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt new file mode 100644 index 0000000000..b145ad640f --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.TrueOnlyFailure + +object TrueOnlyValidator : ValueTypeValidator { + + override fun validate(value: String): Result { + return when (value) { + "false" -> { + Result.Failure(TrueOnlyFailure.FalseIsNotAValidValueException) + } + "1" -> { + Result.Failure(TrueOnlyFailure.OneIsNotTrueException) + } + "true" -> { + Result.Success(value) + } + else -> { + Result.Failure(TrueOnlyFailure.BooleanMalformedException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt index cf7f7e703f..30f0d40fbe 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidatorShould.kt @@ -54,5 +54,4 @@ class BooleanValidatorShould : ValidatorShouldHelper(BooleanVali valueShouldFail("asg", BooleanFailure.BooleanMalformedException) valueShouldFail("", BooleanFailure.BooleanMalformedException) } - } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt index f042e21508..db4615e56d 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt @@ -32,7 +32,7 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerZe import org.junit.Test class IntegerZeroOrPositiveValidatorShould : - ValidatorShouldHelper(IntegerZeroOrPositiveValidator) { + ValidatorShouldHelper(IntegerZeroOrPositiveValidator) { @Test fun `Should success when passing valid values`() { diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidatorShould.kt new file mode 100644 index 0000000000..415893140e --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidatorShould.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.TrueOnlyFailure +import org.junit.Test + +class TrueOnlyValidatorShould : ValidatorShouldHelper(TrueOnlyValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("true") + } + + @Test + fun `Should fail when passing false as string`() { + valueShouldFail("false", TrueOnlyFailure.FalseIsNotAValidValueException) + } + + @Test + fun `Should fail when passing one as string`() { + valueShouldFail("1", TrueOnlyFailure.OneIsNotTrueException) + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("asg", TrueOnlyFailure.BooleanMalformedException) + valueShouldFail("", TrueOnlyFailure.BooleanMalformedException) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt index c70ea2070d..1f61ec816a 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt @@ -32,7 +32,7 @@ import com.google.common.truth.Truth import org.hisp.dhis.android.core.arch.helpers.Result import org.junit.Assert.fail -open class ValidatorShouldHelper(v: ValueTypeValidator) { +open class ValidatorShouldHelper(v: ValueTypeValidator) { private val validator = v From adce8811e97367b4f9617998241d0e34d047600f Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Apr 2021 10:25:00 +0200 Subject: [PATCH 034/308] [androsdk-1334] Add TimeValidator --- .../dhis/android/core/common/ValueType.kt | 4 +- .../validation/failures/DateFailure.kt | 33 +++++++++ .../validation/failures/TimeFailure.kt | 33 +++++++++ .../validation/validators/BooleanValidator.kt | 2 +- .../validation/validators/DateValidator.kt | 46 ++++++++++++ .../validation/validators/DefaultValidator.kt | 2 +- .../validators/IntegerNegativeValidator.kt | 2 +- .../validators/IntegerPositiveValidator.kt | 2 +- .../validation/validators/IntegerValidator.kt | 2 +- .../IntegerZeroOrPositiveValidator.kt | 2 +- .../validation/validators/LetterValidator.kt | 2 +- .../validators/LongTextValidator.kt | 2 +- .../validators/PercentageValidator.kt | 2 +- .../validation/validators/TextValidator.kt | 2 +- .../validation/validators/TimeValidator.kt | 48 +++++++++++++ .../validators/TrueOnlyValidator.kt | 2 +- .../validators/ValueTypeValidator.kt | 4 +- .../validators/TimeValidatorShould.kt | 70 +++++++++++++++++++ .../validators/ValidatorShouldHelper.kt | 2 +- 19 files changed, 246 insertions(+), 16 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TimeFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 3c3e05fb93..a8df989479 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -32,13 +32,13 @@ import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import java.util.* -enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator) { +enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) { TEXT(String::class.java, TextValidator), LONG_TEXT(String::class.java, LongTextValidator), LETTER(String::class.java, LetterValidator), BOOLEAN(Boolean::class.java, BooleanValidator), TRUE_ONLY(Boolean::class.java, TrueOnlyValidator), - DATE(Date::class.java, DefaultValidator), + DATE(Date::class.java, DateValidator), DATETIME(Date::class.java, DefaultValidator), TIME(String::class.java, DefaultValidator), NUMBER(Double::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateFailure.kt new file mode 100644 index 0000000000..ec07cf21a7 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class DateFailure : Throwable() { + object ParseException : DateFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TimeFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TimeFailure.kt new file mode 100644 index 0000000000..aa3fb58e59 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/TimeFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class TimeFailure : Throwable() { + object ParseException : TimeFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt index 734a04238a..bee08e9d5d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/BooleanValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.BooleanFailure -object BooleanValidator : ValueTypeValidator { +object BooleanValidator : ValueTypeValidator { override fun validate(value: String): Result { return when (value) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt new file mode 100644 index 0000000000..e96d9511a6 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.DateUtils +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.DateFailure +import java.text.ParseException + +object DateValidator : ValueTypeValidator { + + override fun validate(value: String): Result { + return try { + DateUtils.DATE_FORMAT.parse(value) + Result.Success(value) + } catch (e: ParseException) { + Result.Failure(DateFailure.ParseException) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt index 87ad66a1bf..29c678c2a9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt @@ -30,7 +30,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result -object DefaultValidator : ValueTypeValidator { +object DefaultValidator : ValueTypeValidator { override fun validate(value: String): Result { return Result.Success(value) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt index 288668d6f4..76eef417d6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure -object IntegerNegativeValidator : ValueTypeValidator { +object IntegerNegativeValidator : ValueTypeValidator { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt index 84d9821a14..03456ff586 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure -object IntegerPositiveValidator : ValueTypeValidator { +object IntegerPositiveValidator : ValueTypeValidator { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt index 137f6592da..f6bf851e67 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerFailure -object IntegerValidator : ValueTypeValidator { +object IntegerValidator : ValueTypeValidator { override fun validate(value: String): Result { return try { value.toInt() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt index faeda55376..55cfe9eab5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerZeroOrPositiveFailure -object IntegerZeroOrPositiveValidator : ValueTypeValidator { +object IntegerZeroOrPositiveValidator : ValueTypeValidator { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt index 975bcd1960..fe587712cc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LetterValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.LetterFailure -object LetterValidator : ValueTypeValidator { +object LetterValidator : ValueTypeValidator { private val LETTER_PATTERN = "[a-zA-Z]".toRegex() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt index 5a993d8454..980784d165 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/LongTextValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.LongTextFailure -object LongTextValidator : ValueTypeValidator { +object LongTextValidator : ValueTypeValidator { override fun validate(value: String): Result { return Result.Success(value) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt index 916e2e654c..e4a8cb8fbd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PercentageValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.PercentageFailure -object PercentageValidator : ValueTypeValidator { +object PercentageValidator : ValueTypeValidator { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt index 99e43ffb3b..43dd4354cc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.TextFailure -object TextValidator : ValueTypeValidator { +object TextValidator : ValueTypeValidator { override fun validate(value: String): Result { return if (value.count() > 50000) { Result.Failure(TextFailure.TooLargeTextException) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidator.kt new file mode 100644 index 0000000000..dcf8b3bd07 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidator.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.TimeFailure + +object TimeValidator : ValueTypeValidator { + + private val TIME_PATTERN = "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]\$".toRegex() + + override fun validate(value: String): Result { + return when { + value.matches(TIME_PATTERN) -> { + Result.Success(value) + } + else -> { + Result.Failure(TimeFailure.ParseException) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt index b145ad640f..5882d69cb1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TrueOnlyValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.TrueOnlyFailure -object TrueOnlyValidator : ValueTypeValidator { +object TrueOnlyValidator : ValueTypeValidator { override fun validate(value: String): Result { return when (value) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt index 08194f6b11..35503412de 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt @@ -30,6 +30,6 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result -interface ValueTypeValidator { - fun validate(value: String): Result +interface ValueTypeValidator { + fun validate(value: String): Result } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidatorShould.kt new file mode 100644 index 0000000000..eb014274a8 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TimeValidatorShould.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.TimeFailure +import org.junit.Test + +class TimeValidatorShould : ValidatorShouldHelper(TimeValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("00:00") + valueShouldSuccess("0:00") + valueShouldSuccess("02:20") + valueShouldSuccess("2:20") + valueShouldSuccess("11:59") + valueShouldSuccess("12:00") + valueShouldSuccess("12:59") + valueShouldSuccess("23:59") + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("", TimeFailure.ParseException) + valueShouldFail("sdf", TimeFailure.ParseException) + valueShouldFail("00", TimeFailure.ParseException) + valueShouldFail("0:", TimeFailure.ParseException) + valueShouldFail(":0", TimeFailure.ParseException) + valueShouldFail(":", TimeFailure.ParseException) + valueShouldFail("2", TimeFailure.ParseException) + valueShouldFail("23", TimeFailure.ParseException) + valueShouldFail("24", TimeFailure.ParseException) + valueShouldFail("08:85", TimeFailure.ParseException) + valueShouldFail("26:25", TimeFailure.ParseException) + valueShouldFail("-05:25", TimeFailure.ParseException) + valueShouldFail("-00:00", TimeFailure.ParseException) + valueShouldFail("-00:00", TimeFailure.ParseException) + valueShouldFail("00:1985", TimeFailure.ParseException) + valueShouldFail("24:00", TimeFailure.ParseException) + valueShouldFail("02:2", TimeFailure.ParseException) + valueShouldFail("2:2", TimeFailure.ParseException) + valueShouldFail("0:0", TimeFailure.ParseException) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt index 1f61ec816a..3fb6f0d668 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValidatorShouldHelper.kt @@ -32,7 +32,7 @@ import com.google.common.truth.Truth import org.hisp.dhis.android.core.arch.helpers.Result import org.junit.Assert.fail -open class ValidatorShouldHelper(v: ValueTypeValidator) { +open class ValidatorShouldHelper(v: ValueTypeValidator) { private val validator = v From 18f7324fc08e575a7df7e4a857f188918686cb4d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Apr 2021 12:03:38 +0200 Subject: [PATCH 035/308] [androsdk-1334] Add NumberValidator --- .../dhis/android/core/common/ValueType.kt | 4 +- .../validation/failures/NumberFailure.kt | 34 +++++++++ .../validation/validators/NumberValidator.kt | 50 +++++++++++++ .../validators/NumberValidatorShould.kt | 72 +++++++++++++++++++ 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/NumberFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index a8df989479..d26bacebe2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -40,8 +40,8 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) TRUE_ONLY(Boolean::class.java, TrueOnlyValidator), DATE(Date::class.java, DateValidator), DATETIME(Date::class.java, DefaultValidator), - TIME(String::class.java, DefaultValidator), - NUMBER(Double::class.java, DefaultValidator), + TIME(String::class.java, TimeValidator), + NUMBER(Double::class.java, NumberValidator), UNIT_INTERVAL(Double::class.java, DefaultValidator), PERCENTAGE(Double::class.java, PercentageValidator), INTEGER(Int::class.java, IntegerValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/NumberFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/NumberFailure.kt new file mode 100644 index 0000000000..681cdd7fda --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/NumberFailure.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class NumberFailure : Throwable() { + object ScientificNotationException : NumberFailure() + object NumberFormatException : NumberFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt new file mode 100644 index 0000000000..47e756b045 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.NumberFailure + +object NumberValidator : ValueTypeValidator { + + private val SCIENTIFIC_NOTATION_PATTERN = "[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)".toRegex() + + override fun validate(value: String): Result { + return try { + value.toDouble() + if (value.matches(SCIENTIFIC_NOTATION_PATTERN)) { + Result.Failure(NumberFailure.ScientificNotationException) + } else { + Result.Success(value) + } + } catch (e: NumberFormatException) { + Result.Failure(NumberFailure.NumberFormatException) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt new file mode 100644 index 0000000000..60bd529059 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.NumberFailure +import org.junit.Test + +class NumberValidatorShould : ValidatorShouldHelper(NumberValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("0") + valueShouldSuccess("4") + valueShouldSuccess("+4") + valueShouldSuccess("254.3") + valueShouldSuccess("98.000005") + valueShouldSuccess("0000005.20") + valueShouldSuccess("+0003") + valueShouldSuccess("-6.299") + } + + @Test + fun `Should fail when passing scientific notation values`() { + valueShouldFail("3e-01", NumberFailure.ScientificNotationException) + valueShouldFail("3e-1", NumberFailure.ScientificNotationException) + valueShouldFail("12e10", NumberFailure.ScientificNotationException) + valueShouldFail("3.2e23", NumberFailure.ScientificNotationException) + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("", NumberFailure.NumberFormatException) + valueShouldFail("sdf", NumberFailure.NumberFormatException) + valueShouldFail("254,3", NumberFailure.NumberFormatException) + valueShouldFail("25.035,21", NumberFailure.NumberFormatException) + valueShouldFail("25,035.21", NumberFailure.NumberFormatException) + valueShouldFail("10:45", NumberFailure.NumberFormatException) + valueShouldFail("10a", NumberFailure.NumberFormatException) + valueShouldFail("10USD", NumberFailure.NumberFormatException) + valueShouldFail("A1.23", NumberFailure.NumberFormatException) + valueShouldFail("π", NumberFailure.NumberFormatException) + valueShouldFail("ln(2)", NumberFailure.NumberFormatException) + valueShouldFail("2/3", NumberFailure.NumberFormatException) + valueShouldFail("37.e88", NumberFailure.NumberFormatException) + } +} From 82513b8f5b307764675a3f0d5eb077f7e3c64b37 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 16 Apr 2021 14:42:46 +0200 Subject: [PATCH 036/308] [androsdk-1334] Add IntegerOverflow validation --- .../validation/failures/IntegerFailure.kt | 1 + .../failures/IntegerNegativeFailure.kt | 1 + .../failures/IntegerPositiveFailure.kt | 1 + .../failures/IntegerZeroOrPositiveFailure.kt | 1 + .../validators/IntegerNegativeValidator.kt | 5 ++- .../validators/IntegerPositiveValidator.kt | 8 +++- .../validation/validators/IntegerValidator.kt | 4 +- .../validators/IntegerValidatorBase.kt | 45 +++++++++++++++++++ .../IntegerZeroOrPositiveValidator.kt | 5 ++- .../IntegerNegativeValidatorShould.kt | 7 +++ .../IntegerPositiveValidatorShould.kt | 7 +++ .../validators/IntegerValidatorShould.kt | 8 ++++ .../IntegerZeroOrPositiveValidatorShould.kt | 7 +++ .../validators/NumberValidatorShould.kt | 2 +- 14 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorBase.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt index 5715da7d43..c3367d644c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerFailure.kt @@ -30,4 +30,5 @@ package org.hisp.dhis.android.core.common.valuetype.validation.failures sealed class IntegerFailure : Throwable() { object NumberFormatException : IntegerFailure() + object IntegerOverflow : IntegerFailure() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt index 3c3e8dec3c..561b523538 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerNegativeFailure.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.failures sealed class IntegerNegativeFailure : Throwable() { object NumberFormatException : IntegerNegativeFailure() + object IntegerOverflow : IntegerNegativeFailure() object ValueIsZero : IntegerNegativeFailure() object ValueIsPositive : IntegerNegativeFailure() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt index 310c66ac35..ff3a4d2cc8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerPositiveFailure.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.failures sealed class IntegerPositiveFailure : Throwable() { object NumberFormatException : IntegerPositiveFailure() + object IntegerOverflow : IntegerPositiveFailure() object ValueIsZero : IntegerPositiveFailure() object ValueIsNegative : IntegerPositiveFailure() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt index 516f193adf..54114c16bd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/IntegerZeroOrPositiveFailure.kt @@ -30,5 +30,6 @@ package org.hisp.dhis.android.core.common.valuetype.validation.failures sealed class IntegerZeroOrPositiveFailure : Throwable() { object NumberFormatException : IntegerZeroOrPositiveFailure() + object IntegerOverflow : IntegerZeroOrPositiveFailure() object ValueIsNegative : IntegerZeroOrPositiveFailure() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt index 76eef417d6..ce6bf6fa17 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerNegativeFailure -object IntegerNegativeValidator : ValueTypeValidator { +object IntegerNegativeValidator : IntegerValidatorBase() { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() @@ -47,7 +47,8 @@ object IntegerNegativeValidator : ValueTypeValidator { } } } catch (e: NumberFormatException) { - Result.Failure(IntegerNegativeFailure.NumberFormatException) + catchOverflowFailure(value, IntegerNegativeFailure.IntegerOverflow, + IntegerNegativeFailure.NumberFormatException) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt index 03456ff586..3bb924d09c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerPositiveFailure -object IntegerPositiveValidator : ValueTypeValidator { +object IntegerPositiveValidator : IntegerValidatorBase() { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() @@ -42,12 +42,16 @@ object IntegerPositiveValidator : ValueTypeValidator { convertedValue < 0 -> { Result.Failure(IntegerPositiveFailure.ValueIsNegative) } + convertedValue < 0 -> { + Result.Failure(IntegerPositiveFailure.ValueIsNegative) + } else -> { Result.Success(value) } } } catch (e: NumberFormatException) { - Result.Failure(IntegerPositiveFailure.NumberFormatException) + catchOverflowFailure(value, IntegerPositiveFailure.IntegerOverflow, + IntegerPositiveFailure.NumberFormatException) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt index f6bf851e67..d0e91d562a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidator.kt @@ -31,13 +31,13 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerFailure -object IntegerValidator : ValueTypeValidator { +object IntegerValidator : IntegerValidatorBase() { override fun validate(value: String): Result { return try { value.toInt() Result.Success(value) } catch (e: NumberFormatException) { - Result.Failure(IntegerFailure.NumberFormatException) + catchOverflowFailure(value, IntegerFailure.IntegerOverflow, IntegerFailure.NumberFormatException) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorBase.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorBase.kt new file mode 100644 index 0000000000..efe23bc9c0 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerValidatorBase.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result + +abstract class IntegerValidatorBase : ValueTypeValidator { + fun catchOverflowFailure(value: String, overflowFailure: T, formatFailure: T): Result { + return try { + val convertedValue = value.toLong() + if (convertedValue > Integer.MAX_VALUE || convertedValue < Integer.MIN_VALUE) { + return Result.Failure(overflowFailure) + } + Result.Failure(formatFailure) + } catch (e: NumberFormatException) { + Result.Failure(formatFailure) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt index 55cfe9eab5..8f34c7b665 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt @@ -31,7 +31,7 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.IntegerZeroOrPositiveFailure -object IntegerZeroOrPositiveValidator : ValueTypeValidator { +object IntegerZeroOrPositiveValidator : IntegerValidatorBase() { override fun validate(value: String): Result { return try { val convertedValue = value.toInt() @@ -44,7 +44,8 @@ object IntegerZeroOrPositiveValidator : ValueTypeValidator(IntegerVali valueShouldSuccess("15") valueShouldSuccess("-15") valueShouldSuccess("0") + valueShouldSuccess(Integer.MAX_VALUE.toString()) + valueShouldSuccess(Integer.MIN_VALUE.toString()) + } + + @Test + fun `Should fail with a integer overflow exception when value is too big`() { + valueShouldFail("2147483648", IntegerFailure.IntegerOverflow) + valueShouldFail("-2147483649", IntegerFailure.IntegerOverflow) } @Test diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt index db4615e56d..b1f43280eb 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidatorShould.kt @@ -38,6 +38,7 @@ class IntegerZeroOrPositiveValidatorShould : fun `Should success when passing valid values`() { valueShouldSuccess("15") valueShouldSuccess("0") + valueShouldSuccess(Integer.MAX_VALUE.toString()) } @Test @@ -45,6 +46,12 @@ class IntegerZeroOrPositiveValidatorShould : valueShouldFail("-5", IntegerZeroOrPositiveFailure.ValueIsNegative) } + @Test + fun `Should fail with a integer overflow exception when value is too big`() { + valueShouldFail("2147483648", IntegerZeroOrPositiveFailure.IntegerOverflow) + valueShouldFail("-2147483649", IntegerZeroOrPositiveFailure.IntegerOverflow) + } + @Test fun `Should fail with a number format exception when value is malformed`() { valueShouldFail("5fe2", IntegerZeroOrPositiveFailure.NumberFormatException) diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt index 60bd529059..5a19281263 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidatorShould.kt @@ -51,6 +51,7 @@ class NumberValidatorShould : ValidatorShouldHelper(NumberValidat valueShouldFail("3e-1", NumberFailure.ScientificNotationException) valueShouldFail("12e10", NumberFailure.ScientificNotationException) valueShouldFail("3.2e23", NumberFailure.ScientificNotationException) + valueShouldFail("37.e88", NumberFailure.ScientificNotationException) } @Test @@ -67,6 +68,5 @@ class NumberValidatorShould : ValidatorShouldHelper(NumberValidat valueShouldFail("π", NumberFailure.NumberFormatException) valueShouldFail("ln(2)", NumberFailure.NumberFormatException) valueShouldFail("2/3", NumberFailure.NumberFormatException) - valueShouldFail("37.e88", NumberFailure.NumberFormatException) } } From de8172234b36a77a22d66266b336872b26bb2656 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 16 Apr 2021 16:30:58 +0200 Subject: [PATCH 037/308] [androsdk-1334] Fix dateValidator --- .../validation/validators/DateValidator.kt | 16 +++--- .../validators/DateValidatorShould.kt | 57 +++++++++++++++++++ 2 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt index e96d9511a6..21b211785e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidator.kt @@ -28,19 +28,21 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators -import org.hisp.dhis.android.core.arch.helpers.DateUtils import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.DateFailure -import java.text.ParseException object DateValidator : ValueTypeValidator { + private val DATE_PATTERN = "^\\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])\$".toRegex() + override fun validate(value: String): Result { - return try { - DateUtils.DATE_FORMAT.parse(value) - Result.Success(value) - } catch (e: ParseException) { - Result.Failure(DateFailure.ParseException) + return when (value.matches(DATE_PATTERN)) { + true -> { + Result.Success(value) + } + else -> { + Result.Failure(DateFailure.ParseException) + } } } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidatorShould.kt new file mode 100644 index 0000000000..77a573be90 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateValidatorShould.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.DateFailure +import org.junit.Test + +class DateValidatorShould : ValidatorShouldHelper(DateValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("2021-04-14") + valueShouldSuccess("0001-01-01") + valueShouldSuccess("9999-12-31") + valueShouldSuccess("0001-01-1") + valueShouldSuccess("0001-1-1") + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("", DateFailure.ParseException) + valueShouldFail("asd", DateFailure.ParseException) + valueShouldFail("-5221-01-14", DateFailure.ParseException) + valueShouldFail("5221-01-14-", DateFailure.ParseException) + valueShouldFail("2021/01/10", DateFailure.ParseException) + valueShouldFail("2021-01-94", DateFailure.ParseException) + valueShouldFail("2021-33-04", DateFailure.ParseException) + valueShouldFail("2021-00-04", DateFailure.ParseException) + valueShouldFail("2021-02-00", DateFailure.ParseException) + } +} From 43a414877555f14cbff5ce63d9e2fcb30124db26 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 16 Apr 2021 16:51:46 +0200 Subject: [PATCH 038/308] [androsdk-1334] Add DateTimeValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/DateTimeFailure.kt | 33 ++++++++++ .../validators/DateTimeValidator.kt | 49 +++++++++++++++ .../validators/DateTimeValidatorShould.kt | 60 +++++++++++++++++++ 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateTimeFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index d26bacebe2..c8288621da 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -39,7 +39,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) BOOLEAN(Boolean::class.java, BooleanValidator), TRUE_ONLY(Boolean::class.java, TrueOnlyValidator), DATE(Date::class.java, DateValidator), - DATETIME(Date::class.java, DefaultValidator), + DATETIME(Date::class.java, DateTimeValidator), TIME(String::class.java, TimeValidator), NUMBER(Double::class.java, NumberValidator), UNIT_INTERVAL(Double::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateTimeFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateTimeFailure.kt new file mode 100644 index 0000000000..4f1642b507 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/DateTimeFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class DateTimeFailure : Throwable() { + object ParseException : DateTimeFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt new file mode 100644 index 0000000000..62d3a007a0 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.DateTimeFailure + +object DateTimeValidator : ValueTypeValidator { + + private val DATE_TIME_PATTERN = + "^(\\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01]))T(([0-1]?[0-9]|2[0-3]):[0-5][0-9])\$".toRegex() + + override fun validate(value: String): Result { + return when (value.matches(DATE_TIME_PATTERN)) { + true -> { + Result.Success(value) + } + else -> { + Result.Failure(DateTimeFailure.ParseException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidatorShould.kt new file mode 100644 index 0000000000..df652cdbb4 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidatorShould.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.DateTimeFailure +import org.junit.Test + +class DateTimeValidatorShould : ValidatorShouldHelper(DateTimeValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("2021-04-15T23:59") + valueShouldSuccess("0000-04-15T23:59") + valueShouldSuccess("1995-1-1T1:01") + valueShouldSuccess("0004-1-1T1:01") + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("", DateTimeFailure.ParseException) + valueShouldFail("asd", DateTimeFailure.ParseException) + valueShouldFail("12021-04-15T23:59", DateTimeFailure.ParseException) + valueShouldFail("2021-40-15T23:59", DateTimeFailure.ParseException) + valueShouldFail("2021-04-80T25:59", DateTimeFailure.ParseException) + valueShouldFail("2021-04-15T23:70", DateTimeFailure.ParseException) + valueShouldFail("2021-00-15T23:20", DateTimeFailure.ParseException) + valueShouldFail("2021-01-00T23:20", DateTimeFailure.ParseException) + valueShouldFail("2021-01-02N23:20", DateTimeFailure.ParseException) + valueShouldFail("-2021-04-15T23:59", DateTimeFailure.ParseException) + valueShouldFail("-0000-04-15T23:59", DateTimeFailure.ParseException) + valueShouldFail("2021-04-15T23:59-", DateTimeFailure.ParseException) + valueShouldFail("2021/04/15T23:59", DateTimeFailure.ParseException) + } +} From 723d4f42d061efb7d77d25645febe09d57bca43f Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Apr 2021 15:00:21 +0200 Subject: [PATCH 039/308] [androsdk-1334] Add UnitIntervalValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../failures/UnitIntervalFailure.kt | 36 ++++++++++ .../validation/validators/NumberValidator.kt | 2 +- .../validators/UnitIntervalValidator.kt | 57 ++++++++++++++++ .../validators/UnitIntervalValidatorShould.kt | 68 +++++++++++++++++++ 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UnitIntervalFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index c8288621da..be9a8c8a6d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -42,7 +42,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) DATETIME(Date::class.java, DateTimeValidator), TIME(String::class.java, TimeValidator), NUMBER(Double::class.java, NumberValidator), - UNIT_INTERVAL(Double::class.java, DefaultValidator), + UNIT_INTERVAL(Double::class.java, UnitIntervalValidator), PERCENTAGE(Double::class.java, PercentageValidator), INTEGER(Int::class.java, IntegerValidator), INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UnitIntervalFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UnitIntervalFailure.kt new file mode 100644 index 0000000000..90e8ed6061 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UnitIntervalFailure.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class UnitIntervalFailure : Throwable() { + object ScientificNotationException : UnitIntervalFailure() + object NumberFormatException : UnitIntervalFailure() + object GreaterThanOneException : UnitIntervalFailure() + object SmallerThanZeroException : UnitIntervalFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt index 47e756b045..312c54d6be 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/NumberValidator.kt @@ -33,7 +33,7 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.NumberFai object NumberValidator : ValueTypeValidator { - private val SCIENTIFIC_NOTATION_PATTERN = "[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)".toRegex() + val SCIENTIFIC_NOTATION_PATTERN = "[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)".toRegex() override fun validate(value: String): Result { return try { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidator.kt new file mode 100644 index 0000000000..606a4d1f4e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidator.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.UnitIntervalFailure + +object UnitIntervalValidator : ValueTypeValidator { + + override fun validate(value: String): Result { + return try { + val convertedValue = value.toDouble() + when { + value.matches(NumberValidator.SCIENTIFIC_NOTATION_PATTERN) -> { + Result.Failure(UnitIntervalFailure.ScientificNotationException) + } + convertedValue > 1 -> { + Result.Failure(UnitIntervalFailure.GreaterThanOneException) + } + convertedValue < 0 -> { + Result.Failure(UnitIntervalFailure.SmallerThanZeroException) + } + else -> { + Result.Success(value) + } + } + } catch (e: NumberFormatException) { + Result.Failure(UnitIntervalFailure.NumberFormatException) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidatorShould.kt new file mode 100644 index 0000000000..6ac8bd3320 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UnitIntervalValidatorShould.kt @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.UnitIntervalFailure +import org.junit.Test + +class UnitIntervalValidatorShould : ValidatorShouldHelper(UnitIntervalValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("0") + valueShouldSuccess("0.2") + valueShouldSuccess("0.6666666666") + valueShouldSuccess("1") + } + + @Test + fun `Should fail when passing scientific notation values`() { + valueShouldFail("3e-01", UnitIntervalFailure.ScientificNotationException) + } + + @Test + fun `Should fail when passing values greater than one`() { + valueShouldFail("20", UnitIntervalFailure.GreaterThanOneException) + valueShouldFail("1.0001", UnitIntervalFailure.GreaterThanOneException) + } + + @Test + fun `Should fail when passing values smaller than zero`() { + valueShouldFail("-0.0001", UnitIntervalFailure.SmallerThanZeroException) + valueShouldFail("-15", UnitIntervalFailure.SmallerThanZeroException) + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("", UnitIntervalFailure.NumberFormatException) + valueShouldFail("sdf", UnitIntervalFailure.NumberFormatException) + valueShouldFail("254,3", UnitIntervalFailure.NumberFormatException) + valueShouldFail("25.035,21", UnitIntervalFailure.NumberFormatException) + } +} From dda3a10a3b4cb93f7bebcc34f478dfa460455cf2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Apr 2021 16:07:19 +0200 Subject: [PATCH 040/308] [androsdk-1334] Add CoordinateValidator --- .../dhis/android/core/common/ValueType.kt | 2 +- .../validation/failures/CoordinateFailure.kt | 33 ++++++++++ .../validators/CoordinateValidator.kt | 50 ++++++++++++++++ .../validators/CoordinateValidatorShould.kt | 60 +++++++++++++++++++ 4 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/CoordinateFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index be9a8c8a6d..04c4d425db 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -49,7 +49,7 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), INTEGER_ZERO_OR_POSITIVE(Int::class.java, IntegerZeroOrPositiveValidator), FILE_RESOURCE(String::class.java, DefaultValidator), - COORDINATE(String::class.java, DefaultValidator), + COORDINATE(String::class.java, CoordinateValidator), PHONE_NUMBER(String::class.java, DefaultValidator), EMAIL(String::class.java, DefaultValidator), USERNAME(String::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/CoordinateFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/CoordinateFailure.kt new file mode 100644 index 0000000000..c23b438fc2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/CoordinateFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class CoordinateFailure : Throwable() { + object CoordinateMalformedException : CoordinateFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt new file mode 100644 index 0000000000..c3277a2e2d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.CoordinateFailure + +object CoordinateValidator : ValueTypeValidator { + + private val COORDINATE_PATTERN = + "^\\[[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)]\$" + .toRegex() + + override fun validate(value: String): Result { + return when (value.matches(COORDINATE_PATTERN)) { + true -> { + Result.Success(value) + } + else -> { + Result.Failure(CoordinateFailure.CoordinateMalformedException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidatorShould.kt new file mode 100644 index 0000000000..b20420747f --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidatorShould.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.CoordinateFailure +import org.junit.Test + +class CoordinateValidatorShould : ValidatorShouldHelper(CoordinateValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("[-11.876444,9.032566]") + valueShouldSuccess("[+90.0, -127.554334]") + valueShouldSuccess("[45, 180]") + valueShouldSuccess("[-90, -180]") + valueShouldSuccess("[+90, +180]") + valueShouldSuccess("[0,0]") + valueShouldSuccess("[47.1231231, 179.99999999]") + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("[-90., -180.]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[-368.532519,16.858788]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[-1,181]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[-181,1]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[+90.1, -100.111]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[-91, 123.456]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[-91,123.456]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("[045, 180]", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("", CoordinateFailure.CoordinateMalformedException) + valueShouldFail("egs", CoordinateFailure.CoordinateMalformedException) + } +} From 0af4f7b7a61562883cad0fde27a39d31d34316c6 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Apr 2021 16:50:38 +0200 Subject: [PATCH 041/308] [androsdk-1334] Add UidValidator --- .../dhis/android/core/common/ValueType.kt | 6 +- .../validation/failures/UidFailure.kt | 35 ++++++++++ .../validation/validators/UidValidator.kt | 54 ++++++++++++++++ .../validators/UidValidatorShould.kt | 64 +++++++++++++++++++ 4 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UidFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 04c4d425db..f53c9c7da7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -48,12 +48,12 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) INTEGER_POSITIVE(Int::class.java, IntegerPositiveValidator), INTEGER_NEGATIVE(Int::class.java, IntegerNegativeValidator), INTEGER_ZERO_OR_POSITIVE(Int::class.java, IntegerZeroOrPositiveValidator), - FILE_RESOURCE(String::class.java, DefaultValidator), + FILE_RESOURCE(String::class.java, UidValidator), COORDINATE(String::class.java, CoordinateValidator), PHONE_NUMBER(String::class.java, DefaultValidator), EMAIL(String::class.java, DefaultValidator), - USERNAME(String::class.java, DefaultValidator), - ORGANISATION_UNIT(OrganisationUnit::class.java, DefaultValidator), + USERNAME(String::class.java, TextValidator), + ORGANISATION_UNIT(OrganisationUnit::class.java, UidValidator), TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, DefaultValidator), AGE(Date::class.java, DefaultValidator), URL(String::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UidFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UidFailure.kt new file mode 100644 index 0000000000..7e64fc6c22 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UidFailure.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class UidFailure : Throwable() { + object MoreThanElevenCharsException : UidFailure() + object LessThanElevenCharsException : UidFailure() + object MalformedUidException : UidFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt new file mode 100644 index 0000000000..36ebac1069 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.UidFailure + +object UidValidator : ValueTypeValidator { + + private val UID_PATTERN = "^[a-zA-Z0-9]{11}\$".toRegex() + + override fun validate(value: String): Result { + return when { + value.matches(UID_PATTERN) -> { + Result.Success(value) + } + value.length < 11 -> { + Result.Failure(UidFailure.LessThanElevenCharsException) + } + value.length > 11 -> { + Result.Failure(UidFailure.MoreThanElevenCharsException) + } + else -> { + Result.Failure(UidFailure.MalformedUidException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidatorShould.kt new file mode 100644 index 0000000000..166919c69a --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidatorShould.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.UidFailure +import org.junit.Test + +class UidValidatorShould : ValidatorShouldHelper(UidValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("E2vUc6z2CV6") + valueShouldSuccess("FsDo0TAPHPI") + valueShouldSuccess("01234567890") + valueShouldSuccess("abcdefghijk") + valueShouldSuccess("LMNOPQRSTUW") + } + + @Test + fun `Should fail when passing values with less than eleven chars`() { + valueShouldFail("FsDo0TAPHP", UidFailure.LessThanElevenCharsException) + } + + @Test + fun `Should fail when passing values with more than eleven chars`() { + valueShouldFail("FsDo0TAPHPI2", UidFailure.MoreThanElevenCharsException) + valueShouldFail("FsDo0TAPHPI FsDo0TAPHPI", UidFailure.MoreThanElevenCharsException) + valueShouldFail(".FsDo0TAPHPI", UidFailure.MoreThanElevenCharsException) + } + + @Test + fun `Should fail when passing malformed values`() { + valueShouldFail("ñsDo0TAPHPI", UidFailure.MalformedUidException) + valueShouldFail("ÁsDo0TAPHPI", UidFailure.MalformedUidException) + valueShouldFail("ásDo0TAPHPI", UidFailure.MalformedUidException) + valueShouldFail(".sDo0TAPHPI", UidFailure.MalformedUidException) + } +} From 7d85ca0634b4285868b63209373ec33dcfc008c6 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 14:32:07 +0200 Subject: [PATCH 042/308] [ANDROSDK-1362] Add TrackerJobObject, store and table info --- .../importer/internal/TrackerJobObject.java | 80 +++++++++++++++++++ .../internal/TrackerJobObjectStore.kt | 52 ++++++++++++ .../internal/TrackerJobObjectTableInfo.java | 71 ++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java new file mode 100644 index 0000000000..539e5ffd37 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal; + +import android.database.Cursor; + +import androidx.annotation.NonNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.BaseObject; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_TrackerJobObject.Builder.class) +public abstract class TrackerJobObject extends BaseObject { + + @NonNull + @JsonProperty() + public abstract String objectType(); + + @NonNull + @JsonProperty() + public abstract String objectUid(); + + @NonNull + @JsonProperty() + public abstract String jobUid(); + + + @NonNull + public static TrackerJobObject create(Cursor cursor) { + return AutoValue_TrackerJobObject.createFromCursor(cursor); + } + + + public static Builder builder() { + return new AutoValue_TrackerJobObject.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public abstract static class Builder extends BaseObject.Builder { + public abstract Builder objectType(String objectType); + + public abstract Builder objectUid(String objectUid); + + public abstract Builder jobUid(String jobUid); + + public abstract TrackerJobObject build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt new file mode 100644 index 0000000000..5caab7eb87 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal + +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +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.internal.ObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectStore + +internal object TrackerJobObjectStore { + + private val BINDER = StatementBinder { o: TrackerJobObject, w: StatementWrapper -> + w.bind(1, o.objectType()) + w.bind(2, o.objectUid()) + w.bind(3, o.jobUid()) + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): ObjectStore { + return objectStore( + databaseAdapter, + TrackerJobObjectTableInfo.TABLE_INFO, + BINDER + ) { TrackerJobObject.create(it) } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java new file mode 100644 index 0000000000..617fe73f52 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal; + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo; +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; +import org.hisp.dhis.android.core.common.CoreColumns; + +public final class TrackerJobObjectTableInfo { + + private TrackerJobObjectTableInfo() { + } + + public static final TableInfo TABLE_INFO = new TableInfo() { + + @Override + public String name() { + return "TrackerJobTableInfo"; + } + + @Override + public CoreColumns columns() { + return new Columns(); + } + }; + + public static class Columns extends CoreColumns { + + public static final String OBJECT_TYPE = "objectType"; + public static final String OBJECT_UID = "objectUid"; + public static final String JOB_UID = "jobUid"; + + + @Override + public String[] all() { + return CollectionsHelper.appendInNewArray(super.all(), + OBJECT_TYPE, OBJECT_UID, JOB_UID); + } + + @Override + public String[] whereUpdate() { + return new String[]{OBJECT_TYPE, OBJECT_UID}; + } + } +} From f1e53e3b44cac50e4f45d40003534ecc6c208a05 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 14:36:53 +0200 Subject: [PATCH 043/308] [ANDROSDK-1362] Add migration --- core/src/main/assets/migrations/99.sql | 3 +++ core/src/main/assets/snapshots/{98.sql => 99.sql} | 2 +- .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 core/src/main/assets/migrations/99.sql rename core/src/main/assets/snapshots/{98.sql => 99.sql} (99%) diff --git a/core/src/main/assets/migrations/99.sql b/core/src/main/assets/migrations/99.sql new file mode 100644 index 0000000000..88ea3a8e29 --- /dev/null +++ b/core/src/main/assets/migrations/99.sql @@ -0,0 +1,3 @@ +# New table for tracker importer +DROP TABLE TrackerJob; +CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT, objectUid TEXT, jobUid TEXT); diff --git a/core/src/main/assets/snapshots/98.sql b/core/src/main/assets/snapshots/99.sql similarity index 99% rename from core/src/main/assets/snapshots/98.sql rename to core/src/main/assets/snapshots/99.sql index 8f1b137ed6..4f35a7382d 100644 --- a/core/src/main/assets/snapshots/98.sql +++ b/core/src/main/assets/snapshots/99.sql @@ -103,10 +103,10 @@ CREATE TABLE TrackedEntityInstanceEventFilter (_id INTEGER PRIMARY KEY AUTOINCRE CREATE TABLE EventFilter (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, program TEXT NOT NULL, programStage TEXT, description TEXT, followUp INTEGER, organisationUnit TEXT, ouMode TEXT, assignedUserMode TEXT, orderProperty TEXT, displayColumnOrder TEXT, events TEXT, eventStatus TEXT, eventDate TEXT, dueDate TEXT, lastUpdatedDate TEXT, completedDate TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE EventDataFilter (_id INTEGER PRIMARY KEY AUTOINCREMENT, eventFilter TEXT NOT NULL, dataItem TEXT, le TEXT, ge TEXT, gt TEXT, lt TEXT, eq TEXT, inProperty TEXT, like TEXT, dateFilter TEXT, FOREIGN KEY (eventFilter) REFERENCES EventFilter (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE ReservedValueSetting (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE, numberOfValuesToReserve INTEGER, FOREIGN KEY (uid) REFERENCES TrackedEntityAttribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE TrackerJob (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE); CREATE TABLE SectionIndicatorLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, section TEXT NOT NULL, indicator TEXT NOT NULL, FOREIGN KEY (section) REFERENCES Section (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (indicator) REFERENCES Indicator (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (section, indicator)); CREATE TABLE DataElementLegendSetLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, legendSet TEXT NOT NULL, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (legendSet) REFERENCES LegendSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, legendSet)); CREATE TABLE Attribute (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, valueType TEXT, uniqueProperty INTEGER, mandatory INTEGER, indicatorAttribute INTEGER, indicatorGroupAttribute INTEGER, userGroupAttribute INTEGER, dataElementAttribute INTEGER, constantAttribute INTEGER, categoryOptionAttribute INTEGER, optionSetAttribute INTEGER, sqlViewAttribute INTEGER, legendSetAttribute INTEGER, trackedEntityAttributeAttribute INTEGER, organisationUnitAttribute INTEGER, dataSetAttribute INTEGER, documentAttribute INTEGER, validationRuleGroupAttribute INTEGER, dataElementGroupAttribute INTEGER, sectionAttribute INTEGER, trackedEntityTypeAttribute INTEGER, userAttribute INTEGER, categoryOptionGroupAttribute INTEGER, programStageAttribute INTEGER, programAttribute INTEGER, categoryAttribute INTEGER, categoryOptionComboAttribute INTEGER, categoryOptionGroupSetAttribute INTEGER, validationRuleAttribute INTEGER, programIndicatorAttribute INTEGER, organisationUnitGroupAttribute INTEGER, dataElementGroupSetAttribute INTEGER, organisationUnitGroupSetAttribute INTEGER, optionAttribute INTEGER); CREATE TABLE ProgramStageAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, programStage TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (programStage, attribute)); CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, attribute)); CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); +CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT, objectUid TEXT, jobUid TEXT); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index dd448decb7..1dfd2092f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 98; + static final int VERSION = 99; private final AssetManager assetManager; private final int targetVersion; From 5c985ed795aad819868061aa6ed69b320d949fa6 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 15:44:42 +0200 Subject: [PATCH 044/308] [ANDROSDK-1362] Remove old tracker job table store and table info --- .../wipe/WipeDBCallMockIntegrationShould.java | 8 ++- .../internal/EventTrackerImporterPostCall.kt | 2 +- .../tracker/importer/internal/JobQueryCall.kt | 21 +++--- ...edEntityInstanceTrackerImporterPostCall.kt | 2 +- .../TrackerImporterPackageDIModule.java | 7 +- .../internal/TrackerJobModuleWiper.kt | 4 +- .../internal/TrackerJobObjectTableInfo.java | 2 +- .../importer/internal/TrackerJobStore.kt | 46 ------------- .../internal/TrackerJobTableInfo.java | 67 ------------------- 9 files changed, 22 insertions(+), 137 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobStore.kt delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobTableInfo.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index a92010ce84..33599e1500 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.wipe; -import org.hisp.dhis.android.core.common.StorableObjectWithUid; import org.hisp.dhis.android.core.data.database.DatabaseAssert; import org.hisp.dhis.android.core.fileresource.FileResource; import org.hisp.dhis.android.core.fileresource.internal.FileResourceStoreImpl; @@ -37,7 +36,8 @@ import org.hisp.dhis.android.core.maintenance.D2Error; import org.hisp.dhis.android.core.maintenance.D2ErrorCode; import org.hisp.dhis.android.core.maintenance.internal.D2ErrorStore; -import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobStore; +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject; +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObjectStore; import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyDispatcher; import org.junit.Test; @@ -88,6 +88,8 @@ private void givenOthersInDatabase() { TrackerImportConflictStoreImpl.create(databaseAdapter).insert(TrackerImportConflict.builder().build()); FileResourceStoreImpl.create(databaseAdapter).insert(FileResource.builder().uid("uid").build()); - TrackerJobStore.create(databaseAdapter).insert(StorableObjectWithUid.create("uid")); + TrackerJobObjectStore.create(databaseAdapter).insert( + TrackerJobObject.builder().jobUid("uid").objectType("type").objectUid("oUid").build() + ); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index 3149719926..b663c1e5f7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -57,7 +57,7 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( val eventPayload = NewTrackerImporterEventPayload(eventsToPost) val res = apiCallExecutor.executeObjectCall(service.postEvents(eventPayload)) val jobId = res.response().uid() - jobQueryCall.storeJob(jobId) + // TODO generate objects and call handler jobQueryCall.storeJob(jobId) jobId }.doOnError { stateManager.markObjectsAs(eventsToPost, DataStateHelper.errorIfOnline(it)) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index 0632f5dd69..e978ae63d7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -29,33 +29,30 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable -import java.util.concurrent.TimeUnit -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore -import org.hisp.dhis.android.core.common.StorableObjectWithUid +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore +import java.util.concurrent.TimeUnit +import javax.inject.Inject @Reusable internal class JobQueryCall @Inject internal constructor( private val service: TrackerImporterService, private val apiCallExecutor: APICallExecutor, - private val trackerJobStore: IdentifiableObjectStore, + private val trackerJobObjectStore: ObjectStore, private val handler: JobReportHandler ) { - fun storeJob(jobId: String) { - trackerJobStore.insert(StorableObjectWithUid.create(jobId)) - } - fun queryPendingJobs(): Observable { return Observable.just(true) .flatMapIterable { - val pendingJobs = trackerJobStore.selectAll() + val pendingJobs = trackerJobObjectStore.selectAll() + .map { it.jobUid() } + .distinct() pendingJobs.withIndex().map { ij -> Pair(ij.value, ij.index == pendingJobs.size - 1) } } - .flatMap { jobWithIsLast -> queryJob(jobWithIsLast.first.uid(), jobWithIsLast.second) } + .flatMap { jobWithIsLast -> queryJob(jobWithIsLast.first, jobWithIsLast.second) } } fun queryJob(jobId: String): Observable { @@ -74,7 +71,7 @@ internal class JobQueryCall @Inject internal constructor( .doOnNext { if (it) { val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) - trackerJobStore.delete(jobId) + // TODO delete trackerJobObjectStore.delete(jobId) handler.handle(jobReport) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 05235df7ec..2b6fe9b9c3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -63,7 +63,7 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con service.postTrackedEntityInstances(trackedEntityInstancePayload) ) val jobId = res.response().uid() - jobQueryCall.storeJob(jobId) + // TODO generate objects and handle jobQueryCall.storeJob(jobId) jobId }.doOnError { stateManager.restoreStates(trackedEntitiesToPost) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java index 73db0bbc7a..304033f6d7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java @@ -29,8 +29,7 @@ package org.hisp.dhis.android.core.tracker.importer.internal; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.common.StorableObjectWithUid; +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import dagger.Module; import dagger.Provides; @@ -48,7 +47,7 @@ TrackerImporterService service(Retrofit retrofit) { @Provides @Reusable - IdentifiableObjectStore store(DatabaseAdapter databaseAdapter) { - return TrackerJobStore.create(databaseAdapter); + ObjectStore store(DatabaseAdapter databaseAdapter) { + return TrackerJobObjectStore.create(databaseAdapter); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt index a013df38af..aa46ced221 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt @@ -28,9 +28,9 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.wipe.internal.ModuleWiper import org.hisp.dhis.android.core.wipe.internal.TableWiper +import javax.inject.Inject @Reusable class TrackerJobModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { @@ -40,7 +40,7 @@ class TrackerJobModuleWiper @Inject internal constructor(private val tableWiper: override fun wipeData() { tableWiper.wipeTables( - TrackerJobTableInfo.TABLE_INFO + TrackerJobObjectTableInfo.TABLE_INFO ) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java index 617fe73f52..a34c7922e6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java @@ -41,7 +41,7 @@ private TrackerJobObjectTableInfo() { @Override public String name() { - return "TrackerJobTableInfo"; + return "TrackerJobObject"; } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobStore.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobStore.kt deleted file mode 100644 index 04dd4777dc..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobStore.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.tracker.importer.internal - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithUidStore -import org.hisp.dhis.android.core.common.StorableObjectWithUid - -internal object TrackerJobStore { - - @JvmStatic - fun create(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { - return objectWithUidStore( - databaseAdapter, - TrackerJobTableInfo.TABLE_INFO, - StatementBinder { o, w -> w.bind(1, o.uid()) } - ) { StorableObjectWithUid.create(it) } - } -} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobTableInfo.java deleted file mode 100644 index 73710c7cdf..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobTableInfo.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.tracker.importer.internal; - -import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo; -import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; -import org.hisp.dhis.android.core.common.CoreColumns; - -import static org.hisp.dhis.android.core.common.IdentifiableColumns.UID; - -public final class TrackerJobTableInfo { - - private TrackerJobTableInfo() { - } - - public static final TableInfo TABLE_INFO = new TableInfo() { - - @Override - public String name() { - return "TrackerJob"; - } - - @Override - public CoreColumns columns() { - return new Columns(); - } - }; - - public static class Columns extends CoreColumns { - - @Override - public String[] all() { - return CollectionsHelper.appendInNewArray(super.all(), UID); - } - - @Override - public String[] whereUpdate() { - return new String[]{UID}; - } - } -} From ee4ae68a6b8231917cb345bdfdd41f88d22b88cf Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 16:44:19 +0200 Subject: [PATCH 045/308] [ANDROSDK-1362] Add last updated --- .../core/wipe/WipeDBCallMockIntegrationShould.java | 9 ++++++++- core/src/main/assets/migrations/99.sql | 2 +- core/src/main/assets/snapshots/99.sql | 2 +- .../tracker/importer/internal/TrackerJobObject.java | 13 ++++++++++--- .../importer/internal/TrackerJobObjectStore.kt | 1 + .../internal/TrackerJobObjectTableInfo.java | 4 +++- 6 files changed, 24 insertions(+), 7 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index 33599e1500..1c4354bc6f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -41,6 +41,8 @@ import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyDispatcher; import org.junit.Test; +import java.util.Date; + public class WipeDBCallMockIntegrationShould extends BaseMockIntegrationTestEmptyDispatcher { @Test @@ -89,7 +91,12 @@ private void givenOthersInDatabase() { FileResourceStoreImpl.create(databaseAdapter).insert(FileResource.builder().uid("uid").build()); TrackerJobObjectStore.create(databaseAdapter).insert( - TrackerJobObject.builder().jobUid("uid").objectType("type").objectUid("oUid").build() + TrackerJobObject.builder() + .jobUid("uid") + .objectType("type") + .objectUid("oUid") + .lastUpdated(new Date()) + .build() ); } } diff --git a/core/src/main/assets/migrations/99.sql b/core/src/main/assets/migrations/99.sql index 88ea3a8e29..cb7bd351f4 100644 --- a/core/src/main/assets/migrations/99.sql +++ b/core/src/main/assets/migrations/99.sql @@ -1,3 +1,3 @@ # New table for tracker importer DROP TABLE TrackerJob; -CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT, objectUid TEXT, jobUid TEXT); +CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); diff --git a/core/src/main/assets/snapshots/99.sql b/core/src/main/assets/snapshots/99.sql index 4f35a7382d..663d0a8102 100644 --- a/core/src/main/assets/snapshots/99.sql +++ b/core/src/main/assets/snapshots/99.sql @@ -109,4 +109,4 @@ CREATE TABLE Attribute (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL CREATE TABLE ProgramStageAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, programStage TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (programStage, attribute)); CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, attribute)); CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); -CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT, objectUid TEXT, jobUid TEXT); +CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java index 539e5ffd37..e8358a293d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java @@ -35,26 +35,31 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbDateColumnAdapter; import org.hisp.dhis.android.core.common.BaseObject; +import java.util.Date; + @AutoValue @JsonDeserialize(builder = $$AutoValue_TrackerJobObject.Builder.class) public abstract class TrackerJobObject extends BaseObject { @NonNull - @JsonProperty() public abstract String objectType(); @NonNull - @JsonProperty() public abstract String objectUid(); @NonNull - @JsonProperty() public abstract String jobUid(); + @NonNull + @ColumnAdapter(DbDateColumnAdapter.class) + public abstract Date lastUpdated(); + @NonNull public static TrackerJobObject create(Cursor cursor) { @@ -75,6 +80,8 @@ public abstract static class Builder extends BaseObject.Builder { public abstract Builder jobUid(String jobUid); + public abstract Builder lastUpdated(Date lastUpdated); + public abstract TrackerJobObject build(); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt index 5caab7eb87..b7bfa10a86 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt @@ -39,6 +39,7 @@ internal object TrackerJobObjectStore { w.bind(1, o.objectType()) w.bind(2, o.objectUid()) w.bind(3, o.jobUid()) + w.bind(4, o.lastUpdated()) } @JvmStatic diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java index a34c7922e6..8a771454c3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java @@ -32,6 +32,8 @@ import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; import org.hisp.dhis.android.core.common.CoreColumns; +import static org.hisp.dhis.android.core.common.BaseIdentifiableObject.LAST_UPDATED; + public final class TrackerJobObjectTableInfo { private TrackerJobObjectTableInfo() { @@ -60,7 +62,7 @@ public static class Columns extends CoreColumns { @Override public String[] all() { return CollectionsHelper.appendInNewArray(super.all(), - OBJECT_TYPE, OBJECT_UID, JOB_UID); + OBJECT_TYPE, OBJECT_UID, JOB_UID, LAST_UPDATED); } @Override From 285bce19bfcb18ac55c8afa75e2331e6b772b549 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 16:45:46 +0200 Subject: [PATCH 046/308] [ANDROSDK-1362] Use last updated --- .../dhis/android/core/tracker/importer/internal/JobQueryCall.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index e978ae63d7..4ef30594a8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -48,6 +48,7 @@ internal class JobQueryCall @Inject internal constructor( return Observable.just(true) .flatMapIterable { val pendingJobs = trackerJobObjectStore.selectAll() + .sortedBy { it.lastUpdated() } .map { it.jobUid() } .distinct() pendingJobs.withIndex().map { ij -> Pair(ij.value, ij.index == pendingJobs.size - 1) } From acca9c7df8c3a27f84dcc327c0bed70e8927e7b0 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 17:00:09 +0200 Subject: [PATCH 047/308] [ANDROSDK-1362] Generate job objects in event call --- .../internal/EventTrackerImporterPostCall.kt | 21 +++++++++++++++-- .../tracker/importer/internal/JobQueryCall.kt | 4 ++-- .../TrackerImporterPackageDIModule.java | 12 ++++++++-- .../internal/TrackerJobObjectStore.kt | 23 +++++++++++++++---- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index b663c1e5f7..58deec5eef 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -33,11 +33,15 @@ import io.reactivex.Single import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress +import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.arch.helpers.internal.DataStateHelper import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterService +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject +import java.util.Date @Reusable internal class EventTrackerImporterPostCall @Inject internal constructor( @@ -45,7 +49,8 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( private val stateManager: EventPostStateManager, private val service: TrackerImporterService, private val apiCallExecutor: APICallExecutor, - private val jobQueryCall: JobQueryCall + private val jobQueryCall: JobQueryCall, + private val jobObjectHandler: Handler ) { fun uploadEvents( events: List @@ -57,7 +62,7 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( val eventPayload = NewTrackerImporterEventPayload(eventsToPost) val res = apiCallExecutor.executeObjectCall(service.postEvents(eventPayload)) val jobId = res.response().uid() - // TODO generate objects and call handler jobQueryCall.storeJob(jobId) + jobObjectHandler.handleMany(generateJobObjects(eventsToPost, jobId)) jobId }.doOnError { stateManager.markObjectsAs(eventsToPost, DataStateHelper.errorIfOnline(it)) @@ -66,4 +71,16 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( } } } + + private fun generateJobObjects(events: List, jobUid: String): List { + val lastUpdated = Date() + return events.map { TrackerJobObject + .builder() + .objectType("EVENT") + .objectUid(it.uid()) + .jobUid(jobUid) + .lastUpdated(lastUpdated) + .build() + } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index 4ef30594a8..dd9aec56b7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -32,7 +32,7 @@ import io.reactivex.Observable import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -40,7 +40,7 @@ import javax.inject.Inject internal class JobQueryCall @Inject internal constructor( private val service: TrackerImporterService, private val apiCallExecutor: APICallExecutor, - private val trackerJobObjectStore: ObjectStore, + private val trackerJobObjectStore: ObjectWithoutUidStore, private val handler: JobReportHandler ) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java index 304033f6d7..66330da190 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterPackageDIModule.java @@ -29,7 +29,9 @@ package org.hisp.dhis.android.core.tracker.importer.internal; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; +import org.hisp.dhis.android.core.arch.handlers.internal.Handler; +import org.hisp.dhis.android.core.arch.handlers.internal.ObjectWithoutUidHandlerImpl; import dagger.Module; import dagger.Provides; @@ -47,7 +49,13 @@ TrackerImporterService service(Retrofit retrofit) { @Provides @Reusable - ObjectStore store(DatabaseAdapter databaseAdapter) { + ObjectWithoutUidStore store(DatabaseAdapter databaseAdapter) { return TrackerJobObjectStore.create(databaseAdapter); } + + @Provides + @Reusable + Handler handler(ObjectWithoutUidStore store) { + return new ObjectWithoutUidHandlerImpl<>(store); + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt index b7bfa10a86..d0b34046a3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt @@ -30,8 +30,9 @@ package org.hisp.dhis.android.core.tracker.importer.internal import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter 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.internal.ObjectStore -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectStore +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.WhereStatementBinder +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithoutUidStore internal object TrackerJobObjectStore { @@ -42,12 +43,24 @@ internal object TrackerJobObjectStore { w.bind(4, o.lastUpdated()) } + private val WHERE_UPDATE_BINDER = WhereStatementBinder { o: TrackerJobObject, w: StatementWrapper -> + w.bind(5, o.objectType()) + w.bind(6, o.objectUid()) + } + + private val DELETE_UPDATE_BINDER = WhereStatementBinder { o: TrackerJobObject, w: StatementWrapper -> + w.bind(1, o.objectType()) + w.bind(2, o.objectUid()) + } + @JvmStatic - fun create(databaseAdapter: DatabaseAdapter): ObjectStore { - return objectStore( + fun create(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { + return objectWithoutUidStore( databaseAdapter, TrackerJobObjectTableInfo.TABLE_INFO, - BINDER + BINDER, + WHERE_UPDATE_BINDER, + DELETE_UPDATE_BINDER ) { TrackerJobObject.create(it) } } } From 563ac47bead6c416f6533d067860955ade4da421 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 20 Apr 2021 17:03:53 +0200 Subject: [PATCH 048/308] [ANDROSDK-1362] Add delete where clause --- .../android/core/tracker/importer/internal/JobQueryCall.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index dd9aec56b7..87f2f07030 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -32,6 +32,7 @@ import io.reactivex.Observable import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -72,7 +73,10 @@ internal class JobQueryCall @Inject internal constructor( .doOnNext { if (it) { val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) - // TODO delete trackerJobObjectStore.delete(jobId) + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(TrackerJobObjectTableInfo.Columns.JOB_UID, jobId) + .build() + trackerJobObjectStore.deleteWhere(whereClause) handler.handle(jobReport) } } From 0d46aa6dd22eaf295b854b45f32b92a3ea0b0039 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 21 Apr 2021 14:44:11 +0200 Subject: [PATCH 049/308] [ANDROSDK-1362] Handle objects in tracked entity call --- .../internal/EventTrackerImporterPostCall.kt | 5 +-- .../importer/internal/JobReportHandler.kt | 9 +++-- ...edEntityInstanceTrackerImporterPostCall.kt | 35 +++++++++++++++++-- .../internal/TrackerImporterObjectTypes.kt | 35 +++++++++++++++++++ 4 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index 58deec5eef..ebddfd47c6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -30,7 +30,6 @@ package org.hisp.dhis.android.core.event.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler @@ -39,9 +38,11 @@ import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterService import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject import java.util.Date +import javax.inject.Inject @Reusable internal class EventTrackerImporterPostCall @Inject internal constructor( @@ -76,7 +77,7 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( val lastUpdated = Date() return events.map { TrackerJobObject .builder() - .objectType("EVENT") + .objectType(EVENT) .objectUid(it.uid()) .jobUid(jobUid) .lastUpdated(lastUpdated) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index afd35d18ad..113f1bfc98 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -28,6 +28,9 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY import javax.inject.Inject @Reusable @@ -40,9 +43,9 @@ internal class JobReportHandler @Inject internal constructor( fun handle(o: JobReport) { o.validationReport.errorReports.forEach { errorReport -> when (errorReport.trackerType) { - "EVENT" -> eventHandler.handleError(errorReport) - "ENROLLMENT" -> enrollmentHandler.handleError(errorReport) - "TRACKED_ENTITY" -> eventHandler.handleError(errorReport) + EVENT -> eventHandler.handleError(errorReport) + ENROLLMENT -> enrollmentHandler.handleError(errorReport) + TRACKED_ENTITY -> trackedEntityHandler.handleError(errorReport) else -> println("Unsupported type") // TODO } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 2b6fe9b9c3..39063a3de6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -30,14 +30,18 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress +import org.hisp.dhis.android.core.arch.handlers.internal.Handler +import org.hisp.dhis.android.core.common.ObjectWithUidInterface import org.hisp.dhis.android.core.relationship.internal.RelationshipDeleteCall +import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntity import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostPayloadGenerator import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostStateManager +import java.util.Date +import javax.inject.Inject @Reusable internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal constructor( @@ -46,6 +50,7 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con private val service: TrackerImporterService, private val apiCallExecutor: APICallExecutor, private val jobQueryCall: JobQueryCall, + private val jobObjectHandler: Handler, private val relationshipDeleteCall: RelationshipDeleteCall ) { fun uploadTrackedEntityInstances( @@ -63,7 +68,7 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con service.postTrackedEntityInstances(trackedEntityInstancePayload) ) val jobId = res.response().uid() - // TODO generate objects and handle jobQueryCall.storeJob(jobId) + jobObjectHandler.handleMany(generateJobObjects(trackedEntitiesToPost, jobId)) jobId }.doOnError { stateManager.restoreStates(trackedEntitiesToPost) @@ -72,4 +77,30 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con } } } + + private fun generateJobObjects(trackedEntities: List, jobUid: String): List { + val builder = TrackerJobObject + .builder() + .jobUid(jobUid) + .lastUpdated(Date()) + + val enrollments = trackedEntities.flatMap { it.enrollments()!! } + val events = enrollments.flatMap { it.events()!! } + + return generateTypeObjects(builder, TrackerImporterObjectTypes.TRACKED_ENTITY, trackedEntities) + + generateTypeObjects(builder, TrackerImporterObjectTypes.ENROLLMENT, enrollments) + + generateTypeObjects(builder, TrackerImporterObjectTypes.EVENT, events) + } + + private fun generateTypeObjects( + builder: TrackerJobObject.Builder, + objectType: String, + objects: List + ): List { + return objects.map { builder + .objectType(objectType) + .objectUid(it.uid()) + .build() + } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt new file mode 100644 index 0000000000..952a119cad --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal + +internal object TrackerImporterObjectTypes { + const val EVENT = "EVENT" + const val TRACKED_ENTITY = "TRACKED_ENTITY" + const val ENROLLMENT = "ENROLLMENT" + const val RELATIONSHIP = "RELATIONSHIP" +} From 8565293e78b67ea5c746f0491ca01b49af8288b8 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 21 Apr 2021 15:02:42 +0200 Subject: [PATCH 050/308] [ANDROSDK-1362] Add TrackerJobObjectStoreIntegrationShould --- ...rackerJobObjectStoreIntegrationShould.java | 57 +++++++++++++++++++ .../importer/internal/TrackerJobObject.java | 3 +- .../internal/TrackerJobObjectSamples.java | 47 +++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStoreIntegrationShould.java create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStoreIntegrationShould.java new file mode 100644 index 0000000000..721b0ed005 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStoreIntegrationShould.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal; + +import org.hisp.dhis.android.core.data.database.ObjectWithoutUidStoreAbstractIntegrationShould; +import org.hisp.dhis.android.core.data.tracker.importer.internal.TrackerJobObjectSamples; +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory; +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; +import org.junit.runner.RunWith; + +@RunWith(D2JunitRunner.class) +public class TrackerJobObjectStoreIntegrationShould extends ObjectWithoutUidStoreAbstractIntegrationShould { + + public TrackerJobObjectStoreIntegrationShould() { + super(TrackerJobObjectStore.create(TestDatabaseAdapterFactory.get()), TrackerJobObjectTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get()); + } + + @Override + protected TrackerJobObject buildObject() { + return TrackerJobObjectSamples.get1(); + } + + @Override + protected TrackerJobObject buildObjectToUpdate() { + return TrackerJobObjectSamples.get1() + .toBuilder() + .jobUid("anotherJobId") + .build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java index e8358a293d..2eed2965fd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java @@ -32,7 +32,6 @@ import androidx.annotation.NonNull; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.gabrielittner.auto.value.cursor.ColumnAdapter; @@ -71,6 +70,8 @@ public static Builder builder() { return new AutoValue_TrackerJobObject.Builder(); } + abstract Builder toBuilder(); + @AutoValue.Builder @JsonPOJOBuilder(withPrefix = "") public abstract static class Builder extends BaseObject.Builder { diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java new file mode 100644 index 0000000000..f58965e980 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.tracker.importer.internal; + +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject; + +import static org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.parseDate; +import static org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT; + +public class TrackerJobObjectSamples { + + public static TrackerJobObject get1() { + return TrackerJobObject.builder() + .id(1L) + .objectType(EVENT) + .objectUid("oUid") + .jobUid("jUid") + .lastUpdated(parseDate("2017-11-29T11:27:46.935")) + .build(); + } +} From 4dfda7205d2b63f8eb82ea9f0abf7ec9a7954d16 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 21 Apr 2021 15:31:21 +0200 Subject: [PATCH 051/308] [ANDROSDK-1362] Detekt --- .../internal/EventTrackerImporterPostCall.kt | 19 ++++++++++--------- .../tracker/importer/internal/JobQueryCall.kt | 4 ++-- .../importer/internal/JobReportHandler.kt | 2 +- ...edEntityInstanceTrackerImporterPostCall.kt | 18 +++++++++++------- .../internal/TrackerJobModuleWiper.kt | 2 +- .../internal/TrackerJobObjectStore.kt | 1 + 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index ebddfd47c6..01352dda31 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -30,6 +30,8 @@ package org.hisp.dhis.android.core.event.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single +import java.util.Date +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler @@ -41,8 +43,6 @@ import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterService import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject -import java.util.Date -import javax.inject.Inject @Reusable internal class EventTrackerImporterPostCall @Inject internal constructor( @@ -75,13 +75,14 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( private fun generateJobObjects(events: List, jobUid: String): List { val lastUpdated = Date() - return events.map { TrackerJobObject - .builder() - .objectType(EVENT) - .objectUid(it.uid()) - .jobUid(jobUid) - .lastUpdated(lastUpdated) - .build() + return events.map { + TrackerJobObject + .builder() + .objectType(EVENT) + .objectUid(it.uid()) + .jobUid(jobUid) + .lastUpdated(lastUpdated) + .build() } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index 87f2f07030..e3b3ea25f4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -29,13 +29,13 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable +import java.util.concurrent.TimeUnit +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore -import java.util.concurrent.TimeUnit -import javax.inject.Inject @Reusable internal class JobQueryCall @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 113f1bfc98..0a55f77b1c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY -import javax.inject.Inject @Reusable internal class JobReportHandler @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 39063a3de6..aa0bbfbe8e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -30,6 +30,8 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single +import java.util.Date +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler @@ -40,8 +42,6 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostPayloadGenerator import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostStateManager -import java.util.Date -import javax.inject.Inject @Reusable internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal constructor( @@ -78,7 +78,10 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con } } - private fun generateJobObjects(trackedEntities: List, jobUid: String): List { + private fun generateJobObjects( + trackedEntities: List, + jobUid: String + ): List { val builder = TrackerJobObject .builder() .jobUid(jobUid) @@ -97,10 +100,11 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con objectType: String, objects: List ): List { - return objects.map { builder - .objectType(objectType) - .objectUid(it.uid()) - .build() + return objects.map { + builder + .objectType(objectType) + .objectUid(it.uid()) + .build() } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt index aa46ced221..a8e324320a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobModuleWiper.kt @@ -28,9 +28,9 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.wipe.internal.ModuleWiper import org.hisp.dhis.android.core.wipe.internal.TableWiper -import javax.inject.Inject @Reusable class TrackerJobModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt index d0b34046a3..1a1a35c22a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.arch.db.stores.binders.internal.WhereStatement import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithoutUidStore +@Suppress("MagicNumber") internal object TrackerJobObjectStore { private val BINDER = StatementBinder { o: TrackerJobObject, w: StatementWrapper -> From 6223dea3b344cc4a264de4d98ee5345957249277 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 21 Apr 2021 16:49:13 +0200 Subject: [PATCH 052/308] feat: [ANDROSDK-1310-2] Add import strategy and atomic mode --- .../internal/EventTrackerImporterPostCall.kt | 9 +++-- ...edEntityInstanceTrackerImporterPostCall.kt | 5 ++- .../internal/TrackerImporterService.kt | 35 ++++++++++++------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index 01352dda31..2de68ded3d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -39,10 +39,10 @@ import org.hisp.dhis.android.core.arch.helpers.internal.DataStateHelper import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.NewTrackerImporterEvent +import org.hisp.dhis.android.core.tracker.importer.internal.* import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterService -import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject @Reusable internal class EventTrackerImporterPostCall @Inject internal constructor( @@ -61,7 +61,12 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( stateManager.markObjectsAs(eventsToPost, State.UPLOADING) Single.fromCallable { val eventPayload = NewTrackerImporterEventPayload(eventsToPost) - val res = apiCallExecutor.executeObjectCall(service.postEvents(eventPayload)) + val res = apiCallExecutor.executeObjectCall( + service.postEvents( + eventPayload, ATOMIC_MODE_OBJECT, + IMPORT_STRATEGY_CREATE_AND_UPDATE + ) + ) val jobId = res.response().uid() jobObjectHandler.handleMany(generateJobObjects(eventsToPost, jobId)) jobId diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index aa0bbfbe8e..6b522916e0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -65,7 +65,10 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con // relationshipDeleteCall.postDeletedRelationships(partition) val trackedEntityInstancePayload = NewTrackerImporterTrackedEntityPayload(trackedEntitiesToPost) val res = apiCallExecutor.executeObjectCall( - service.postTrackedEntityInstances(trackedEntityInstancePayload) + service.postTrackedEntityInstances( + trackedEntityInstancePayload, ATOMIC_MODE_OBJECT, + IMPORT_STRATEGY_CREATE_AND_UPDATE + ) ) val jobId = res.response().uid() jobObjectHandler.handleMany(generateJobObjects(trackedEntitiesToPost, jobId)) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt index 3bbe60517e..8a6a18b651 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt @@ -31,26 +31,37 @@ import org.hisp.dhis.android.core.event.internal.NewTrackerImporterEventPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPayload import org.hisp.dhis.android.core.trackedentity.internal.ObjectWithUidWebResponse import retrofit2.Call -import retrofit2.http.Body -import retrofit2.http.GET -import retrofit2.http.POST -import retrofit2.http.Path +import retrofit2.http.* + +internal const val TRACKER_URL = "tracker" +internal const val JOBS_URL = "tracker/jobs/" + +internal const val ATOMIC_MODE = "atomicMode" +internal const val ATOMIC_MODE_OBJECT = "OBJECT" + +internal const val IMPORT_STRATEGY = "importStrategy" +internal const val IMPORT_STRATEGY_CREATE_AND_UPDATE = "CREATE_AND_UPDATE" +internal const val JOB_ID = "jobId" internal interface TrackerImporterService { - @POST("tracker") + @POST(TRACKER_URL) fun postTrackedEntityInstances( - @Body payload: NewTrackerImporterTrackedEntityPayload + @Body payload: NewTrackerImporterTrackedEntityPayload, + @Query(ATOMIC_MODE) atomicMode: String, + @Query(IMPORT_STRATEGY) importStrategy: String ): Call - @POST("tracker") + @POST(TRACKER_URL) fun postEvents( - @Body events: NewTrackerImporterEventPayload + @Body events: NewTrackerImporterEventPayload, + @Query(ATOMIC_MODE) atomicMode: String, + @Query(IMPORT_STRATEGY) importStrategy: String ): Call - @GET("tracker/jobs/{jobId}") - fun getJob(@Path("jobId") jobId: String): Call> + @GET("$JOBS_URL{jobId}") + fun getJob(@Path(JOB_ID) jobId: String): Call> - @GET("tracker/jobs/{jobId}/report") - fun getJobReport(@Path("jobId") jobId: String): Call + @GET("$JOBS_URL{jobId}/report") + fun getJobReport(@Path(JOB_ID) jobId: String): Call } From fffed354b1a108b2c4edb28f4610095ca3e6fa98 Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 22 Apr 2021 15:10:18 +0200 Subject: [PATCH 053/308] [ANDROSDK-1310-3] Only handle objects when part of last update --- .../tracker/importer/internal/JobQueryCall.kt | 15 ++++---- .../importer/internal/JobReportHandler.kt | 35 +++++++++++-------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index e3b3ea25f4..4d9f25f248 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -50,18 +50,21 @@ internal class JobQueryCall @Inject internal constructor( .flatMapIterable { val pendingJobs = trackerJobObjectStore.selectAll() .sortedBy { it.lastUpdated() } - .map { it.jobUid() } - .distinct() + .groupBy { it.jobUid() } + .toList() + pendingJobs.withIndex().map { ij -> Pair(ij.value, ij.index == pendingJobs.size - 1) } } - .flatMap { jobWithIsLast -> queryJob(jobWithIsLast.first, jobWithIsLast.second) } + .flatMap { jobPairIndex -> queryJob(jobPairIndex.first.first, jobPairIndex.first.second, jobPairIndex.second) } } fun queryJob(jobId: String): Observable { - return queryJob(jobId, true) + val jobObjects = trackerJobObjectStore.selectAll() + .filter { it.jobUid() == jobId } + return queryJob(jobId, jobObjects, true) } - private fun queryJob(jobId: String, isLastJob: Boolean): Observable { + private fun queryJob(jobId: String, jobObjects: List, isLastJob: Boolean): Observable { val progressManager = D2ProgressManager(null) @Suppress("MagicNumber") return Observable.interval(0, 5, TimeUnit.SECONDS) @@ -77,7 +80,7 @@ internal class JobQueryCall @Inject internal constructor( .appendKeyStringValue(TrackerJobObjectTableInfo.Columns.JOB_UID, jobId) .build() trackerJobObjectStore.deleteWhere(whereClause) - handler.handle(jobReport) + handler.handle(jobReport, jobObjects) } } .take(3) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 0a55f77b1c..7bbaf897e0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY +import javax.inject.Inject @Reusable internal class JobReportHandler @Inject internal constructor( @@ -40,27 +40,34 @@ internal class JobReportHandler @Inject internal constructor( private val trackedEntityHandler: JobReportTrackedEntityHandler ) { - fun handle(o: JobReport) { + fun handle(o: JobReport, jobObjects: List) { + val jobObjectsMap = jobObjects.groupBy { jo -> Pair(jo.objectType(), jo.objectUid()) } o.validationReport.errorReports.forEach { errorReport -> - when (errorReport.trackerType) { - EVENT -> eventHandler.handleError(errorReport) - ENROLLMENT -> enrollmentHandler.handleError(errorReport) - TRACKED_ENTITY -> trackedEntityHandler.handleError(errorReport) - else -> println("Unsupported type") // TODO + if (jobObjectsMap.containsKey(Pair(errorReport.trackerType, errorReport.uid))) { + when (errorReport.trackerType) { + EVENT -> eventHandler.handleError(errorReport) + ENROLLMENT -> enrollmentHandler.handleError(errorReport) + TRACKED_ENTITY -> trackedEntityHandler.handleError(errorReport) + else -> println("Unsupported type") // TODO + } } } if (o.bundleReport != null) { val typeMap = o.bundleReport.typeReportMap - applySuccess(typeMap.event, eventHandler) - applySuccess(typeMap.enrollment, enrollmentHandler) - applySuccess(typeMap.trackedEntity, trackedEntityHandler) + applySuccess(typeMap.event, jobObjectsMap, eventHandler) + applySuccess(typeMap.enrollment, jobObjectsMap, enrollmentHandler) + applySuccess(typeMap.trackedEntity, jobObjectsMap, trackedEntityHandler) } } - private fun applySuccess(typeReport: JobTypeReport, typeHandler: JobReportTypeHandler) { - typeReport.objectReports.forEach { objectReport -> - typeHandler.handleSuccess(objectReport.uid) - } + private fun applySuccess( + typeReport: JobTypeReport, + jobObjects: Map, List>, + typeHandler: JobReportTypeHandler + ) { + typeReport.objectReports + .filter { jobObjects.containsKey(Pair(it.trackerType, it.uid)) } + .forEach { typeHandler.handleSuccess(it.uid) } } } From 7485120e7996dd5a7e7e8be2c557f993a4ab896a Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 22 Apr 2021 15:29:27 +0200 Subject: [PATCH 054/308] [ANDROSDK-1310-3] Handle not present objects --- .../importer/internal/JobReportHandler.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 7bbaf897e0..ddf5c4c085 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY @@ -42,6 +43,12 @@ internal class JobReportHandler @Inject internal constructor( fun handle(o: JobReport, jobObjects: List) { val jobObjectsMap = jobObjects.groupBy { jo -> Pair(jo.objectType(), jo.objectUid()) } + handleErrors(o, jobObjectsMap) + handleSuccesses(o, jobObjectsMap) + handleNotPresentObjects(o, jobObjects) + } + + private fun handleErrors(o: JobReport, jobObjectsMap: Map, List>) { o.validationReport.errorReports.forEach { errorReport -> if (jobObjectsMap.containsKey(Pair(errorReport.trackerType, errorReport.uid))) { when (errorReport.trackerType) { @@ -52,7 +59,9 @@ internal class JobReportHandler @Inject internal constructor( } } } + } + private fun handleSuccesses(o: JobReport, jobObjectsMap: Map, List>) { if (o.bundleReport != null) { val typeMap = o.bundleReport.typeReportMap applySuccess(typeMap.event, jobObjectsMap, eventHandler) @@ -61,6 +70,35 @@ internal class JobReportHandler @Inject internal constructor( } } + private fun handleNotPresentObjects( + o: JobReport, + jobObjectsMap: List + ) { + val presentSuccesses = if (o.bundleReport == null) emptySet>() else { + val tm = o.bundleReport.typeReportMap + setOf(tm.event, tm.trackedEntity, tm.enrollment, tm.relationship).flatMap { + it.objectReports + }.map { Pair(it.trackerType, it.uid) } + } + + val presentErrors = o.validationReport.errorReports.map { + Pair(it.trackerType, it.uid) + }.toSet() + + val expectedObjects = jobObjectsMap.map { Pair(it.objectType(), it.objectUid()) } + + val notPresentObjects = expectedObjects - presentSuccesses - presentErrors + + for (p in notPresentObjects) { + when (p.first) { + EVENT -> eventHandler.handleObject(p.second, State.TO_UPDATE) + ENROLLMENT -> enrollmentHandler.handleObject(p.second, State.TO_UPDATE) + TRACKED_ENTITY -> trackedEntityHandler.handleObject(p.second, State.TO_UPDATE) + else -> println("Unsupported type") // TODO + } + } + } + private fun applySuccess( typeReport: JobTypeReport, jobObjects: Map, List>, From 890a74754adc53e5bba67bd617ed1835e16b43f2 Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 22 Apr 2021 16:15:05 +0200 Subject: [PATCH 055/308] [ANDROSDK-1310-3] Detekt --- .../core/tracker/importer/internal/JobQueryCall.kt | 12 +++++++++--- .../tracker/importer/internal/JobReportHandler.kt | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index 4d9f25f248..316227768a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -53,9 +53,11 @@ internal class JobQueryCall @Inject internal constructor( .groupBy { it.jobUid() } .toList() - pendingJobs.withIndex().map { ij -> Pair(ij.value, ij.index == pendingJobs.size - 1) } + pendingJobs.withIndex().map { + Triple(it.value.first, it.value.second, it.index == pendingJobs.size - 1) + } } - .flatMap { jobPairIndex -> queryJob(jobPairIndex.first.first, jobPairIndex.first.second, jobPairIndex.second) } + .flatMap { queryJob(it.first, it.second, it.third) } } fun queryJob(jobId: String): Observable { @@ -64,7 +66,11 @@ internal class JobQueryCall @Inject internal constructor( return queryJob(jobId, jobObjects, true) } - private fun queryJob(jobId: String, jobObjects: List, isLastJob: Boolean): Observable { + private fun queryJob( + jobId: String, + jobObjects: List, + isLastJob: Boolean + ): Observable { val progressManager = D2ProgressManager(null) @Suppress("MagicNumber") return Observable.interval(0, 5, TimeUnit.SECONDS) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index ddf5c4c085..a841e6bb52 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -28,11 +28,11 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY -import javax.inject.Inject @Reusable internal class JobReportHandler @Inject internal constructor( @@ -85,7 +85,7 @@ internal class JobReportHandler @Inject internal constructor( Pair(it.trackerType, it.uid) }.toSet() - val expectedObjects = jobObjectsMap.map { Pair(it.objectType(), it.objectUid()) } + val expectedObjects = jobObjectsMap.map { Pair(it.objectType(), it.objectUid()) } val notPresentObjects = expectedObjects - presentSuccesses - presentErrors From 37feb0cf710a5cde753632b7e049307fd355ec3b Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 22 Apr 2021 17:01:27 +0200 Subject: [PATCH 056/308] feat: [ANDROSDK-1349] Request pending jobs before uploading --- .../core/event/EventCollectionRepository.java | 19 +++++++++++++------ ...kedEntityInstanceCollectionRepository.java | 18 +++++++++++++----- .../tracker/importer/internal/JobQueryCall.kt | 13 ++++++++----- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java index d48199161c..3ceeafd203 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java @@ -50,6 +50,7 @@ import org.hisp.dhis.android.core.event.internal.EventStore; import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo; import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValueTableInfo; +import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall; import java.util.Collections; import java.util.List; @@ -72,6 +73,7 @@ public final class EventCollectionRepository private final EventStore store; private final DataStatePropagator dataStatePropagator; + private final JobQueryCall jobQueryCall; @Inject EventCollectionRepository(final EventStore store, @@ -79,21 +81,26 @@ public final class EventCollectionRepository final RepositoryScope scope, final EventPostParentCall postCall, final Transformer transformer, - final DataStatePropagator dataStatePropagator) { + final DataStatePropagator dataStatePropagator, + final JobQueryCall jobQueryCall) { super(store, childrenAppenders, scope, transformer, new FilterConnectorFactory<>(scope, s -> new EventCollectionRepository( - store, childrenAppenders, s, postCall, transformer, dataStatePropagator))); + store, childrenAppenders, s, postCall, transformer, dataStatePropagator, jobQueryCall))); this.store = store; this.postCall = postCall; this.dataStatePropagator = dataStatePropagator; + this.jobQueryCall = jobQueryCall; } @Override public Observable upload() { - return Observable.fromCallable(() -> byState().in(State.uploadableStates()) - .byEnrollmentUid().isNull() - .blockingGetWithoutChildren()) - .flatMap(postCall::uploadEvents); + return Observable.concat( + jobQueryCall.queryPendingJobs(), + Observable.fromCallable(() -> byState().in(State.uploadableStates()) + .byEnrollmentUid().isNull() + .blockingGetWithoutChildren()) + .flatMap(postCall::uploadEvents) + ); } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java index afbc1bf078..2d52e1dd64 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java @@ -47,6 +47,7 @@ import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceFields; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceParentPostCall; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; +import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall; import java.util.List; import java.util.Map; @@ -65,6 +66,7 @@ public final class TrackedEntityInstanceCollectionRepository private final TrackedEntityInstanceParentPostCall postCall; private final TrackedEntityInstanceStore store; + private final JobQueryCall jobQueryCall; @Inject TrackedEntityInstanceCollectionRepository( @@ -72,18 +74,24 @@ public final class TrackedEntityInstanceCollectionRepository final Map> childrenAppenders, final RepositoryScope scope, final Transformer transformer, - final TrackedEntityInstanceParentPostCall postCall) { + final TrackedEntityInstanceParentPostCall postCall, + final JobQueryCall jobQueryCall) { super(store, childrenAppenders, scope, transformer, new FilterConnectorFactory<>(scope, s -> - new TrackedEntityInstanceCollectionRepository(store, childrenAppenders, s, transformer, postCall))); + new TrackedEntityInstanceCollectionRepository(store, childrenAppenders, s, transformer, postCall, + jobQueryCall))); this.postCall = postCall; this.store = store; + this.jobQueryCall = jobQueryCall; } @Override public Observable upload() { - return Observable.fromCallable(() -> - byState().in(State.uploadableStates()).blockingGetWithoutChildren() - ).flatMap(postCall::uploadTrackedEntityInstances); + return Observable.concat( + jobQueryCall.queryPendingJobs(), + Observable.fromCallable(() -> + byState().in(State.uploadableStates()).blockingGetWithoutChildren() + ).flatMap(postCall::uploadTrackedEntityInstances) + ); } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index 316227768a..32157265a2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -37,6 +37,8 @@ import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +internal const val ATTEMPTS_AFTER_UPLOAD = 3 +internal const val ATTEMPTS_WHEN_QUERYING = 1 @Reusable internal class JobQueryCall @Inject internal constructor( private val service: TrackerImporterService, @@ -57,19 +59,20 @@ internal class JobQueryCall @Inject internal constructor( Triple(it.value.first, it.value.second, it.index == pendingJobs.size - 1) } } - .flatMap { queryJob(it.first, it.second, it.third) } + .flatMap { queryJobForever(it.first, it.second, it.third, ATTEMPTS_WHEN_QUERYING) } } fun queryJob(jobId: String): Observable { val jobObjects = trackerJobObjectStore.selectAll() .filter { it.jobUid() == jobId } - return queryJob(jobId, jobObjects, true) + return queryJobForever(jobId, jobObjects, true, ATTEMPTS_AFTER_UPLOAD) } - private fun queryJob( + private fun queryJobForever( jobId: String, jobObjects: List, - isLastJob: Boolean + isLastJob: Boolean, + attempts: Int ): Observable { val progressManager = D2ProgressManager(null) @Suppress("MagicNumber") @@ -89,7 +92,7 @@ internal class JobQueryCall @Inject internal constructor( handler.handle(jobReport, jobObjects) } } - .take(3) + .take(attempts.toLong()) .map { progressManager.increaseProgress( JobReport::class.java, From 382413feba27b1f9153d9397af63d3d5ddb725cb Mon Sep 17 00:00:00 2001 From: luis Date: Thu, 22 Apr 2021 17:29:56 +0200 Subject: [PATCH 057/308] feat: [RENAME-TRACKER-TYPE] Rename objectType -> trackerType for consistency with job report --- .../android/core/wipe/WipeDBCallMockIntegrationShould.java | 2 +- core/src/main/assets/migrations/99.sql | 2 +- core/src/main/assets/snapshots/99.sql | 2 +- .../core/event/internal/EventTrackerImporterPostCall.kt | 2 +- .../core/tracker/importer/internal/JobReportHandler.kt | 4 ++-- .../importer/internal/JobReportTrackedEntityHandler.kt | 2 -- .../TrackedEntityInstanceTrackerImporterPostCall.kt | 2 +- .../core/tracker/importer/internal/TrackerJobObject.java | 4 ++-- .../core/tracker/importer/internal/TrackerJobObjectStore.kt | 6 +++--- .../importer/internal/TrackerJobObjectTableInfo.java | 6 +++--- .../tracker/importer/internal/TrackerJobObjectSamples.java | 2 +- 11 files changed, 16 insertions(+), 18 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index 1c4354bc6f..bcce35a56b 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -93,7 +93,7 @@ private void givenOthersInDatabase() { TrackerJobObjectStore.create(databaseAdapter).insert( TrackerJobObject.builder() .jobUid("uid") - .objectType("type") + .trackerType("type") .objectUid("oUid") .lastUpdated(new Date()) .build() diff --git a/core/src/main/assets/migrations/99.sql b/core/src/main/assets/migrations/99.sql index cb7bd351f4..9422b0e887 100644 --- a/core/src/main/assets/migrations/99.sql +++ b/core/src/main/assets/migrations/99.sql @@ -1,3 +1,3 @@ # New table for tracker importer DROP TABLE TrackerJob; -CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); +CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); diff --git a/core/src/main/assets/snapshots/99.sql b/core/src/main/assets/snapshots/99.sql index 663d0a8102..938a4ece5b 100644 --- a/core/src/main/assets/snapshots/99.sql +++ b/core/src/main/assets/snapshots/99.sql @@ -109,4 +109,4 @@ CREATE TABLE Attribute (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL CREATE TABLE ProgramStageAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, programStage TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (programStage, attribute)); CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, attribute)); CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); -CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, objectType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); +CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index 2de68ded3d..cbc3de3f9a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -83,7 +83,7 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( return events.map { TrackerJobObject .builder() - .objectType(EVENT) + .trackerType(EVENT) .objectUid(it.uid()) .jobUid(jobUid) .lastUpdated(lastUpdated) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index a841e6bb52..e2c6de97ae 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -42,7 +42,7 @@ internal class JobReportHandler @Inject internal constructor( ) { fun handle(o: JobReport, jobObjects: List) { - val jobObjectsMap = jobObjects.groupBy { jo -> Pair(jo.objectType(), jo.objectUid()) } + val jobObjectsMap = jobObjects.groupBy { jo -> Pair(jo.trackerType(), jo.objectUid()) } handleErrors(o, jobObjectsMap) handleSuccesses(o, jobObjectsMap) handleNotPresentObjects(o, jobObjects) @@ -85,7 +85,7 @@ internal class JobReportHandler @Inject internal constructor( Pair(it.trackerType, it.uid) }.toSet() - val expectedObjects = jobObjectsMap.map { Pair(it.objectType(), it.objectUid()) } + val expectedObjects = jobObjectsMap.map { Pair(it.trackerType(), it.objectUid()) } val notPresentObjects = expectedObjects - presentSuccesses - presentErrors diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt index 51c0c0aaf4..db1c618626 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -44,8 +44,6 @@ internal class JobReportTrackedEntityHandler @Inject internal constructor( override fun handleObject(uid: String, state: State) { trackedEntityStore.setState(uid, state) conflictStore.deleteTrackedEntityConflicts(uid) - // TODO setRelationshipsState?? - // TODO handle enrollments } override fun storeConflict(errorReport: JobValidationError) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 6b522916e0..68fb49bc6f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -105,7 +105,7 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con ): List { return objects.map { builder - .objectType(objectType) + .trackerType(objectType) .objectUid(it.uid()) .build() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java index 2eed2965fd..66dd59b4ab 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java @@ -47,7 +47,7 @@ public abstract class TrackerJobObject extends BaseObject { @NonNull - public abstract String objectType(); + public abstract String trackerType(); @NonNull public abstract String objectUid(); @@ -75,7 +75,7 @@ public static Builder builder() { @AutoValue.Builder @JsonPOJOBuilder(withPrefix = "") public abstract static class Builder extends BaseObject.Builder { - public abstract Builder objectType(String objectType); + public abstract Builder trackerType(String trackerType); public abstract Builder objectUid(String objectUid); diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt index 1a1a35c22a..080ce64bde 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectStore.kt @@ -38,19 +38,19 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWit internal object TrackerJobObjectStore { private val BINDER = StatementBinder { o: TrackerJobObject, w: StatementWrapper -> - w.bind(1, o.objectType()) + w.bind(1, o.trackerType()) w.bind(2, o.objectUid()) w.bind(3, o.jobUid()) w.bind(4, o.lastUpdated()) } private val WHERE_UPDATE_BINDER = WhereStatementBinder { o: TrackerJobObject, w: StatementWrapper -> - w.bind(5, o.objectType()) + w.bind(5, o.trackerType()) w.bind(6, o.objectUid()) } private val DELETE_UPDATE_BINDER = WhereStatementBinder { o: TrackerJobObject, w: StatementWrapper -> - w.bind(1, o.objectType()) + w.bind(1, o.trackerType()) w.bind(2, o.objectUid()) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java index 8a771454c3..493f59ddb4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObjectTableInfo.java @@ -54,7 +54,7 @@ public CoreColumns columns() { public static class Columns extends CoreColumns { - public static final String OBJECT_TYPE = "objectType"; + public static final String TRACKER_TYPE = "trackerType"; public static final String OBJECT_UID = "objectUid"; public static final String JOB_UID = "jobUid"; @@ -62,12 +62,12 @@ public static class Columns extends CoreColumns { @Override public String[] all() { return CollectionsHelper.appendInNewArray(super.all(), - OBJECT_TYPE, OBJECT_UID, JOB_UID, LAST_UPDATED); + TRACKER_TYPE, OBJECT_UID, JOB_UID, LAST_UPDATED); } @Override public String[] whereUpdate() { - return new String[]{OBJECT_TYPE, OBJECT_UID}; + return new String[]{TRACKER_TYPE, OBJECT_UID}; } } } diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java index f58965e980..c8d5417b9a 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java @@ -38,7 +38,7 @@ public class TrackerJobObjectSamples { public static TrackerJobObject get1() { return TrackerJobObject.builder() .id(1L) - .objectType(EVENT) + .trackerType(EVENT) .objectUid("oUid") .jobUid("jUid") .lastUpdated(parseDate("2017-11-29T11:27:46.935")) From 9043c8db6742c76b3e26a9bc95dd51311983a2ec Mon Sep 17 00:00:00 2001 From: luis Date: Mon, 26 Apr 2021 12:54:26 +0200 Subject: [PATCH 058/308] feat: [ANDROSDK-1371] Remove unnecessary job info call --- .../core/tracker/importer/internal/JobInfo.kt | 42 -------------- .../tracker/importer/internal/JobQueryCall.kt | 41 ++++++-------- .../internal/TrackerImporterService.kt | 3 - .../core/tracker/importer/JobInfoShould.kt | 56 ------------------- 4 files changed, 18 insertions(+), 124 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobInfo.kt delete mode 100644 core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobInfoShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobInfo.kt deleted file mode 100644 index 642696b5c4..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobInfo.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.tracker.importer.internal - -import com.gabrielittner.auto.value.cursor.ColumnAdapter -import java.util.Date -import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbDateColumnAdapter - -internal data class JobInfo( - val id: String, - val uid: String, - val level: String, - val category: String, - @ColumnAdapter(DbDateColumnAdapter::class) val time: Date, - val message: String, - val completed: Boolean -) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index 32157265a2..c245b7fa62 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -59,16 +59,16 @@ internal class JobQueryCall @Inject internal constructor( Triple(it.value.first, it.value.second, it.index == pendingJobs.size - 1) } } - .flatMap { queryJobForever(it.first, it.second, it.third, ATTEMPTS_WHEN_QUERYING) } + .flatMap { queryJobInternal(it.first, it.second, it.third, ATTEMPTS_WHEN_QUERYING) } } fun queryJob(jobId: String): Observable { val jobObjects = trackerJobObjectStore.selectAll() .filter { it.jobUid() == jobId } - return queryJobForever(jobId, jobObjects, true, ATTEMPTS_AFTER_UPLOAD) + return queryJobInternal(jobId, jobObjects, true, ATTEMPTS_AFTER_UPLOAD) } - private fun queryJobForever( + private fun queryJobInternal( jobId: String, jobObjects: List, isLastJob: Boolean, @@ -78,20 +78,14 @@ internal class JobQueryCall @Inject internal constructor( @Suppress("MagicNumber") return Observable.interval(0, 5, TimeUnit.SECONDS) .map { - apiCallExecutor.executeObjectCall(service.getJob(jobId)) - } - .map { it.any { ji -> ji.completed } } - .takeUntil { it } - .doOnNext { - if (it) { - val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) - val whereClause = WhereClauseBuilder() - .appendKeyStringValue(TrackerJobObjectTableInfo.Columns.JOB_UID, jobId) - .build() - trackerJobObjectStore.deleteWhere(whereClause) - handler.handle(jobReport, jobObjects) + try { + downloadAndHandle(jobId, jobObjects) + true + } catch (_: Throwable) { + false } } + .takeUntil { it } .take(attempts.toLong()) .map { progressManager.increaseProgress( @@ -99,13 +93,14 @@ internal class JobQueryCall @Inject internal constructor( it && isLastJob ) } - .onErrorResumeNext { _: Throwable -> - return@onErrorResumeNext Observable.just( - progressManager.increaseProgress( - JobReport::class.java, - false - ) - ) - } + } + + private fun downloadAndHandle(jobId: String, jobObjects: List) { + val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(TrackerJobObjectTableInfo.Columns.JOB_UID, jobId) + .build() + trackerJobObjectStore.deleteWhere(whereClause) + handler.handle(jobReport, jobObjects) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt index 8a6a18b651..f920eab6df 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt @@ -59,9 +59,6 @@ internal interface TrackerImporterService { @Query(IMPORT_STRATEGY) importStrategy: String ): Call - @GET("$JOBS_URL{jobId}") - fun getJob(@Path(JOB_ID) jobId: String): Call> - @GET("$JOBS_URL{jobId}/report") fun getJobReport(@Path(JOB_ID) jobId: String): Call } diff --git a/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobInfoShould.kt b/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobInfoShould.kt deleted file mode 100644 index ae47292e46..0000000000 --- a/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobInfoShould.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.tracker.importer - -import com.google.common.truth.Truth.assertThat -import java.io.IOException -import java.text.ParseException -import org.hisp.dhis.android.core.Inject -import org.hisp.dhis.android.core.common.BaseIdentifiableObject -import org.hisp.dhis.android.core.common.BaseObjectShould -import org.hisp.dhis.android.core.common.ObjectShould -import org.hisp.dhis.android.core.tracker.importer.internal.JobInfo -import org.junit.Test - -class JobInfoShould : BaseObjectShould("tracker/importer/jobinfo.json"), ObjectShould { - - @Test - @Throws(IOException::class, ParseException::class) - override fun map_from_json_string() { - val objectMapper = Inject.objectMapper() - val jobInfo = objectMapper.readValue(jsonStream, JobInfo::class.java) - - assertThat(jobInfo.id).isEqualTo("id") - assertThat(jobInfo.uid).isEqualTo("uid") - assertThat(jobInfo.level).isEqualTo("INFO") - assertThat(jobInfo.category).isEqualTo("TRACKER_IMPORT_JOB") - assertThat(jobInfo.time).isEqualTo(BaseIdentifiableObject.DATE_FORMAT.parse("2021-01-25T12:09:18.571")) - assertThat(jobInfo.message).isEqualTo("(android) Import:Done took 0.360910 sec.") - assertThat(jobInfo.completed).isTrue() - } -} From 9ed3a05b2ea3430f28aa76953923580ee1ec9fb8 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 27 Apr 2021 14:55:03 +0200 Subject: [PATCH 059/308] [RENAME-PARENT-CALL] Rename TEI post parent call (consistent with event) --- .../TrackedEntityInstanceCollectionRepository.java | 6 +++--- ...ntPostCall.kt => TrackedEntityInstancePostParentCall.kt} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/{TrackedEntityInstanceParentPostCall.kt => TrackedEntityInstancePostParentCall.kt} (97%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java index 2d52e1dd64..df2b8eb566 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java @@ -45,7 +45,7 @@ import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo.Columns; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceFields; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceParentPostCall; +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstancePostParentCall; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall; @@ -64,7 +64,7 @@ public final class TrackedEntityInstanceCollectionRepository implements ReadWriteWithUploadWithUidCollectionRepository { - private final TrackedEntityInstanceParentPostCall postCall; + private final TrackedEntityInstancePostParentCall postCall; private final TrackedEntityInstanceStore store; private final JobQueryCall jobQueryCall; @@ -74,7 +74,7 @@ public final class TrackedEntityInstanceCollectionRepository final Map> childrenAppenders, final RepositoryScope scope, final Transformer transformer, - final TrackedEntityInstanceParentPostCall postCall, + final TrackedEntityInstancePostParentCall postCall, final JobQueryCall jobQueryCall) { super(store, childrenAppenders, scope, transformer, new FilterConnectorFactory<>(scope, s -> new TrackedEntityInstanceCollectionRepository(store, childrenAppenders, s, transformer, postCall, diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceParentPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostParentCall.kt similarity index 97% rename from core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceParentPostCall.kt rename to core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostParentCall.kt index a7a2e543fe..ef5e820c02 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceParentPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostParentCall.kt @@ -35,7 +35,7 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.tracker.importer.internal.TrackedEntityInstanceTrackerImporterPostCall @Reusable -internal class TrackedEntityInstanceParentPostCall @Inject internal constructor( +internal class TrackedEntityInstancePostParentCall @Inject internal constructor( private val oldCall: OldTrackedEntityInstancePostCall, private val trackerImporterCall: TrackedEntityInstanceTrackerImporterPostCall ) { From 2dcbba55d44aa910addc09fa2e44de2ecc964911 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 10 May 2021 16:46:11 +0200 Subject: [PATCH 060/308] [androsdk-1334] Add Email and Phone validation --- .../dhis/android/core/common/ValueType.kt | 4 +- .../validation/failures/EmailFailure.kt | 33 +++++++++++ .../validation/failures/PhoneNumberFailure.kt | 33 +++++++++++ .../validation/validators/EmailValidator.kt | 57 +++++++++++++++++++ .../validators/PhoneNumberValidator.kt | 49 ++++++++++++++++ .../validators/EmailValidatorShould.kt | 49 ++++++++++++++++ .../validators/PhoneNumberValidatorShould.kt | 51 +++++++++++++++++ 7 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/EmailFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PhoneNumberFailure.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index f53c9c7da7..d4ac791271 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -50,8 +50,8 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) INTEGER_ZERO_OR_POSITIVE(Int::class.java, IntegerZeroOrPositiveValidator), FILE_RESOURCE(String::class.java, UidValidator), COORDINATE(String::class.java, CoordinateValidator), - PHONE_NUMBER(String::class.java, DefaultValidator), - EMAIL(String::class.java, DefaultValidator), + PHONE_NUMBER(String::class.java, PhoneNumberValidator), + EMAIL(String::class.java, EmailValidator), USERNAME(String::class.java, TextValidator), ORGANISATION_UNIT(OrganisationUnit::class.java, UidValidator), TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, DefaultValidator), diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/EmailFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/EmailFailure.kt new file mode 100644 index 0000000000..cbb3493ffd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/EmailFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class EmailFailure : Throwable() { + object MalformedEmailException : EmailFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PhoneNumberFailure.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PhoneNumberFailure.kt new file mode 100644 index 0000000000..4b291084dd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/PhoneNumberFailure.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.failures + +sealed class PhoneNumberFailure : Throwable() { + object MalformedPhoneNumberException : PhoneNumberFailure() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt new file mode 100644 index 0000000000..c7f453b721 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.EmailFailure + +object EmailValidator : ValueTypeValidator { + + private const val EMAIL_RFC_5322_PATTERN = "^(?:[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#\$%&'*+/=?^_`{|}~" + + "-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c" + + "\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:" + + "(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?" + + "[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\" + + "x09\\x0b\\x0c\\x0e-\\x7f])+)\\])\n$" + private val EMAIL_RFC_5322_REGEX = EMAIL_RFC_5322_PATTERN.toRegex() + + private val EMAIL_PATTERN = "^(.+)@(\\S+)$".toRegex() + + override fun validate(value: String): Result { + // TODO Review pattern used + return when (value.matches(EMAIL_PATTERN)) { + true -> { + Result.Success(value) + } + else -> { + Result.Failure(EmailFailure.MalformedEmailException) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt new file mode 100644 index 0000000000..9ee15ac084 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.PhoneNumberFailure + +object PhoneNumberValidator : ValueTypeValidator { + + private val INTERNATIONAL_PHONE_PATTERN = "^(\\+)?(?:[0-9].?){4,14}[0-9]$".toRegex() + + override fun validate(value: String): Result { + // TODO Review pattern used + return when (value.matches(INTERNATIONAL_PHONE_PATTERN)) { + true -> { + Result.Success(value) + } + else -> { + Result.Failure(PhoneNumberFailure.MalformedPhoneNumberException) + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt new file mode 100644 index 0000000000..cba72661a4 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.EmailFailure +import org.junit.Test + +class EmailValidatorShould : ValidatorShouldHelper(EmailValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("email@email.com") + valueShouldSuccess("email.123@email.com") + valueShouldSuccess("email.email@email.123.com") + valueShouldSuccess(".@1.1") + } + + @Test + fun `Should fail when value is malformed`() { + valueShouldFail("5fe2", EmailFailure.MalformedEmailException) + //valueShouldFail("email@email", EmailFailure.MalformedEmailException) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt new file mode 100644 index 0000000000..43babdf2c9 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.PhoneNumberFailure +import org.junit.Test + +class PhoneNumberValidatorShould : ValidatorShouldHelper(PhoneNumberValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("652214478") + valueShouldSuccess("+34 521 587 422") + valueShouldSuccess("0034 521 587 422") + valueShouldSuccess("0034521587422") + valueShouldSuccess("+34521587422") + } + + @Test + fun `Should fail with a number format exception when value is malformed`() { + valueShouldFail("5fe2", PhoneNumberFailure.MalformedPhoneNumberException) + valueShouldFail("987", PhoneNumberFailure.MalformedPhoneNumberException) + valueShouldFail("", PhoneNumberFailure.MalformedPhoneNumberException) + } +} From e98d8c99b7048ba48a7f6282b470d51daeaf3ea1 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 10 May 2021 17:52:16 +0200 Subject: [PATCH 061/308] [androsdk-1334] Add Url validation --- .../dhis/android/core/common/ValueType.kt | 8 +-- .../UrlFailure.kt} | 10 +--- .../validation/validators/UrlValidator.kt | 45 +++++++++++++++ .../validators/UrlValidatorShould.kt | 55 +++++++++++++++++++ 4 files changed, 107 insertions(+), 11 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/{validators/DefaultValidator.kt => failures/UrlFailure.kt} (82%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index d4ac791271..995911faa3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -54,10 +54,10 @@ enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) EMAIL(String::class.java, EmailValidator), USERNAME(String::class.java, TextValidator), ORGANISATION_UNIT(OrganisationUnit::class.java, UidValidator), - TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, DefaultValidator), - AGE(Date::class.java, DefaultValidator), - URL(String::class.java, DefaultValidator), - IMAGE(String::class.java, DefaultValidator); + TRACKER_ASSOCIATE(TrackedEntityInstance::class.java, UidValidator), + AGE(Date::class.java, DateValidator), + URL(String::class.java, TextValidator), + IMAGE(String::class.java, UidValidator); val isInteger: Boolean get() = INTEGER_TYPES.contains(this) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UrlFailure.kt similarity index 82% rename from core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt rename to core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UrlFailure.kt index 29c678c2a9..88c5af8a85 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DefaultValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/failures/UrlFailure.kt @@ -26,12 +26,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.common.valuetype.validation.validators +package org.hisp.dhis.android.core.common.valuetype.validation.failures -import org.hisp.dhis.android.core.arch.helpers.Result - -object DefaultValidator : ValueTypeValidator { - override fun validate(value: String): Result { - return Result.Success(value) - } +sealed class UrlFailure : Throwable() { + object MalformedUrlException : UrlFailure() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt new file mode 100644 index 0000000000..80a6b554e9 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.arch.helpers.Result +import org.hisp.dhis.android.core.common.valuetype.validation.failures.UrlFailure +import java.net.MalformedURLException +import java.net.URL + +object UrlValidator : ValueTypeValidator { + override fun validate(value: String): Result { + return try { + URL(value) + Result.Success(value) + } catch (e: MalformedURLException) { + Result.Failure(UrlFailure.MalformedUrlException) + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt new file mode 100644 index 0000000000..635576bb82 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.valuetype.validation.validators + +import org.hisp.dhis.android.core.common.valuetype.validation.failures.UrlFailure +import org.junit.Test + +class UrlValidatorShould : ValidatorShouldHelper(UrlValidator) { + + @Test + fun `Should success when passing valid values`() { + valueShouldSuccess("https://dhis2.org/resources/") + valueShouldSuccess("http://www.dhis2.org") + valueShouldSuccess("http://dhis2.org") + valueShouldSuccess("https://dhis2.org") + valueShouldSuccess("http://localhost:4200/demo") + + // TODO Review what to do with those urls + //valueShouldSuccess("dhis2.org") + //valueShouldSuccess("dhis2.org/demo") + //valueShouldSuccess("www.dhis2.org") + //valueShouldSuccess("255.255.255.255") + } + + @Test + fun `Should fail when value is malformed`() { + valueShouldFail("5fe2", UrlFailure.MalformedUrlException) + } +} From c9eeca476f5187e6a203a46b44331c4af4c65028 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 11 May 2021 17:38:53 +0200 Subject: [PATCH 062/308] [androsdk-1334] ktlinFormat --- .../validation/validators/CoordinateValidator.kt | 4 ++-- .../validation/validators/DateTimeValidator.kt | 2 +- .../valuetype/validation/validators/EmailValidator.kt | 10 +++++----- .../validation/validators/IntegerNegativeValidator.kt | 6 ++++-- .../validation/validators/IntegerPositiveValidator.kt | 9 ++++----- .../validators/IntegerZeroOrPositiveValidator.kt | 6 ++++-- .../validation/validators/PercentageValidator.kt | 6 ++++-- .../valuetype/validation/validators/TextValidator.kt | 4 +++- .../valuetype/validation/validators/UidValidator.kt | 5 +++-- .../validation/validators/ValueTypeValidator.kt | 2 +- .../validation/validators/EmailValidatorShould.kt | 2 +- .../validators/PhoneNumberValidatorShould.kt | 1 + .../validation/validators/UrlValidatorShould.kt | 8 ++++---- 13 files changed, 37 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt index c3277a2e2d..aeba8d1e50 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/CoordinateValidator.kt @@ -34,8 +34,8 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.Coordinat object CoordinateValidator : ValueTypeValidator { private val COORDINATE_PATTERN = - "^\\[[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)]\$" - .toRegex() + "^\\[[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)]\$" + .toRegex() override fun validate(value: String): Result { return when (value.matches(COORDINATE_PATTERN)) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt index 62d3a007a0..c488e99032 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/DateTimeValidator.kt @@ -34,7 +34,7 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.DateTimeF object DateTimeValidator : ValueTypeValidator { private val DATE_TIME_PATTERN = - "^(\\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01]))T(([0-1]?[0-9]|2[0-3]):[0-5][0-9])\$".toRegex() + "^(\\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01]))T(([0-1]?[0-9]|2[0-3]):[0-5][0-9])\$".toRegex() override fun validate(value: String): Result { return when (value.matches(DATE_TIME_PATTERN)) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt index c7f453b721..3df946c1c2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt @@ -34,11 +34,11 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.EmailFail object EmailValidator : ValueTypeValidator { private const val EMAIL_RFC_5322_PATTERN = "^(?:[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#\$%&'*+/=?^_`{|}~" + - "-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c" + - "\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:" + - "(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?" + - "[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\" + - "x09\\x0b\\x0c\\x0e-\\x7f])+)\\])\n$" + "-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c" + + "\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:" + + "(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?" + + "[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\" + + "x09\\x0b\\x0c\\x0e-\\x7f])+)\\])\n$" private val EMAIL_RFC_5322_REGEX = EMAIL_RFC_5322_PATTERN.toRegex() private val EMAIL_PATTERN = "^(.+)@(\\S+)$".toRegex() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt index ce6bf6fa17..c3ac66d395 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerNegativeValidator.kt @@ -47,8 +47,10 @@ object IntegerNegativeValidator : IntegerValidatorBase() } } } catch (e: NumberFormatException) { - catchOverflowFailure(value, IntegerNegativeFailure.IntegerOverflow, - IntegerNegativeFailure.NumberFormatException) + catchOverflowFailure( + value, IntegerNegativeFailure.IntegerOverflow, + IntegerNegativeFailure.NumberFormatException + ) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt index 3bb924d09c..c7c20d631d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerPositiveValidator.kt @@ -42,16 +42,15 @@ object IntegerPositiveValidator : IntegerValidatorBase() convertedValue < 0 -> { Result.Failure(IntegerPositiveFailure.ValueIsNegative) } - convertedValue < 0 -> { - Result.Failure(IntegerPositiveFailure.ValueIsNegative) - } else -> { Result.Success(value) } } } catch (e: NumberFormatException) { - catchOverflowFailure(value, IntegerPositiveFailure.IntegerOverflow, - IntegerPositiveFailure.NumberFormatException) + catchOverflowFailure( + value, IntegerPositiveFailure.IntegerOverflow, + IntegerPositiveFailure.NumberFormatException + ) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt index 8f34c7b665..d6502d6893 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/IntegerZeroOrPositiveValidator.kt @@ -44,8 +44,10 @@ object IntegerZeroOrPositiveValidator : IntegerValidatorBase { + private const val ONE_HUNDRED_PERCENT = 100 + private const val ZERO_PERCENT = 0 override fun validate(value: String): Result { return try { val convertedValue = value.toInt() when { - convertedValue > 100 -> { + convertedValue > ONE_HUNDRED_PERCENT -> { Result.Failure(PercentageFailure.ValueGreaterThan100) } - convertedValue < 0 -> { + convertedValue < ZERO_PERCENT -> { Result.Failure(PercentageFailure.ValueIsNegative) } else -> { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt index 43dd4354cc..c3856fd5a7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/TextValidator.kt @@ -32,8 +32,10 @@ import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.TextFailure object TextValidator : ValueTypeValidator { + private const val MAX_CHARS = 50000 + override fun validate(value: String): Result { - return if (value.count() > 50000) { + return if (value.count() > MAX_CHARS) { Result.Failure(TextFailure.TooLargeTextException) } else { Result.Success(value) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt index 36ebac1069..487dc3d447 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UidValidator.kt @@ -34,16 +34,17 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.UidFailur object UidValidator : ValueTypeValidator { private val UID_PATTERN = "^[a-zA-Z0-9]{11}\$".toRegex() + private const val NUMBER_OF_UID_CHARS = 11 override fun validate(value: String): Result { return when { value.matches(UID_PATTERN) -> { Result.Success(value) } - value.length < 11 -> { + value.length < NUMBER_OF_UID_CHARS -> { Result.Failure(UidFailure.LessThanElevenCharsException) } - value.length > 11 -> { + value.length > NUMBER_OF_UID_CHARS -> { Result.Failure(UidFailure.MoreThanElevenCharsException) } else -> { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt index 35503412de..eeced85940 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/ValueTypeValidator.kt @@ -30,6 +30,6 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result -interface ValueTypeValidator { +interface ValueTypeValidator { fun validate(value: String): Result } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt index cba72661a4..b951f52cfa 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt @@ -44,6 +44,6 @@ class EmailValidatorShould : ValidatorShouldHelper(EmailValidator) @Test fun `Should fail when value is malformed`() { valueShouldFail("5fe2", EmailFailure.MalformedEmailException) - //valueShouldFail("email@email", EmailFailure.MalformedEmailException) + // valueShouldFail("email@email", EmailFailure.MalformedEmailException) } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt index 43babdf2c9..926b55cd9b 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt @@ -40,6 +40,7 @@ class PhoneNumberValidatorShould : ValidatorShouldHelper(Pho valueShouldSuccess("0034 521 587 422") valueShouldSuccess("0034521587422") valueShouldSuccess("+34521587422") + // valueShouldSuccess("+34 (521)-58 7422") } @Test diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt index 635576bb82..5f7d0cce7c 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt @@ -42,10 +42,10 @@ class UrlValidatorShould : ValidatorShouldHelper(UrlValidator) { valueShouldSuccess("http://localhost:4200/demo") // TODO Review what to do with those urls - //valueShouldSuccess("dhis2.org") - //valueShouldSuccess("dhis2.org/demo") - //valueShouldSuccess("www.dhis2.org") - //valueShouldSuccess("255.255.255.255") + // valueShouldSuccess("dhis2.org") + // valueShouldSuccess("dhis2.org/demo") + // valueShouldSuccess("www.dhis2.org") + // valueShouldSuccess("255.255.255.255") } @Test From 2b47c15fd65c4e29c8e720ca1acf2c717816c933 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 13 May 2021 16:18:48 +0200 Subject: [PATCH 063/308] [androsdk-1334] Improve email, phone and url validators --- .../validation/validators/EmailValidator.kt | 12 ++---------- .../validators/PhoneNumberValidator.kt | 5 ++--- .../validation/validators/UrlValidator.kt | 18 +++++++++++------- .../validators/EmailValidatorShould.kt | 1 - .../validators/PhoneNumberValidatorShould.kt | 14 +++++++++++++- .../validators/UrlValidatorShould.kt | 14 +++++++------- 6 files changed, 35 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt index 3df946c1c2..a5959e2543 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt @@ -33,18 +33,10 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.EmailFail object EmailValidator : ValueTypeValidator { - private const val EMAIL_RFC_5322_PATTERN = "^(?:[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#\$%&'*+/=?^_`{|}~" + - "-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c" + - "\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:" + - "(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?" + - "[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\" + - "x09\\x0b\\x0c\\x0e-\\x7f])+)\\])\n$" - private val EMAIL_RFC_5322_REGEX = EMAIL_RFC_5322_PATTERN.toRegex() - - private val EMAIL_PATTERN = "^(.+)@(\\S+)$".toRegex() + private val EMAIL_PATTERN = ("^[a-zA-Z0-9.!#\$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" + + "(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\$").toRegex() override fun validate(value: String): Result { - // TODO Review pattern used return when (value.matches(EMAIL_PATTERN)) { true -> { Result.Success(value) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt index 9ee15ac084..f75b68c4f3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidator.kt @@ -33,11 +33,10 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.PhoneNumb object PhoneNumberValidator : ValueTypeValidator { - private val INTERNATIONAL_PHONE_PATTERN = "^(\\+)?(?:[0-9].?){4,14}[0-9]$".toRegex() + private val PHONE_PATTERN = "^[0-9+(][0-9+\\-() ]{2,18}[0-9]$".toRegex() override fun validate(value: String): Result { - // TODO Review pattern used - return when (value.matches(INTERNATIONAL_PHONE_PATTERN)) { + return when (value.matches(PHONE_PATTERN)) { true -> { Result.Success(value) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt index 80a6b554e9..44fa402233 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidator.kt @@ -30,16 +30,20 @@ package org.hisp.dhis.android.core.common.valuetype.validation.validators import org.hisp.dhis.android.core.arch.helpers.Result import org.hisp.dhis.android.core.common.valuetype.validation.failures.UrlFailure -import java.net.MalformedURLException -import java.net.URL object UrlValidator : ValueTypeValidator { + + private val URL_PATTERN = "^(http|https):\\/\\/[a-z0-9]+([-.]{1}[a-z0-9]+)*\\.[a-z]{2,6}(:[0-9]{1,5})?(\\/.*)?\$" + .toRegex() + override fun validate(value: String): Result { - return try { - URL(value) - Result.Success(value) - } catch (e: MalformedURLException) { - Result.Failure(UrlFailure.MalformedUrlException) + return when (value.matches(URL_PATTERN)) { + true -> { + Result.Success(value) + } + else -> { + Result.Failure(UrlFailure.MalformedUrlException) + } } } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt index b951f52cfa..b829001d07 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidatorShould.kt @@ -44,6 +44,5 @@ class EmailValidatorShould : ValidatorShouldHelper(EmailValidator) @Test fun `Should fail when value is malformed`() { valueShouldFail("5fe2", EmailFailure.MalformedEmailException) - // valueShouldFail("email@email", EmailFailure.MalformedEmailException) } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt index 926b55cd9b..a3fc58a700 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/PhoneNumberValidatorShould.kt @@ -40,13 +40,25 @@ class PhoneNumberValidatorShould : ValidatorShouldHelper(Pho valueShouldSuccess("0034 521 587 422") valueShouldSuccess("0034521587422") valueShouldSuccess("+34521587422") - // valueShouldSuccess("+34 (521)-58 7422") + valueShouldSuccess("+34 (521)-58 7422") + valueShouldSuccess("+55 11 99999-5555") + valueShouldSuccess("+65 6511 9266") + valueShouldSuccess("+86 21 2230 1000") + valueShouldSuccess("+9124 4723300") + valueShouldSuccess("+821012345678") + valueShouldSuccess("+593 7 282-3889") + valueShouldSuccess("(+44) 0848 9123 456") + valueShouldSuccess("+1 284 852 5500") + valueShouldSuccess("+1 345 9490088") + valueShouldSuccess("+32 2 702-9200") } @Test fun `Should fail with a number format exception when value is malformed`() { valueShouldFail("5fe2", PhoneNumberFailure.MalformedPhoneNumberException) valueShouldFail("987", PhoneNumberFailure.MalformedPhoneNumberException) + valueShouldFail("984534534432324325347", PhoneNumberFailure.MalformedPhoneNumberException) + valueShouldFail("234234234234ó", PhoneNumberFailure.MalformedPhoneNumberException) valueShouldFail("", PhoneNumberFailure.MalformedPhoneNumberException) } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt index 5f7d0cce7c..80c6c22374 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/UrlValidatorShould.kt @@ -39,17 +39,17 @@ class UrlValidatorShould : ValidatorShouldHelper(UrlValidator) { valueShouldSuccess("http://www.dhis2.org") valueShouldSuccess("http://dhis2.org") valueShouldSuccess("https://dhis2.org") - valueShouldSuccess("http://localhost:4200/demo") - - // TODO Review what to do with those urls - // valueShouldSuccess("dhis2.org") - // valueShouldSuccess("dhis2.org/demo") - // valueShouldSuccess("www.dhis2.org") - // valueShouldSuccess("255.255.255.255") + valueShouldSuccess("https://dhis2.org/demo") + valueShouldSuccess("https://dhis2.org/demo/yo-yo") } @Test fun `Should fail when value is malformed`() { valueShouldFail("5fe2", UrlFailure.MalformedUrlException) + valueShouldFail("", UrlFailure.MalformedUrlException) + valueShouldFail("dhis2.org", UrlFailure.MalformedUrlException) + valueShouldFail("www.dhis2.org", UrlFailure.MalformedUrlException) + valueShouldFail("dhis2.org/demo", UrlFailure.MalformedUrlException) + valueShouldFail("http://localhost:4200/demo", UrlFailure.MalformedUrlException) } } From 94ac4ad0815f3717d9b15d194706063865795e9f Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 13 May 2021 16:38:47 +0200 Subject: [PATCH 064/308] [androsdk-1334] Ktlinkt format --- .../valuetype/validation/validators/EmailValidator.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt index a5959e2543..428783b844 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/valuetype/validation/validators/EmailValidator.kt @@ -33,8 +33,10 @@ import org.hisp.dhis.android.core.common.valuetype.validation.failures.EmailFail object EmailValidator : ValueTypeValidator { - private val EMAIL_PATTERN = ("^[a-zA-Z0-9.!#\$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" + - "(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\$").toRegex() + private val EMAIL_PATTERN = ( + "^[a-zA-Z0-9.!#\$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" + + "(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\$" + ).toRegex() override fun validate(value: String): Result { return when (value.matches(EMAIL_PATTERN)) { From c5979caf032826ac76bd00c30526d1a2f5e448d4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 14 May 2021 16:12:07 +0200 Subject: [PATCH 065/308] [androsdk-1334] Sort imports --- .../main/java/org/hisp/dhis/android/core/common/ValueType.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt index 995911faa3..85cf07d5ee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/ValueType.kt @@ -27,10 +27,10 @@ */ package org.hisp.dhis.android.core.common +import java.util.* import org.hisp.dhis.android.core.common.valuetype.validation.validators.* import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import java.util.* enum class ValueType(javaClass: Class<*>, val validator: ValueTypeValidator<*>) { TEXT(String::class.java, TextValidator), From d94617c8345da313120dd98cfba99bf4afbda90a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 20 May 2021 16:11:03 +0200 Subject: [PATCH 066/308] [androsdk-1357] Add dueDateLabel to program stage --- .../android/core/program/ProgramStage.java | 6 +++ .../core/program/ProgramStageTableInfo.java | 2 + .../program/internal/ProgramStageFields.java | 1 + .../program/internal/ProgramStageStore.java | 45 ++++++++++--------- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStage.java b/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStage.java index eafee35d3b..6e19424baf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStage.java +++ b/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStage.java @@ -79,6 +79,10 @@ public abstract class ProgramStage extends BaseIdentifiableObject @JsonProperty() public abstract String executionDateLabel(); + @Nullable + @JsonProperty() + public abstract String dueDateLabel(); + @Nullable @JsonProperty() public abstract Boolean allowGenerateNextVisit(); @@ -210,6 +214,8 @@ public static abstract class Builder extends BaseIdentifiableObject.Builderfield(Columns.DESCRIPTION), fh.field(Columns.DISPLAY_DESCRIPTION), fh.field(Columns.EXECUTION_DATE_LABEL), + fh.field(Columns.DUE_DATE_LABEL), fh.field(Columns.ALLOW_GENERATE_NEXT_VISIT), fh.field(Columns.VALID_COMPLETE_ONLY), fh.field(Columns.REPORT_DATE_TO_USE), diff --git a/core/src/main/java/org/hisp/dhis/android/core/program/internal/ProgramStageStore.java b/core/src/main/java/org/hisp/dhis/android/core/program/internal/ProgramStageStore.java index 456347b57c..7ca63a8db2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/program/internal/ProgramStageStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/program/internal/ProgramStageStore.java @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.program.internal; +import androidx.annotation.NonNull; + import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableWithStyleStatementBinder; import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; @@ -39,8 +41,6 @@ import org.hisp.dhis.android.core.program.ProgramStage; import org.hisp.dhis.android.core.program.ProgramStageTableInfo; -import androidx.annotation.NonNull; - public final class ProgramStageStore { private static StatementBinder BINDER = new IdentifiableWithStyleStatementBinder() { @@ -51,26 +51,27 @@ public void bindToStatement(@NonNull ProgramStage o, @NonNull StatementWrapper w w.bind(9, o.description()); w.bind(10, o.displayDescription()); w.bind(11, o.executionDateLabel()); - w.bind(12, o.allowGenerateNextVisit()); - w.bind(13, o.validCompleteOnly()); - w.bind(14, o.reportDateToUse()); - w.bind(15, o.openAfterEnrollment()); - w.bind(16, o.repeatable()); - w.bind(17, o.formType().name()); - w.bind(18, o.displayGenerateEventBox()); - w.bind(19, o.generatedByEnrollmentDate()); - w.bind(20, o.autoGenerateEvent()); - w.bind(21, o.sortOrder()); - w.bind(22, o.hideDueDate()); - w.bind(23, o.blockEntryForm()); - w.bind(24, o.minDaysFromStart()); - w.bind(25, o.standardInterval()); - w.bind(26, UidsHelper.getUidOrNull(o.program())); - w.bind(27, o.periodType()); - w.bind(28, o.access().data().write()); - w.bind(29, o.remindCompleted()); - w.bind(30, o.featureType()); - w.bind(31, o.enableUserAssignment()); + w.bind(12, o.dueDateLabel()); + w.bind(13, o.allowGenerateNextVisit()); + w.bind(14, o.validCompleteOnly()); + w.bind(15, o.reportDateToUse()); + w.bind(16, o.openAfterEnrollment()); + w.bind(17, o.repeatable()); + w.bind(18, o.formType().name()); + w.bind(19, o.displayGenerateEventBox()); + w.bind(20, o.generatedByEnrollmentDate()); + w.bind(21, o.autoGenerateEvent()); + w.bind(22, o.sortOrder()); + w.bind(23, o.hideDueDate()); + w.bind(24, o.blockEntryForm()); + w.bind(25, o.minDaysFromStart()); + w.bind(26, o.standardInterval()); + w.bind(27, UidsHelper.getUidOrNull(o.program())); + w.bind(28, o.periodType()); + w.bind(29, o.access().data().write()); + w.bind(30, o.remindCompleted()); + w.bind(31, o.featureType()); + w.bind(32, o.enableUserAssignment()); } }; From 88a41c466aabbd28f31cf723c41482e83673e4d0 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 20 May 2021 16:11:21 +0200 Subject: [PATCH 067/308] [androsdk-1357] Add dueDateLabel to table and migrations --- core/src/main/assets/migrations/100.sql | 2 ++ core/src/main/assets/snapshots/{99.sql => 100.sql} | 2 +- .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 core/src/main/assets/migrations/100.sql rename core/src/main/assets/snapshots/{99.sql => 100.sql} (99%) diff --git a/core/src/main/assets/migrations/100.sql b/core/src/main/assets/migrations/100.sql new file mode 100644 index 0000000000..da734f947f --- /dev/null +++ b/core/src/main/assets/migrations/100.sql @@ -0,0 +1,2 @@ +# Adds column ProgramStage.dueDateLabel +ALTER TABLE ProgramStage ADD COLUMN dueDateLabel TEXT; \ No newline at end of file diff --git a/core/src/main/assets/snapshots/99.sql b/core/src/main/assets/snapshots/100.sql similarity index 99% rename from core/src/main/assets/snapshots/99.sql rename to core/src/main/assets/snapshots/100.sql index 938a4ece5b..8085dc1024 100644 --- a/core/src/main/assets/snapshots/99.sql +++ b/core/src/main/assets/snapshots/100.sql @@ -66,7 +66,7 @@ CREATE TABLE TrackerImportConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, confl CREATE TABLE DataSetOrganisationUnitLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataSet TEXT NOT NULL, organisationUnit TEXT NOT NULL, FOREIGN KEY (dataSet) REFERENCES DataSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (organisationUnit, dataSet)); CREATE TABLE UserOrganisationUnit (_id INTEGER PRIMARY KEY AUTOINCREMENT, user TEXT NOT NULL, organisationUnit TEXT NOT NULL, organisationUnitScope TEXT NOT NULL, root INTEGER, FOREIGN KEY (user) REFERENCES User (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (organisationUnitScope, user, organisationUnit)); CREATE TABLE RelationshipType (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, fromToName TEXT, toFromName TEXT, bidirectional INTEGER, accessDataWrite INTEGER ); -CREATE TABLE ProgramStage (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, executionDateLabel TEXT, allowGenerateNextVisit INTEGER, validCompleteOnly INTEGER, reportDateToUse TEXT, openAfterEnrollment INTEGER, repeatable INTEGER, formType TEXT, displayGenerateEventBox INTEGER, generatedByEnrollmentDate INTEGER, autoGenerateEvent INTEGER, sortOrder INTEGER, hideDueDate INTEGER, blockEntryForm INTEGER, minDaysFromStart INTEGER, standardInterval INTEGER, program TEXT NOT NULL, periodType TEXT, accessDataWrite INTEGER, remindCompleted INTEGER, description TEXT, displayDescription TEXT, featureType TEXT, color TEXT, icon TEXT, enableUserAssignment INTEGER, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE ProgramStage (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, executionDateLabel TEXT, allowGenerateNextVisit INTEGER, validCompleteOnly INTEGER, reportDateToUse TEXT, openAfterEnrollment INTEGER, repeatable INTEGER, formType TEXT, displayGenerateEventBox INTEGER, generatedByEnrollmentDate INTEGER, autoGenerateEvent INTEGER, sortOrder INTEGER, hideDueDate INTEGER, blockEntryForm INTEGER, minDaysFromStart INTEGER, standardInterval INTEGER, program TEXT NOT NULL, periodType TEXT, accessDataWrite INTEGER, remindCompleted INTEGER, description TEXT, displayDescription TEXT, featureType TEXT, color TEXT, icon TEXT, enableUserAssignment INTEGER, dueDateLabel TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Program (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, version INTEGER, onlyEnrollOnce INTEGER, enrollmentDateLabel TEXT, displayIncidentDate INTEGER, incidentDateLabel TEXT, registration INTEGER, selectEnrollmentDatesInFuture INTEGER, dataEntryMethod INTEGER, ignoreOverdueEvents INTEGER, selectIncidentDatesInFuture INTEGER, useFirstStageDuringRegistration INTEGER, displayFrontPageList INTEGER, programType TEXT, relatedProgram TEXT, trackedEntityType TEXT, categoryCombo TEXT, accessDataWrite INTEGER, expiryDays INTEGER, completeEventsExpiryDays INTEGER, expiryPeriodType TEXT, minAttributesRequiredToSearch INTEGER, maxTeiCountToReturn INTEGER, featureType TEXT, accessLevel TEXT, color TEXT, icon TEXT, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryCombo) REFERENCES CategoryCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, state TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, state TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index 1dfd2092f1..ce80aacd50 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 99; + static final int VERSION = 100; private final AssetManager assetManager; private final int targetVersion; From 1e9d21e58495b985b39f8111e9d45132c81b9d69 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 20 May 2021 16:11:36 +0200 Subject: [PATCH 068/308] [androsdk-1357] Add dueDateLabel to ProgramStageCollectionRepository --- .../core/program/ProgramStageCollectionRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStageCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStageCollectionRepository.java index e998add379..2d90929040 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStageCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/program/ProgramStageCollectionRepository.java @@ -73,6 +73,10 @@ public StringFilterConnector byExecutionDateLa return cf.string(Columns.EXECUTION_DATE_LABEL); } + public StringFilterConnector byDueDateLabel() { + return cf.string(Columns.DUE_DATE_LABEL); + } + public BooleanFilterConnector byAllowGenerateNextVisit() { return cf.bool(Columns.ALLOW_GENERATE_NEXT_VISIT); } From 745dd097948a98782214139ae10aafc55ef5c1a1 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 20 May 2021 16:12:43 +0200 Subject: [PATCH 069/308] [androsdk-1357] Add dueDateLabel to tests --- .../android/core/program/CreateProgramStageUtils.java | 2 ++ ...tageCollectionRepositoryMockIntegrationShould.java | 11 +++++++++++ .../core/data/program/ProgramStageSamples.java | 1 + .../sharedTest/resources/program/program_stage.json | 1 + .../sharedTest/resources/program/program_stages.json | 2 ++ .../dhis/android/core/program/ProgramStageShould.java | 1 + 6 files changed, 18 insertions(+) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/program/CreateProgramStageUtils.java b/core/src/androidTest/java/org/hisp/dhis/android/core/program/CreateProgramStageUtils.java index fe5c1a2ab5..f0218c238b 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/program/CreateProgramStageUtils.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/program/CreateProgramStageUtils.java @@ -40,6 +40,7 @@ public class CreateProgramStageUtils { private static final String DISPLAY_NAME = "test_display_name"; private static final String EXECUTION_DATE_LABEL = "test_executionDateLabel"; + private static final String DUE_DATE_LABEL = "test_dueDateLabel"; private static final Integer ALLOW_GENERATE_NEXT_VISIT = 0; private static final Integer VALID_COMPLETE_ONLY = 0; private static final String REPORT_DATE_TO_USE = "test_reportDateToUse"; @@ -69,6 +70,7 @@ public static ContentValues create(long id, String uid, String programId) { programStage.put(IdentifiableColumns.CREATED, DATE); programStage.put(IdentifiableColumns.LAST_UPDATED, DATE); programStage.put(ProgramStageTableInfo.Columns.EXECUTION_DATE_LABEL, EXECUTION_DATE_LABEL); + programStage.put(ProgramStageTableInfo.Columns.DUE_DATE_LABEL, DUE_DATE_LABEL); programStage.put(ProgramStageTableInfo.Columns.ALLOW_GENERATE_NEXT_VISIT, ALLOW_GENERATE_NEXT_VISIT); programStage.put(ProgramStageTableInfo.Columns.VALID_COMPLETE_ONLY, VALID_COMPLETE_ONLY); programStage.put(ProgramStageTableInfo.Columns.REPORT_DATE_TO_USE, REPORT_DATE_TO_USE); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java index e9ffad0203..67fcd013eb 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/program/ProgramStageCollectionRepositoryMockIntegrationShould.java @@ -87,6 +87,17 @@ public void filter_by_execution_date_label() { assertThat(programStages.size()).isEqualTo(1); } + @Test + public void filter_by_due_date_label() { + List programStages = + d2.programModule().programStages() + .byDueDateLabel() + .eq("Due date") + .blockingGet(); + + assertThat(programStages.size()).isEqualTo(1); + } + @Test public void filter_by_allow_generate_next_visit() { List programStages = diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/program/ProgramStageSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/program/ProgramStageSamples.java index b112f51a00..51b31e2bca 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/program/ProgramStageSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/program/ProgramStageSamples.java @@ -51,6 +51,7 @@ public static ProgramStage getProgramStage() { .description("description") .displayDescription("display_description") .executionDateLabel("execution_date_label") + .dueDateLabel("due_date_label") .allowGenerateNextVisit(Boolean.FALSE) .validCompleteOnly(Boolean.TRUE) .reportDateToUse("report_date_to_use") diff --git a/core/src/sharedTest/resources/program/program_stage.json b/core/src/sharedTest/resources/program/program_stage.json index b04ea17db7..8a1f35a98b 100644 --- a/core/src/sharedTest/resources/program/program_stage.json +++ b/core/src/sharedTest/resources/program/program_stage.json @@ -17,6 +17,7 @@ "enableUserAssignment": "true", "captureCoordinates": true, "formType": "DEFAULT", + "dueDateLabel": "Due date", "remindCompleted": false, "displayGenerateEventBox": false, "generatedByEnrollmentDate": false, diff --git a/core/src/sharedTest/resources/program/program_stages.json b/core/src/sharedTest/resources/program/program_stages.json index 36604f64f0..d0a3c3eb27 100644 --- a/core/src/sharedTest/resources/program/program_stages.json +++ b/core/src/sharedTest/resources/program/program_stages.json @@ -9,6 +9,7 @@ "displayDescription": "Display Description", "allowGenerateNextVisit": false, "executionDateLabel": "Visit date", + "dueDateLabel": "Due date", "validCompleteOnly": true, "displayName": "Antenatal care visit - Program rules demo", "openAfterEnrollment": false, @@ -193,6 +194,7 @@ "name": "Child care visit - demo", "allowGenerateNextVisit": true, "executionDateLabel": "Visit date 2", + "dueDateLabel": "Due date 2", "validCompleteOnly": false, "displayName": "Antenatal care visit - Program rules demo", "openAfterEnrollment": true, diff --git a/core/src/test/java/org/hisp/dhis/android/core/program/ProgramStageShould.java b/core/src/test/java/org/hisp/dhis/android/core/program/ProgramStageShould.java index 1412fc990c..dbd77a57d5 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/program/ProgramStageShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/program/ProgramStageShould.java @@ -70,6 +70,7 @@ public void map_from_json_string() throws IOException, ParseException { assertThat(programStage.captureCoordinates()).isTrue(); assertThat(programStage.displayGenerateEventBox()).isFalse(); assertThat(programStage.executionDateLabel()).isNull(); + assertThat(programStage.dueDateLabel()).isEqualTo("Due date"); assertThat(programStage.formType()).isEqualTo(FormType.DEFAULT); assertThat(programStage.generatedByEnrollmentDate()).isFalse(); assertThat(programStage.hideDueDate()).isFalse(); From 3c7eea79271a898ebb5259d77b916feb787e9346 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 2 Jun 2021 17:31:54 +0200 Subject: [PATCH 070/308] [ANDROSDK-1379] Create DataValueImportConflictParser.kt --- .../core/datavalue/DataValueConflict.java | 85 +++++++++++++++++++ .../internal/DataValueImportConflict.kt | 41 +++++++++ .../internal/DataValueImportConflictParser.kt | 59 +++++++++++++ .../conflicts/DataValueImportConflictItem.kt | 36 ++++++++ .../InvalidDataElementTypeConflict.kt | 44 ++++++++++ 5 files changed, 265 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java new file mode 100644 index 0000000000..891cf697cc --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue; + +import androidx.annotation.Nullable; + +import com.gabrielittner.auto.value.cursor.ColumnAdapter; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbDateColumnAdapter; +import org.hisp.dhis.android.core.common.BaseObject; + +import java.util.Date; + +@AutoValue +public abstract class DataValueConflict extends BaseObject { + + @Nullable + public abstract String conflict(); + + @Nullable + public abstract String value(); + + @Nullable + public abstract String dataElement(); + + @Nullable + public abstract String tableReference(); + + @Nullable + public abstract String errorCode(); + + @Nullable + @ColumnAdapter(DbDateColumnAdapter.class) + public abstract Date created(); + + public static Builder builder() { + return new $AutoValue_DataValueConflict.Builder(); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + public static abstract class Builder extends BaseObject.Builder { + public abstract Builder conflict(String conflict); + + public abstract Builder value(String value); + + public abstract Builder dataElement(String dataElement); + + public abstract Builder tableReference(String tableReference); + + public abstract Builder errorCode(String errorCode); + + public abstract Builder created(Date created); + + public abstract DataValueConflict build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt new file mode 100644 index 0000000000..4c5feb13ec --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.annotation.JsonRootName + +private const val OBJECT = "object" +private const val VALUE = "value" + +@JsonRootName("conflicts") +internal data class DataValueImportConflict( + @JsonProperty(OBJECT) val `object`: String, + @JsonProperty(VALUE) val value: String +) \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt new file mode 100644 index 0000000000..7d35b9fdf7 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict +import javax.inject.Inject + +@Reusable +internal class DataValueImportConflictParser @Inject constructor( + +) { + + private val conflicts = listOf( + InvalidDataElementTypeConflict + ) + + fun getDataValueConflict( + conflict: DataValueImportConflict, + conflictBuilder: DataValueConflict.Builder + ): DataValueConflict { + return evaluateConflicts(conflict, conflictBuilder, conflicts) + } + + private fun evaluateConflicts( + conflict: DataValueImportConflict, + conflictBuilder: DataValueConflict.Builder, + conflicts: List + ): DataValueConflict { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt new file mode 100644 index 0000000000..705a29013d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import org.hisp.dhis.android.core.datavalue.internal.DataValueImportConflict + +internal interface DataValueImportConflictItem { + fun matches(conflict: DataValueImportConflict): Boolean + fun getDataValues(conflict: DataValueImportConflict): String +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt new file mode 100644 index 0000000000..6eeacc0cdb --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import org.hisp.dhis.android.core.datavalue.internal.DataValueImportConflict + +internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { + + private val regex: Regex = Regex("must match data element type: (\\w{11})") + + override fun matches(conflict: DataValueImportConflict): Boolean { + return regex.matches(conflict.value) + } + + override fun getDataValues(conflict: DataValueImportConflict): String { + return conflict.`object` + } +} From 3845579e4c9df6e8a6a88c8299cdb814ba778c3e Mon Sep 17 00:00:00 2001 From: andresmr Date: Fri, 4 Jun 2021 10:26:22 +0200 Subject: [PATCH 071/308] [ANDROSDK-1379] Integrate parse into DataValueImportHandler --- .../MetadataCallRealIntegrationShould.java | 3 +- .../core/datavalue/DataValueConflict.java | 34 ++++++++++ .../internal/DataValueImportConflict.kt | 41 ------------ .../internal/DataValueImportConflictParser.kt | 24 +++---- .../internal/DataValueImportHandler.kt | 66 ++++++++----------- .../conflicts/DataValueImportConflictItem.kt | 8 ++- .../InvalidDataElementTypeConflict.kt | 51 ++++++++++++-- 7 files changed, 125 insertions(+), 102 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java index c7411c5248..e3b514c19b 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java @@ -31,6 +31,7 @@ import android.util.Log; import org.junit.Before; +import org.junit.Test; import java.io.IOException; @@ -70,7 +71,7 @@ make a debugger break point where desired (after sync complete) //This test is uncommented because technically it is flaky. //It depends on a live server to operate and the login is hardcoded here. //Uncomment in order to quickly test changes vs a real server, but keep it uncommented after. - //@Test + @Test public void response_successful_on_sync_meta_data_once() throws Exception { d2.userModule().logIn(username, password, url).blockingGet(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java index 891cf697cc..3757c6a8b7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java @@ -34,7 +34,9 @@ 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.enums.internal.ImportStatusColumnAdapter; import org.hisp.dhis.android.core.common.BaseObject; +import org.hisp.dhis.android.core.imports.ImportStatus; import java.util.Date; @@ -47,15 +49,35 @@ public abstract class DataValueConflict extends BaseObject { @Nullable public abstract String value(); + @Nullable + public abstract String attributeOptionCombo(); + + @Nullable + public abstract String categoryOptionCombo(); + @Nullable public abstract String dataElement(); + @Nullable + public abstract String period(); + + @Nullable + public abstract String orgUnit(); + @Nullable public abstract String tableReference(); @Nullable public abstract String errorCode(); + // TODO legible description chade id by data elemtn type + @Nullable + public abstract String displayDescription(); + + @Nullable + @ColumnAdapter(ImportStatusColumnAdapter.class) + public abstract ImportStatus status(); + @Nullable @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date created(); @@ -72,12 +94,24 @@ public static abstract class Builder extends BaseObject.Builder { public abstract Builder value(String value); + public abstract Builder attributeOptionCombo(String attributeOptionCombo); + + public abstract Builder categoryOptionCombo(String categoryOptionCombo); + public abstract Builder dataElement(String dataElement); + public abstract Builder period(String period); + + public abstract Builder orgUnit(String orgUnit); + public abstract Builder tableReference(String tableReference); public abstract Builder errorCode(String errorCode); + public abstract Builder displayDescription(String displayDescription); + + public abstract Builder status(ImportStatus status); + public abstract Builder created(Date created); public abstract DataValueConflict build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt deleted file mode 100644 index 4c5feb13ec..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflict.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.datavalue.internal - -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.annotation.JsonRootName - -private const val OBJECT = "object" -private const val VALUE = "value" - -@JsonRootName("conflicts") -internal data class DataValueImportConflict( - @JsonProperty(OBJECT) val `object`: String, - @JsonProperty(VALUE) val value: String -) \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt index 7d35b9fdf7..efa1049581 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt @@ -29,8 +29,10 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable +import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict +import org.hisp.dhis.android.core.imports.internal.ImportConflict import javax.inject.Inject @Reusable @@ -42,18 +44,12 @@ internal class DataValueImportConflictParser @Inject constructor( InvalidDataElementTypeConflict ) - fun getDataValueConflict( - conflict: DataValueImportConflict, - conflictBuilder: DataValueConflict.Builder - ): DataValueConflict { - return evaluateConflicts(conflict, conflictBuilder, conflicts) + fun getDataValueConflicts( + conflict: ImportConflict, + dataValues: List + ): List { + return conflicts.find { + it.matches(conflict) + }?.getDataValues(conflict, dataValues) ?: emptyList() } - - private fun evaluateConflicts( - conflict: DataValueImportConflict, - conflictBuilder: DataValueConflict.Builder, - conflicts: List - ): DataValueConflict { - TODO("Not yet implemented") - } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt index 3be37abbba..523e19a7f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt @@ -28,19 +28,18 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable -import java.util.ArrayList -import java.util.HashSet -import java.util.regex.Pattern -import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.datavalue.DataValue +import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.DataValueImportSummary import org.hisp.dhis.android.core.imports.internal.ImportConflict +import javax.inject.Inject @Reusable internal class DataValueImportHandler @Inject constructor( - private val dataValueStore: DataValueStore + private val dataValueStore: DataValueStore, + private val dataValueImportConflictParser: DataValueImportConflictParser ) { fun handleImportSummary( @@ -68,25 +67,38 @@ internal class DataValueImportHandler @Inject constructor( dataValueSet: DataValueSet, dataValueImportSummary: DataValueImportSummary ) { - getValuesWithConflicts(dataValueSet, dataValueImportSummary)?.let { dataValueConflicts -> + getValuesWithConflicts( + dataValueSet.dataValues, + dataValueImportSummary.importConflicts() + )?.let { dataValueConflicts -> setDataValueStates(dataValueSet, dataValueConflicts) } ?: setStateToDataValues(State.WARNING, dataValueSet.dataValues) } private fun getValuesWithConflicts( - dataValueSet: DataValueSet, - dataValueImportSummary: DataValueImportSummary + dataValues: List, + importConflicts: List? ): Set? { - val dataValueConflicts: MutableSet = HashSet() - dataValueImportSummary.importConflicts()?.forEach { importConflict -> - getDataValues(importConflict, dataValueSet.dataValues).let { dataValues -> - if (dataValues.isEmpty()) { - return null - } - dataValueConflicts.addAll(dataValues) + val dataValueImportConflicts: MutableList = mutableListOf() + importConflicts?.forEach { importConflict -> + + val valuesPerConflict = dataValueImportConflictParser + .getDataValueConflicts(importConflict, dataValues) + + if (valuesPerConflict.isEmpty()) { + return null } + dataValueImportConflicts.addAll(valuesPerConflict) + + //TODO INSERT AND DELETE CONFLICTS in DataBase, SEE TrackedEntityInstanceImportHandler + //Delete only dataValues conflicts that i uploaded and have no more conflicts } - return dataValueConflicts + return dataValueImportConflicts.mapNotNull { dataValueConflict -> + dataValues.find { dataValue -> + dataValue.attributeOptionCombo().equals(dataValueConflict.attributeOptionCombo()) && + dataValue.categoryOptionCombo().equals(dataValueConflict.categoryOptionCombo()) + } + }.toSet() } private fun setDataValueStates( @@ -100,28 +112,6 @@ internal class DataValueImportHandler @Inject constructor( setStateToDataValues(State.SYNCED, syncedValues) } - private fun getDataValues( - importConflict: ImportConflict, - dataValues: Collection - ): List { - val patternStr = "(?<=:\\s)[a-zA-Z0-9]{11}" - val pattern = Pattern.compile(patternStr) - val matcher = pattern.matcher(importConflict.value()) - - val foundDataValues: MutableList = ArrayList() - - if (matcher.find()) { - val value = importConflict.`object`() - val dataElementUid = matcher.group(0) - for (dataValue in dataValues) { - if (dataValue.value() == value && dataValue.dataElement() == dataElementUid) { - foundDataValues.add(dataValue) - } - } - } - return foundDataValues - } - private fun setStateToDataValues(state: State, dataValues: Collection) { for (dataValue in dataValues) { if (dataValueStore.isDataValueBeingUpload(dataValue)) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt index 705a29013d..5bddde0a3d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -28,9 +28,11 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts -import org.hisp.dhis.android.core.datavalue.internal.DataValueImportConflict +import org.hisp.dhis.android.core.datavalue.DataValue +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.imports.internal.ImportConflict internal interface DataValueImportConflictItem { - fun matches(conflict: DataValueImportConflict): Boolean - fun getDataValues(conflict: DataValueImportConflict): String + fun matches(conflict: ImportConflict): Boolean + fun getDataValues(conflict: ImportConflict, dataValues: List): List } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt index 6eeacc0cdb..f53ad823ce 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -28,17 +28,58 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts -import org.hisp.dhis.android.core.datavalue.internal.DataValueImportConflict +import org.hisp.dhis.android.core.datavalue.DataValue +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.DataValueTableInfo +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.internal.ImportConflict +import java.util.ArrayList +import java.util.Date +import java.util.regex.Pattern internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { private val regex: Regex = Regex("must match data element type: (\\w{11})") - override fun matches(conflict: DataValueImportConflict): Boolean { - return regex.matches(conflict.value) + override fun matches(conflict: ImportConflict): Boolean { + val patternStr = "(?<=:\\s)[a-zA-Z0-9]{11}" + val pattern = Pattern.compile(patternStr) + val matcher = pattern.matcher(conflict.value()) + return matcher.find() } - override fun getDataValues(conflict: DataValueImportConflict): String { - return conflict.`object` + override fun getDataValues(conflict: ImportConflict, dataValues: List): List { + val patternStr = "(?<=:\\s)[a-zA-Z0-9]{11}" + val pattern = Pattern.compile(patternStr) + val matcher = pattern.matcher(conflict.value()) + + val foundDataValuesConflicts: MutableList = ArrayList() + if (matcher.find()) { + val value = conflict.`object`() + val dataElementUid = matcher.group(0) + for (dataValue in dataValues) { + if (dataValue.value() == value && dataValue.dataElement() == dataElementUid) { + foundDataValuesConflicts.add(getConflictBuilder(dataValue).build()) + } + } + } + + return foundDataValuesConflicts + } + + private fun getConflictBuilder(dataValue: DataValue): DataValueConflict.Builder { + return DataValueConflict.builder() + .conflict("") + .value(dataValue.value()) + .attributeOptionCombo(dataValue.attributeOptionCombo()) + .categoryOptionCombo(dataValue.categoryOptionCombo()) + .dataElement(dataValue.dataElement()) + .orgUnit(dataValue.organisationUnit()) + .period(dataValue.period()) + .tableReference(DataValueTableInfo.TABLE_INFO.name()) + .status(ImportStatus.WARNING) + .errorCode("") + .displayDescription("") + .created(Date()) } } From 19eff502abffae0fe37594a7f00e6b58d7604f4b Mon Sep 17 00:00:00 2001 From: andresmr Date: Fri, 4 Jun 2021 17:14:17 +0200 Subject: [PATCH 072/308] [ANDROSDK-1379] Created DataValueConflict table --- .../core/arch/d2/internal/D2DIComponent.java | 5 +- .../core/datavalue/DataValueConflict.java | 10 ++- .../datavalue/DataValueConflictTableInfo.kt | 80 +++++++++++++++++++ .../internal/DataValueConflictDIModule.kt | 46 +++++++++++ ...ctParser.kt => DataValueConflictParser.kt} | 2 +- .../internal/DataValueConflictStore.kt | 60 ++++++++++++++ .../internal/DataValueImportHandler.kt | 11 ++- 7 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt rename core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/{DataValueImportConflictParser.kt => DataValueConflictParser.kt} (97%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java index dbaa02c925..9bdb2fd1f3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java @@ -59,6 +59,7 @@ import org.hisp.dhis.android.core.dataelement.internal.DataElementPackageDIModule; import org.hisp.dhis.android.core.dataset.DataSet; import org.hisp.dhis.android.core.dataset.internal.DataSetPackageDIModule; +import org.hisp.dhis.android.core.datavalue.internal.DataValueConflictDIModule; import org.hisp.dhis.android.core.datavalue.internal.DataValuePackageDIModule; import org.hisp.dhis.android.core.domain.aggregated.data.internal.AggregatedDataPackageDIModule; import org.hisp.dhis.android.core.domain.aggregated.internal.AggregatedModuleImpl; @@ -143,7 +144,8 @@ TrackerImporterPackageDIModule.class, SmsDIModule.class, UserPackageDIModule.class, - ValidationPackageDIModule.class} + ValidationPackageDIModule.class, + DataValueConflictDIModule.class} ) public interface D2DIComponent { @@ -220,6 +222,7 @@ interface Builder { Builder trackerImporterPackageDIModule(TrackerImporterPackageDIModule trackerImporterPackageDIModule); Builder userPackageDIModule(UserPackageDIModule userPackageDIModule); Builder validationPackageDIModule(ValidationPackageDIModule validationPackageDIModule); + Builder dataValueConflictDIModule(DataValueConflictDIModule dataValueConflictDIModule); D2DIComponent build(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java index 3757c6a8b7..5df3ea057a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java @@ -28,6 +28,9 @@ package org.hisp.dhis.android.core.datavalue; +import android.database.Cursor; + +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.gabrielittner.auto.value.cursor.ColumnAdapter; @@ -82,8 +85,13 @@ public abstract class DataValueConflict extends BaseObject { @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date created(); + @NonNull + public static DataValueConflict create(Cursor cursor) { + return AutoValue_DataValueConflict.createFromCursor(cursor); + } + public static Builder builder() { - return new $AutoValue_DataValueConflict.Builder(); + return new $$AutoValue_DataValueConflict.Builder(); } public abstract Builder toBuilder(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt new file mode 100644 index 0000000000..c59559f881 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns + +object DataValueConflictTableInfo { + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "DataValueConflict" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : CoreColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + CONFLICT, + VALUE, + ATTRIBUTE_OPTION_COMBO, + CATEGORY_OPTION_COMBO, + DATA_ELEMENT, + PERIOD, + ORG_UNIT, + TABLE_REFERENCE, + ERROR_CODE, + DISPLAY_DESCRIPTION, + STATUS, + CREATED + ) + } + + companion object { + const val CONFLICT = "conflict" + const val VALUE = "value" + const val ATTRIBUTE_OPTION_COMBO = "attributeOptionCombo" + const val CATEGORY_OPTION_COMBO = "categoryOptionCombo" + const val DATA_ELEMENT = "dataElement" + const val PERIOD = "period" + const val ORG_UNIT = "orgUnit" + const val TABLE_REFERENCE = "tableReference" + const val ERROR_CODE = "errorCode" + const val DISPLAY_DESCRIPTION = "displayDescription" + const val STATUS = "status" + const val CREATED = "created" + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt new file mode 100644 index 0000000000..e48efaab15 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore +import org.hisp.dhis.android.core.datavalue.DataValueConflict + +@Module +internal class DataValueConflictDIModule { + + @Provides + @Reusable + fun store (databaseAdapter: DatabaseAdapter): ObjectStore { + return DataValueConflictStore.create(databaseAdapter) + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt similarity index 97% rename from core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt rename to core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt index efa1049581..c91bd79427 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt @@ -36,7 +36,7 @@ import org.hisp.dhis.android.core.imports.internal.ImportConflict import javax.inject.Inject @Reusable -internal class DataValueImportConflictParser @Inject constructor( +internal class DataValueConflictParser @Inject constructor( ) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt new file mode 100644 index 0000000000..a903dc270e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal + +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.DataValueConflictTableInfo + +internal object DataValueConflictStore { + private val BINDER = StatementBinder { o, w -> + w.bind(1, o.conflict()) + w.bind(2, o.value()) + w.bind(3, o.attributeOptionCombo()) + w.bind(4, o.categoryOptionCombo()) + w.bind(5, o.dataElement()) + w.bind(6, o.period()) + w.bind(7, o.orgUnit()) + w.bind(8, o.tableReference()) + w.bind(9, o.errorCode()) + w.bind(10, o.displayDescription()) + w.bind(11, o.status()) + w.bind(12, o.created()) + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): ObjectStore { + return StoreFactory.objectStore(databaseAdapter, DataValueConflictTableInfo.TABLE_INFO, BINDER) { + DataValueConflict.create(it) + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt index 523e19a7f1..81871931b3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict @@ -39,7 +40,8 @@ import javax.inject.Inject @Reusable internal class DataValueImportHandler @Inject constructor( private val dataValueStore: DataValueStore, - private val dataValueImportConflictParser: DataValueImportConflictParser + private val dataValueConflictParser: DataValueConflictParser, + private val dataValueConflictStore: ObjectStore ) { fun handleImportSummary( @@ -82,7 +84,7 @@ internal class DataValueImportHandler @Inject constructor( val dataValueImportConflicts: MutableList = mutableListOf() importConflicts?.forEach { importConflict -> - val valuesPerConflict = dataValueImportConflictParser + val valuesPerConflict = dataValueConflictParser .getDataValueConflicts(importConflict, dataValues) if (valuesPerConflict.isEmpty()) { @@ -90,9 +92,12 @@ internal class DataValueImportHandler @Inject constructor( } dataValueImportConflicts.addAll(valuesPerConflict) - //TODO INSERT AND DELETE CONFLICTS in DataBase, SEE TrackedEntityInstanceImportHandler + //TODO DELETE CONFLICTS in DataBase, SEE TrackedEntityInstanceImportHandler //Delete only dataValues conflicts that i uploaded and have no more conflicts } + + dataValueConflictStore.insert(dataValueImportConflicts) + return dataValueImportConflicts.mapNotNull { dataValueConflict -> dataValues.find { dataValue -> dataValue.attributeOptionCombo().equals(dataValueConflict.attributeOptionCombo()) && From 0edbff37e6d932fed1669eee95166b87c1fac362 Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 7 Jun 2021 12:27:26 +0200 Subject: [PATCH 073/308] [ANDROSDK-1379] Delete DataValueConflicts from Database --- .../DataValuePostCallMockIntegrationShould.kt | 4 +- .../internal/DataValueConflictDIModule.kt | 4 +- .../internal/DataValueConflictParser.kt | 6 +- .../internal/DataValueConflictStore.kt | 3 +- .../internal/DataValueImportHandler.kt | 72 ++++++++++++++----- .../conflicts/DataValueImportConflictItem.kt | 2 +- .../InvalidDataElementTypeConflict.kt | 6 +- 7 files changed, 66 insertions(+), 31 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt index bad0bd18ba..7ccbbc0ca4 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt @@ -28,8 +28,8 @@ class DataValuePostCallMockIntegrationShould : BaseMockIntegrationTestMetadataEn d2.dataValueModule().dataValues().blockingUpload() // Then all data set should be properly synced - val warnings = d2.dataValueModule().dataValues().byState().eq(State.SYNCED).blockingGet() - assertThat(warnings.size).isEqualTo(2) + val synced = d2.dataValueModule().dataValues().byState().eq(State.SYNCED).blockingGet() + assertThat(synced.size).isEqualTo(2) } @Test diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt index e48efaab15..b199f5c451 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictDIModule.kt @@ -40,7 +40,7 @@ internal class DataValueConflictDIModule { @Provides @Reusable - fun store (databaseAdapter: DatabaseAdapter): ObjectStore { + fun store(databaseAdapter: DatabaseAdapter): ObjectStore { return DataValueConflictStore.create(databaseAdapter) } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt index c91bd79427..93f8934f37 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt @@ -29,16 +29,14 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict import org.hisp.dhis.android.core.imports.internal.ImportConflict -import javax.inject.Inject @Reusable -internal class DataValueConflictParser @Inject constructor( - -) { +internal class DataValueConflictParser @Inject constructor() { private val conflicts = listOf( InvalidDataElementTypeConflict diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt index a903dc270e..8463f521af 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt @@ -35,6 +35,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.DataValueConflictTableInfo +@Suppress("MagicNumber") internal object DataValueConflictStore { private val BINDER = StatementBinder { o, w -> w.bind(1, o.conflict()) @@ -57,4 +58,4 @@ internal object DataValueConflictStore { DataValueConflict.create(it) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt index 81871931b3..a37b5f7b82 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt @@ -28,14 +28,20 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable +import javax.inject.Inject +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.State.ERROR +import org.hisp.dhis.android.core.common.State.SYNCED +import org.hisp.dhis.android.core.common.State.WARNING import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.DataValueConflictTableInfo +import org.hisp.dhis.android.core.datavalue.DataValueTableInfo import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.DataValueImportSummary import org.hisp.dhis.android.core.imports.internal.ImportConflict -import javax.inject.Inject @Reusable internal class DataValueImportHandler @Inject constructor( @@ -53,28 +59,61 @@ internal class DataValueImportHandler @Inject constructor( } val state = when (dataValueImportSummary.importStatus()) { - ImportStatus.ERROR -> State.ERROR - ImportStatus.WARNING -> State.WARNING - else -> State.SYNCED + ImportStatus.ERROR -> ERROR + ImportStatus.WARNING -> WARNING + else -> SYNCED } - if (state == State.WARNING) { - handleDataValueWarnings(dataValueSet, dataValueImportSummary) + deleteDataValueConflicts(dataValueSet.dataValues) + + if (state == WARNING || state == ERROR) { + handleDataValueWarnings(dataValueSet.dataValues, dataValueImportSummary) } else { setStateToDataValues(state, dataValueSet.dataValues) } } + private fun deleteDataValueConflicts(dataValues: List) { + dataValues.forEach { dataValue -> + val whereClause = WhereClauseBuilder() + .appendKeyStringValue( + DataValueConflictTableInfo.Columns.TABLE_REFERENCE, + DataValueTableInfo.TABLE_INFO.name() + ) + .appendKeyStringValue( + DataValueConflictTableInfo.Columns.ATTRIBUTE_OPTION_COMBO, + dataValue.attributeOptionCombo() + ) + .appendKeyStringValue( + DataValueConflictTableInfo.Columns.CATEGORY_OPTION_COMBO, + dataValue.categoryOptionCombo() + ) + .appendKeyStringValue( + DataValueConflictTableInfo.Columns.DATA_ELEMENT, + dataValue.dataElement() + ) + .appendKeyStringValue( + DataValueConflictTableInfo.Columns.PERIOD, + dataValue.period() + ) + .appendKeyStringValue( + DataValueConflictTableInfo.Columns.ORG_UNIT, + dataValue.organisationUnit() + ).build() + dataValueConflictStore.deleteWhereIfExists(whereClause) + } + } + private fun handleDataValueWarnings( - dataValueSet: DataValueSet, + dataValues: List, dataValueImportSummary: DataValueImportSummary ) { getValuesWithConflicts( - dataValueSet.dataValues, + dataValues, dataValueImportSummary.importConflicts() )?.let { dataValueConflicts -> - setDataValueStates(dataValueSet, dataValueConflicts) - } ?: setStateToDataValues(State.WARNING, dataValueSet.dataValues) + setDataValueStates(dataValues, dataValueConflicts) + } ?: setStateToDataValues(WARNING, dataValues) } private fun getValuesWithConflicts( @@ -91,9 +130,6 @@ internal class DataValueImportHandler @Inject constructor( return null } dataValueImportConflicts.addAll(valuesPerConflict) - - //TODO DELETE CONFLICTS in DataBase, SEE TrackedEntityInstanceImportHandler - //Delete only dataValues conflicts that i uploaded and have no more conflicts } dataValueConflictStore.insert(dataValueImportConflicts) @@ -107,20 +143,20 @@ internal class DataValueImportHandler @Inject constructor( } private fun setDataValueStates( - dataValueSet: DataValueSet, + dataValues: List, dataValueConflicts: Set ) { - val syncedValues = dataValueSet.dataValues.filter { dataValue -> + val syncedValues = dataValues.filter { dataValue -> !dataValueConflicts.contains(dataValue) } - setStateToDataValues(State.WARNING, dataValueConflicts) - setStateToDataValues(State.SYNCED, syncedValues) + setStateToDataValues(WARNING, dataValueConflicts) + setStateToDataValues(SYNCED, syncedValues) } private fun setStateToDataValues(state: State, dataValues: Collection) { for (dataValue in dataValues) { if (dataValueStore.isDataValueBeingUpload(dataValue)) { - if (state == State.SYNCED && dataValueStore.isDeleted(dataValue)) { + if (state == SYNCED && dataValueStore.isDeleted(dataValue)) { dataValueStore.deleteWhere(dataValue) } else { dataValueStore.setState(dataValue, state) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt index 5bddde0a3d..5c66cdb5e3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -35,4 +35,4 @@ import org.hisp.dhis.android.core.imports.internal.ImportConflict internal interface DataValueImportConflictItem { fun matches(conflict: ImportConflict): Boolean fun getDataValues(conflict: ImportConflict, dataValues: List): List -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt index f53ad823ce..c948b0e30c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -28,14 +28,14 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts +import java.util.ArrayList +import java.util.Date +import java.util.regex.Pattern import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.DataValueTableInfo import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.ImportConflict -import java.util.ArrayList -import java.util.Date -import java.util.regex.Pattern internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { From 0646f5a989412e871dba1131d406e4727d6ea1b5 Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 7 Jun 2021 17:46:11 +0200 Subject: [PATCH 074/308] [ANDROSDK-1379] PastExpiryDate.kt Datavalue conflict --- .../internal/DataValueConflictParser.kt | 4 +- .../conflicts/DataValueImportConflictItem.kt | 22 +++++++ .../InvalidDataElementTypeConflict.kt | 53 +++++----------- .../internal/conflicts/PastExpiryDate.kt | 62 +++++++++++++++++++ .../datavalueset/data_value_set_warning.json | 2 +- ...data_value_set_warning_expired_period.json | 49 +++++++++++++++ 6 files changed, 154 insertions(+), 38 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt create mode 100644 core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt index 93f8934f37..72aa02a7f8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt @@ -33,13 +33,15 @@ import javax.inject.Inject import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict +import org.hisp.dhis.android.core.datavalue.internal.conflicts.PastExpiryDate import org.hisp.dhis.android.core.imports.internal.ImportConflict @Reusable internal class DataValueConflictParser @Inject constructor() { private val conflicts = listOf( - InvalidDataElementTypeConflict + InvalidDataElementTypeConflict, + PastExpiryDate ) fun getDataValueConflicts( diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt index 5c66cdb5e3..c7032908ca 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -28,11 +28,33 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts +import java.util.Date import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.DataValueTableInfo +import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.ImportConflict internal interface DataValueImportConflictItem { fun matches(conflict: ImportConflict): Boolean fun getDataValues(conflict: ImportConflict, dataValues: List): List + + fun getConflictBuilder( + dataValue: DataValue, + conflict: ImportConflict, + displayDescription: String + ): DataValueConflict.Builder { + return DataValueConflict.builder() + .conflict(conflict.value()) + .value(dataValue.value()) + .attributeOptionCombo(dataValue.attributeOptionCombo()) + .categoryOptionCombo(dataValue.categoryOptionCombo()) + .dataElement(dataValue.dataElement()) + .orgUnit(dataValue.organisationUnit()) + .period(dataValue.period()) + .tableReference(DataValueTableInfo.TABLE_INFO.name()) + .status(ImportStatus.WARNING) + .displayDescription(displayDescription) + .created(Date()) + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt index c948b0e30c..797bbdbaf6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -29,57 +29,38 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts import java.util.ArrayList -import java.util.Date -import java.util.regex.Pattern import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict -import org.hisp.dhis.android.core.datavalue.DataValueTableInfo -import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.ImportConflict internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { - private val regex: Regex = Regex("must match data element type: (\\w{11})") + private val regex: Regex = Regex(".*, must match data element type: (\\w{11})") + private fun description(value: String, elementType: String) = + "DataValue $value must match with data element type $elementType" override fun matches(conflict: ImportConflict): Boolean { - val patternStr = "(?<=:\\s)[a-zA-Z0-9]{11}" - val pattern = Pattern.compile(patternStr) - val matcher = pattern.matcher(conflict.value()) - return matcher.find() + return regex.matches(conflict.value()) } override fun getDataValues(conflict: ImportConflict, dataValues: List): List { - val patternStr = "(?<=:\\s)[a-zA-Z0-9]{11}" - val pattern = Pattern.compile(patternStr) - val matcher = pattern.matcher(conflict.value()) - val foundDataValuesConflicts: MutableList = ArrayList() - if (matcher.find()) { - val value = conflict.`object`() - val dataElementUid = matcher.group(0) - for (dataValue in dataValues) { - if (dataValue.value() == value && dataValue.dataElement() == dataElementUid) { - foundDataValuesConflicts.add(getConflictBuilder(dataValue).build()) - } + val value = conflict.`object`() + val dataElementUid = regex.find(conflict.value())?.groupValues?.get(1) + for (dataValue in dataValues) { + if (dataValue.value() == value && dataValue.dataElement() == dataElementUid) { + foundDataValuesConflicts.add( + getConflictBuilder( + dataValue = dataValue, + conflict = conflict, + displayDescription = dataValue.dataElement()?.let { + description(conflict.`object`(), it) + } ?: conflict.value() + ).build() + ) } } return foundDataValuesConflicts } - - private fun getConflictBuilder(dataValue: DataValue): DataValueConflict.Builder { - return DataValueConflict.builder() - .conflict("") - .value(dataValue.value()) - .attributeOptionCombo(dataValue.attributeOptionCombo()) - .categoryOptionCombo(dataValue.categoryOptionCombo()) - .dataElement(dataValue.dataElement()) - .orgUnit(dataValue.organisationUnit()) - .period(dataValue.period()) - .tableReference(DataValueTableInfo.TABLE_INFO.name()) - .status(ImportStatus.WARNING) - .errorCode("") - .displayDescription("") - .created(Date()) - } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt new file mode 100644 index 0000000000..6b8e98828d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import java.util.ArrayList +import org.hisp.dhis.android.core.datavalue.DataValue +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.imports.internal.ImportConflict + +internal object PastExpiryDate : DataValueImportConflictItem { + + val regex: Regex = Regex("Current date is past expiry days for period (\\d+) and data set: (\\w{11})") + + override fun matches(conflict: ImportConflict): Boolean { + return regex.matches(conflict.value()) + } + + override fun getDataValues(conflict: ImportConflict, dataValues: List): List { + val foundDataValuesConflicts: MutableList = ArrayList() + val period = conflict.`object`() + val dataSet = regex.find(conflict.value())?.groupValues?.get(1) + dataValues.forEach { dataValue -> + if (dataValue.period() == period) { + foundDataValuesConflicts.add( + getConflictBuilder( + dataValue = dataValue, + conflict = conflict, + displayDescription = conflict.value() + ).build() + ) + } + } + + return foundDataValuesConflicts + } +} diff --git a/core/src/sharedTest/resources/datavalueset/data_value_set_warning.json b/core/src/sharedTest/resources/datavalueset/data_value_set_warning.json index dabfdd390a..29ceb60547 100644 --- a/core/src/sharedTest/resources/datavalueset/data_value_set_warning.json +++ b/core/src/sharedTest/resources/datavalueset/data_value_set_warning.json @@ -38,7 +38,7 @@ "conflicts": [ { "object": "40L", - "value": "El valor de dato no es un entero, must match data element type: vANAXwtLwcT" + "value": "Data value is not a positive integer, must match data element type: vANAXwtLwcT" } ], "dataSetComplete": "false" diff --git a/core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json b/core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json new file mode 100644 index 0000000000..e1707d440f --- /dev/null +++ b/core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json @@ -0,0 +1,49 @@ +{ + "responseType": "ImportSummary", + "status": "WARNING", + "importOptions": { + "idSchemes": {}, + "dryRun": false, + "async": false, + "importStrategy": "CREATE_AND_UPDATE", + "mergeMode": "REPLACE", + "reportMode": "FULL", + "skipExistingCheck": false, + "sharing": false, + "skipNotifications": false, + "skipAudit": false, + "datasetAllowsPeriods": false, + "strictPeriods": false, + "strictDataElements": false, + "strictCategoryOptionCombos": false, + "strictAttributeOptionCombos": false, + "strictOrganisationUnits": false, + "requireCategoryOptionCombo": false, + "requireAttributeOptionCombo": false, + "skipPatternValidation": false, + "ignoreEmptyCollection": false, + "force": false, + "firstRowIsHeader": true, + "skipLastUpdated": false, + "mergeDataValues": false, + "skipCache": false + }, + "description": "Import process completed successfully", + "importCount": { + "imported": 0, + "updated": 0, + "ignored": 2, + "deleted": 0 + }, + "conflicts": [ + { + "object": "202104", + "value": "Current date is past expiry days for period 202104 and data set: BfMAe6Itzgt" + }, + { + "object": "202103", + "value": "Current date is past expiry days for period 202103 and data set: BfMAe6Itzgt" + } + ], + "dataSetComplete": "false" +} \ No newline at end of file From bca441ef3c56fca9743132524fa23332a2bc91cb Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Jun 2021 08:38:20 +0200 Subject: [PATCH 075/308] [ANDROSDK-1379] InvalidDataElementTypeConflict.kt shows element type in displayDescription --- .../internal/DataValueConflictParser.kt | 12 +++++++----- .../InvalidDataElementTypeConflict.kt | 18 ++++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt index 72aa02a7f8..c36f3c8647 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt @@ -29,19 +29,21 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable -import javax.inject.Inject +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataelement.DataElement import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict -import org.hisp.dhis.android.core.datavalue.internal.conflicts.PastExpiryDate import org.hisp.dhis.android.core.imports.internal.ImportConflict +import javax.inject.Inject @Reusable -internal class DataValueConflictParser @Inject constructor() { +internal class DataValueConflictParser @Inject constructor( + dataElementStore: IdentifiableObjectStore +) { private val conflicts = listOf( - InvalidDataElementTypeConflict, - PastExpiryDate + InvalidDataElementTypeConflict(dataElementStore) ) fun getDataValueConflicts( diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt index 797bbdbaf6..4029c34945 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -28,16 +28,18 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataelement.DataElement import java.util.ArrayList import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.imports.internal.ImportConflict -internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { +internal data class InvalidDataElementTypeConflict( + private val dataElementStore: IdentifiableObjectStore +) : DataValueImportConflictItem { private val regex: Regex = Regex(".*, must match data element type: (\\w{11})") - private fun description(value: String, elementType: String) = - "DataValue $value must match with data element type $elementType" override fun matches(conflict: ImportConflict): Boolean { return regex.matches(conflict.value()) @@ -53,9 +55,8 @@ internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { getConflictBuilder( dataValue = dataValue, conflict = conflict, - displayDescription = dataValue.dataElement()?.let { - description(conflict.`object`(), it) - } ?: conflict.value() + displayDescription = getDisplayDescription(conflict.`object`(), dataValue.dataElement()) + ?: conflict.value() ).build() ) } @@ -63,4 +64,9 @@ internal object InvalidDataElementTypeConflict : DataValueImportConflictItem { return foundDataValuesConflicts } + + private fun getDisplayDescription(value: String, dataElementUid: String?) = dataElementUid?.let { + val dataElementType = dataElementStore.selectByUid(it)?.valueType().toString() + "DataValue $value must match with data element type $dataElementType" + } } From 9684daab3caa4aa8ac969673db2cd4956d869bbf Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Jun 2021 11:47:33 +0200 Subject: [PATCH 076/308] [ANDROSDK-1379] PeriodAfterLatestOpenFutureConflict.kt --- .../internal/DataValueConflictParser.kt | 8 ++- .../conflicts/DataValueImportConflictItem.kt | 7 +- .../InvalidDataElementTypeConflict.kt | 11 ++- ...xpiryDate.kt => PastExpiryDateConflict.kt} | 9 +-- .../PeriodAfterLatestOpenFutureConflict.kt | 70 +++++++++++++++++++ ...data_value_set_warning_expired_period.json | 49 ------------- 6 files changed, 89 insertions(+), 65 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/{PastExpiryDate.kt => PastExpiryDateConflict.kt} (90%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt delete mode 100644 core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt index c36f3c8647..a3eed6b308 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt @@ -29,13 +29,15 @@ package org.hisp.dhis.android.core.datavalue.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.dataelement.DataElement import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict +import org.hisp.dhis.android.core.datavalue.internal.conflicts.PastExpiryDateConflict +import org.hisp.dhis.android.core.datavalue.internal.conflicts.PeriodAfterLatestOpenFutureConflict import org.hisp.dhis.android.core.imports.internal.ImportConflict -import javax.inject.Inject @Reusable internal class DataValueConflictParser @Inject constructor( @@ -43,7 +45,9 @@ internal class DataValueConflictParser @Inject constructor( ) { private val conflicts = listOf( - InvalidDataElementTypeConflict(dataElementStore) + InvalidDataElementTypeConflict(dataElementStore), + PastExpiryDateConflict(), + PeriodAfterLatestOpenFutureConflict(dataElementStore) ) fun getDataValueConflicts( diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt index c7032908ca..198d4ac62e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -36,9 +36,14 @@ import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.ImportConflict internal interface DataValueImportConflictItem { - fun matches(conflict: ImportConflict): Boolean + val regex: Regex + fun getDataValues(conflict: ImportConflict, dataValues: List): List + fun matches(conflict: ImportConflict): Boolean { + return regex.matches(conflict.value()) + } + fun getConflictBuilder( dataValue: DataValue, conflict: ImportConflict, diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt index 4029c34945..116eac50d1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -28,22 +28,19 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts +import java.util.ArrayList import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.dataelement.DataElement -import java.util.ArrayList import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.imports.internal.ImportConflict -internal data class InvalidDataElementTypeConflict( +internal class InvalidDataElementTypeConflict( private val dataElementStore: IdentifiableObjectStore ) : DataValueImportConflictItem { - private val regex: Regex = Regex(".*, must match data element type: (\\w{11})") - - override fun matches(conflict: ImportConflict): Boolean { - return regex.matches(conflict.value()) - } + override val regex: Regex + get() = Regex(".*, must match data element type: (\\w{11})") override fun getDataValues(conflict: ImportConflict, dataValues: List): List { val foundDataValuesConflicts: MutableList = ArrayList() diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt similarity index 90% rename from core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt rename to core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt index 6b8e98828d..09e7c72db0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDate.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt @@ -33,13 +33,10 @@ import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.imports.internal.ImportConflict -internal object PastExpiryDate : DataValueImportConflictItem { +internal class PastExpiryDateConflict : DataValueImportConflictItem { - val regex: Regex = Regex("Current date is past expiry days for period (\\d+) and data set: (\\w{11})") - - override fun matches(conflict: ImportConflict): Boolean { - return regex.matches(conflict.value()) - } + override val regex: Regex + get() = Regex("Current date is past expiry days for period (\\d+) and data set: (\\w{11})") override fun getDataValues(conflict: ImportConflict, dataValues: List): List { val foundDataValuesConflicts: MutableList = ArrayList() diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt new file mode 100644 index 0000000000..cc9e181487 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import java.util.ArrayList +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.datavalue.DataValue +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.imports.internal.ImportConflict + +@Suppress("MagicNumber") +internal class PeriodAfterLatestOpenFutureConflict( + private val dataElementStore: IdentifiableObjectStore +) : DataValueImportConflictItem { + + override val regex: Regex + get() = Regex("Period: (\\d+) is after latest open future period: (\\d+) for data element: (\\w{11})") + + override fun getDataValues(conflict: ImportConflict, dataValues: List): List { + val foundDataValuesConflicts: MutableList = ArrayList() + val period = conflict.`object`() + val dataElementUid = regex.find(conflict.value())?.groupValues?.get(3) + for (dataValue in dataValues) { + if (dataValue.period() == period && dataValue.dataElement() == dataElementUid) { + foundDataValuesConflicts.add( + getConflictBuilder( + dataValue = dataValue, + conflict = conflict, + displayDescription = getDisplayDescription(conflict.`object`(), dataValue.dataElement()) + ?: conflict.value() + ).build() + ) + } + } + + return foundDataValuesConflicts + } + + private fun getDisplayDescription(value: String, dataElementUid: String?) = dataElementUid?.let { + val dataElementType = dataElementStore.selectByUid(it)?.valueType().toString() + "Period $value is after latest open future period for data element: $dataElementType" + } +} diff --git a/core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json b/core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json deleted file mode 100644 index e1707d440f..0000000000 --- a/core/src/sharedTest/resources/datavalueset/data_value_set_warning_expired_period.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "responseType": "ImportSummary", - "status": "WARNING", - "importOptions": { - "idSchemes": {}, - "dryRun": false, - "async": false, - "importStrategy": "CREATE_AND_UPDATE", - "mergeMode": "REPLACE", - "reportMode": "FULL", - "skipExistingCheck": false, - "sharing": false, - "skipNotifications": false, - "skipAudit": false, - "datasetAllowsPeriods": false, - "strictPeriods": false, - "strictDataElements": false, - "strictCategoryOptionCombos": false, - "strictAttributeOptionCombos": false, - "strictOrganisationUnits": false, - "requireCategoryOptionCombo": false, - "requireAttributeOptionCombo": false, - "skipPatternValidation": false, - "ignoreEmptyCollection": false, - "force": false, - "firstRowIsHeader": true, - "skipLastUpdated": false, - "mergeDataValues": false, - "skipCache": false - }, - "description": "Import process completed successfully", - "importCount": { - "imported": 0, - "updated": 0, - "ignored": 2, - "deleted": 0 - }, - "conflicts": [ - { - "object": "202104", - "value": "Current date is past expiry days for period 202104 and data set: BfMAe6Itzgt" - }, - { - "object": "202103", - "value": "Current date is past expiry days for period 202103 and data set: BfMAe6Itzgt" - } - ], - "dataSetComplete": "false" -} \ No newline at end of file From 9e1b366ba231b976aaf930b452cedd9c9da2b4c7 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Jun 2021 14:27:44 +0200 Subject: [PATCH 077/308] [ANDROSDK-1379] display dataset name in PastExpiryDateConflict.kt --- .../internal/DataValueConflictParser.kt | 7 +++++-- .../internal/DataValueImportHandler.kt | 2 +- .../datavalue/internal/DataValueStore.java | 12 +++++++++++- .../InvalidDataElementTypeConflict.kt | 14 +++++++------- .../conflicts/PastExpiryDateConflict.kt | 19 +++++++++++++++---- .../PeriodAfterLatestOpenFutureConflict.kt | 14 +++++++------- .../DataValueImportHandlerShould.java | 10 +++++++++- 7 files changed, 55 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt index a3eed6b308..1a23229708 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictParser.kt @@ -32,6 +32,7 @@ import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.dataset.DataSet import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.internal.conflicts.InvalidDataElementTypeConflict @@ -41,12 +42,14 @@ import org.hisp.dhis.android.core.imports.internal.ImportConflict @Reusable internal class DataValueConflictParser @Inject constructor( - dataElementStore: IdentifiableObjectStore + dataElementStore: IdentifiableObjectStore, + dataValueStore: DataValueStore, + dataSetStore: IdentifiableObjectStore ) { private val conflicts = listOf( InvalidDataElementTypeConflict(dataElementStore), - PastExpiryDateConflict(), + PastExpiryDateConflict(dataValueStore, dataSetStore), PeriodAfterLatestOpenFutureConflict(dataElementStore) ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt index a37b5f7b82..47bcbe5498 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt @@ -66,7 +66,7 @@ internal class DataValueImportHandler @Inject constructor( deleteDataValueConflicts(dataValueSet.dataValues) - if (state == WARNING || state == ERROR) { + if (state == WARNING) { handleDataValueWarnings(dataValueSet.dataValues, dataValueImportSummary) } else { setStateToDataValues(state, dataValueSet.dataValues) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java index d4c0df825a..a760c7b476 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStoreImpl; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.datavalue.DataValue; +import org.hisp.dhis.android.core.datavalue.DataValueByDataSetQueryHelper; import org.hisp.dhis.android.core.datavalue.DataValueTableInfo; import java.util.Collection; @@ -100,7 +101,7 @@ Collection getDataValuesWithState(State state) { /** * @param dataValue DataValue element you want to update - * @param newState The new state to be set for the DataValue + * @param newState The new state to be set for the DataValue */ public void setState(DataValue dataValue, State newState) { @@ -135,4 +136,13 @@ private WhereClauseBuilder uniqueWhereClauseBuilder(DataValue dataValue) { .appendKeyStringValue(Columns.CATEGORY_OPTION_COMBO, dataValue.categoryOptionCombo()) .appendKeyStringValue(Columns.ATTRIBUTE_OPTION_COMBO, dataValue.attributeOptionCombo()); } + + public Boolean existsInDataSet(DataValue dataValue, String dataSetUid) { + WhereClauseBuilder whereClauseBuilder = uniqueWhereClauseBuilder(dataValue) + .appendInSubQuery( + DataValueByDataSetQueryHelper.getKey(), + DataValueByDataSetQueryHelper.whereClause(dataSetUid) + ); + return selectWhere(whereClauseBuilder.build()).size() > 0; + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt index 116eac50d1..c02d9adb48 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflict.kt @@ -46,14 +46,13 @@ internal class InvalidDataElementTypeConflict( val foundDataValuesConflicts: MutableList = ArrayList() val value = conflict.`object`() val dataElementUid = regex.find(conflict.value())?.groupValues?.get(1) - for (dataValue in dataValues) { + dataValues.forEach { dataValue -> if (dataValue.value() == value && dataValue.dataElement() == dataElementUid) { foundDataValuesConflicts.add( getConflictBuilder( dataValue = dataValue, conflict = conflict, - displayDescription = getDisplayDescription(conflict.`object`(), dataValue.dataElement()) - ?: conflict.value() + displayDescription = getDisplayDescription(conflict, value, dataValue.dataElement()) ).build() ) } @@ -62,8 +61,9 @@ internal class InvalidDataElementTypeConflict( return foundDataValuesConflicts } - private fun getDisplayDescription(value: String, dataElementUid: String?) = dataElementUid?.let { - val dataElementType = dataElementStore.selectByUid(it)?.valueType().toString() - "DataValue $value must match with data element type $dataElementType" - } + private fun getDisplayDescription(conflict: ImportConflict, value: String, dataElementUid: String?) = + dataElementUid?.let { + val dataElementType = dataElementStore.selectByUid(it)?.valueType().toString() + "DataValue $value must match with data element type $dataElementType" + } ?: conflict.value() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt index 09e7c72db0..697677fce5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflict.kt @@ -29,11 +29,17 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts import java.util.ArrayList +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataset.DataSet import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.internal.DataValueStore import org.hisp.dhis.android.core.imports.internal.ImportConflict -internal class PastExpiryDateConflict : DataValueImportConflictItem { +internal class PastExpiryDateConflict( + private val dataValueStore: DataValueStore, + private val dataSetStore: IdentifiableObjectStore +) : DataValueImportConflictItem { override val regex: Regex get() = Regex("Current date is past expiry days for period (\\d+) and data set: (\\w{11})") @@ -41,14 +47,14 @@ internal class PastExpiryDateConflict : DataValueImportConflictItem { override fun getDataValues(conflict: ImportConflict, dataValues: List): List { val foundDataValuesConflicts: MutableList = ArrayList() val period = conflict.`object`() - val dataSet = regex.find(conflict.value())?.groupValues?.get(1) + val dataSetUid = regex.find(conflict.value())?.groupValues?.get(2) dataValues.forEach { dataValue -> - if (dataValue.period() == period) { + if (dataValue.period() == period && dataValueStore.existsInDataSet(dataValue, dataSetUid)) { foundDataValuesConflicts.add( getConflictBuilder( dataValue = dataValue, conflict = conflict, - displayDescription = conflict.value() + displayDescription = getDisplayDescription(conflict, dataValue, dataSetUid!!) ).build() ) } @@ -56,4 +62,9 @@ internal class PastExpiryDateConflict : DataValueImportConflictItem { return foundDataValuesConflicts } + + private fun getDisplayDescription(conflict: ImportConflict, dataValue: DataValue, dataSetUid: String) = + dataSetStore.selectByUid(dataSetUid)?.let { dataSet -> + "Current date is past expiry days for period ${dataValue.period()} and data set: ${dataSet.displayName()}" + } ?: conflict.value() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt index cc9e181487..16dc17e608 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflict.kt @@ -47,14 +47,13 @@ internal class PeriodAfterLatestOpenFutureConflict( val foundDataValuesConflicts: MutableList = ArrayList() val period = conflict.`object`() val dataElementUid = regex.find(conflict.value())?.groupValues?.get(3) - for (dataValue in dataValues) { + dataValues.forEach { dataValue -> if (dataValue.period() == period && dataValue.dataElement() == dataElementUid) { foundDataValuesConflicts.add( getConflictBuilder( dataValue = dataValue, conflict = conflict, - displayDescription = getDisplayDescription(conflict.`object`(), dataValue.dataElement()) - ?: conflict.value() + displayDescription = getDisplayDescription(conflict, period, dataValue.dataElement()) ).build() ) } @@ -63,8 +62,9 @@ internal class PeriodAfterLatestOpenFutureConflict( return foundDataValuesConflicts } - private fun getDisplayDescription(value: String, dataElementUid: String?) = dataElementUid?.let { - val dataElementType = dataElementStore.selectByUid(it)?.valueType().toString() - "Period $value is after latest open future period for data element: $dataElementType" - } + private fun getDisplayDescription(conflict: ImportConflict, period: String, dataElementUid: String?) = + dataElementUid?.let { + val dataElementType = dataElementStore.selectByUid(it)?.valueType().toString() + "Period $period is after latest open future period for data element: $dataElementType" + } ?: conflict.value() } diff --git a/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandlerShould.java index 49e3544fa1..0f6aefd0bb 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandlerShould.java @@ -28,8 +28,10 @@ package org.hisp.dhis.android.core.datavalue.internal; +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.datavalue.DataValue; +import org.hisp.dhis.android.core.datavalue.DataValueConflict; import org.hisp.dhis.android.core.imports.ImportStatus; import org.hisp.dhis.android.core.imports.internal.DataValueImportSummary; import org.junit.Before; @@ -53,6 +55,12 @@ public class DataValueImportHandlerShould { @Mock DataValueStore dataValueStore; + @Mock + DataValueConflictParser dataValueConflictParser; + + @Mock + ObjectStore dataValueConflictStore; + @Mock DataValueImportSummary dataValueImportSummary; @@ -69,7 +77,7 @@ public void setUp() { dataValueSet = new DataValueSet(Collections.singletonList(dataValue)); - dataValueImportHandler = new DataValueImportHandler(dataValueStore); + dataValueImportHandler = new DataValueImportHandler(dataValueStore, dataValueConflictParser, dataValueConflictStore); } @Test From 1740cd86a631cba359274d018ea4b2a51bd6a6e3 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Jun 2021 17:23:00 +0200 Subject: [PATCH 078/308] Rename .java to .kt --- .../{DataValueModuleWiper.java => DataValueModuleWiper.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/{DataValueModuleWiper.java => DataValueModuleWiper.kt} (100%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.kt similarity index 100% rename from core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.java rename to core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.kt From 1cd7340bc25dae14045be565c6fe3ec23f846c02 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 8 Jun 2021 17:23:00 +0200 Subject: [PATCH 079/308] [ANDROSDK-1379] DataValueImportConflict tests --- .../wipe/WipeDBCallMockIntegrationShould.java | 3 ++ .../internal/DataValueModuleWiper.kt | 41 ++++++-------- .../DataValueImportConflictSamples.kt | 49 +++++++++++++++++ .../InvalidDataElementTypeConflictShould.kt | 51 ++++++++++++++++++ .../conflicts/PastExpiryDateConflictShould.kt | 53 +++++++++++++++++++ ...riodAfterLatestOpenFutureConflictShould.kt | 52 ++++++++++++++++++ 6 files changed, 223 insertions(+), 26 deletions(-) create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictSamples.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflictShould.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflictShould.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflictShould.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index bcce35a56b..5a2666e66e 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -29,6 +29,8 @@ package org.hisp.dhis.android.core.wipe; import org.hisp.dhis.android.core.data.database.DatabaseAssert; +import org.hisp.dhis.android.core.datavalue.DataValueConflict; +import org.hisp.dhis.android.core.datavalue.internal.DataValueConflictStore; import org.hisp.dhis.android.core.fileresource.FileResource; import org.hisp.dhis.android.core.fileresource.internal.FileResourceStoreImpl; import org.hisp.dhis.android.core.imports.TrackerImportConflict; @@ -98,5 +100,6 @@ private void givenOthersInDatabase() { .lastUpdated(new Date()) .build() ); + DataValueConflictStore.create(databaseAdapter).insert(DataValueConflict.builder().build()); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.kt index 2f9fb66a28..2432cf5698 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueModuleWiper.kt @@ -25,38 +25,27 @@ * (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.datavalue.internal -package org.hisp.dhis.android.core.datavalue.internal; - -import org.hisp.dhis.android.core.datavalue.DataValueTableInfo; -import org.hisp.dhis.android.core.domain.aggregated.data.internal.AggregatedDataSyncTableInfo; -import org.hisp.dhis.android.core.wipe.internal.ModuleWiper; -import org.hisp.dhis.android.core.wipe.internal.TableWiper; - -import javax.inject.Inject; - -import dagger.Reusable; +import dagger.Reusable +import javax.inject.Inject +import org.hisp.dhis.android.core.datavalue.DataValueConflictTableInfo +import org.hisp.dhis.android.core.datavalue.DataValueTableInfo +import org.hisp.dhis.android.core.domain.aggregated.data.internal.AggregatedDataSyncTableInfo +import org.hisp.dhis.android.core.wipe.internal.ModuleWiper +import org.hisp.dhis.android.core.wipe.internal.TableWiper @Reusable -public final class DataValueModuleWiper implements ModuleWiper { - - private final TableWiper tableWiper; - - @Inject - DataValueModuleWiper(TableWiper tableWiper) { - this.tableWiper = tableWiper; - } - - @Override - public void wipeMetadata() { +class DataValueModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { + override fun wipeMetadata() { // No metadata to wipe } - @Override - public void wipeData() { + override fun wipeData() { tableWiper.wipeTables( - DataValueTableInfo.TABLE_INFO, - AggregatedDataSyncTableInfo.TABLE_INFO - ); + DataValueTableInfo.TABLE_INFO, + AggregatedDataSyncTableInfo.TABLE_INFO, + DataValueConflictTableInfo.TABLE_INFO + ) } } diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictSamples.kt new file mode 100644 index 0000000000..3b38427cdd --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictSamples.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import org.hisp.dhis.android.core.imports.internal.ImportConflict + +object DataValueImportConflictSamples { + + fun invalidDataElementType(): ImportConflict = ImportConflict.create( + "40L", + "Data value is not a positive integer, must match data element type: vANAXwtLwcT" + ) + + fun pastExpiryDate(): ImportConflict = ImportConflict.create( + "202104", + "Current date is past expiry days for period 202104 and data set: BfMAe6Itzgt" + ) + + fun periodAfterLatestOpenFuture(): ImportConflict = ImportConflict.create( + "202111", + "Period: 202111 is after latest open future period: 202105 for data element: UOlfIjgN8X6" + ) +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflictShould.kt b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflictShould.kt new file mode 100644 index 0000000000..dbea42e521 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/InvalidDataElementTypeConflictShould.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import com.nhaarman.mockitokotlin2.mock +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataelement.DataElement +import org.junit.Before +import org.junit.Test + +internal class InvalidDataElementTypeConflictShould { + + private lateinit var invalidDataElementTypeConflict: InvalidDataElementTypeConflict + private val dataElementStore: IdentifiableObjectStore = mock() + + @Before + fun setUp() { + invalidDataElementTypeConflict = InvalidDataElementTypeConflict(dataElementStore) + } + + @Test + fun `Should match error messages`() { + assert(invalidDataElementTypeConflict.matches(DataValueImportConflictSamples.invalidDataElementType())) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflictShould.kt b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflictShould.kt new file mode 100644 index 0000000000..f31afc1a5f --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PastExpiryDateConflictShould.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import com.nhaarman.mockitokotlin2.mock +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataset.DataSet +import org.hisp.dhis.android.core.datavalue.internal.DataValueStore +import org.junit.Before +import org.junit.Test + +internal class PastExpiryDateConflictShould { + + private lateinit var pastExpiryDateConflict: PastExpiryDateConflict + private val dataValueStore: DataValueStore = mock() + private val dataSetStore: IdentifiableObjectStore = mock() + + @Before + fun setUp() { + pastExpiryDateConflict = PastExpiryDateConflict(dataValueStore, dataSetStore) + } + + @Test + fun `Should match error messages`() { + assert(pastExpiryDateConflict.matches(DataValueImportConflictSamples.pastExpiryDate())) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflictShould.kt b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflictShould.kt new file mode 100644 index 0000000000..161c8fa85b --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/PeriodAfterLatestOpenFutureConflictShould.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal.conflicts + +import com.nhaarman.mockitokotlin2.mock +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.dataelement.DataElement +import org.junit.Before +import org.junit.Test + +internal class PeriodAfterLatestOpenFutureConflictShould { + private lateinit var periodAfterLatestOpenFutureConflict: PeriodAfterLatestOpenFutureConflict + private val dataElementStore: IdentifiableObjectStore = mock() + + @Before + fun setUp() { + periodAfterLatestOpenFutureConflict = PeriodAfterLatestOpenFutureConflict(dataElementStore) + } + + @Test + fun `Should match error messages`() { + assert( + periodAfterLatestOpenFutureConflict.matches(DataValueImportConflictSamples.periodAfterLatestOpenFuture()) + ) + } +} From 3e6fb05669b2df619a204ff30fd4ff2e11616a4c Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 9 Jun 2021 09:53:11 +0200 Subject: [PATCH 080/308] [ANDROSDK-1379] Update database version for DataValueConflict table --- core/src/main/assets/migrations/101.sql | 1 + core/src/main/assets/snapshots/{100.sql => 101.sql} | 1 + .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 core/src/main/assets/migrations/101.sql rename core/src/main/assets/snapshots/{100.sql => 101.sql} (99%) diff --git a/core/src/main/assets/migrations/101.sql b/core/src/main/assets/migrations/101.sql new file mode 100644 index 0000000000..30cb71622e --- /dev/null +++ b/core/src/main/assets/migrations/101.sql @@ -0,0 +1 @@ +CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, tableReference TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/100.sql b/core/src/main/assets/snapshots/101.sql similarity index 99% rename from core/src/main/assets/snapshots/100.sql rename to core/src/main/assets/snapshots/101.sql index 8085dc1024..d085191812 100644 --- a/core/src/main/assets/snapshots/100.sql +++ b/core/src/main/assets/snapshots/101.sql @@ -110,3 +110,4 @@ CREATE TABLE ProgramStageAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREME CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, attribute)); CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); +CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, tableReference TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index ce80aacd50..a7adfeb070 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 100; + static final int VERSION = 101; private final AssetManager assetManager; private final int targetVersion; From 53d778fa1a552ef4333a4697068eb806660b3c48 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 9 Jun 2021 13:34:18 +0200 Subject: [PATCH 081/308] [ANDROSDK-1379] Remove TABLE_REFERENCE property from DataValueConflict --- .../android/core/MetadataCallRealIntegrationShould.java | 3 +-- core/src/main/assets/migrations/101.sql | 2 +- core/src/main/assets/snapshots/101.sql | 2 +- .../dhis/android/core/datavalue/DataValueConflict.java | 6 ------ .../android/core/datavalue/DataValueConflictTableInfo.kt | 2 -- .../core/datavalue/internal/DataValueConflictStore.kt | 9 ++++----- .../core/datavalue/internal/DataValueImportHandler.kt | 4 ---- .../internal/conflicts/DataValueImportConflictItem.kt | 1 - 8 files changed, 7 insertions(+), 22 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java index e3b514c19b..21b6a63bfe 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java @@ -31,7 +31,6 @@ import android.util.Log; import org.junit.Before; -import org.junit.Test; import java.io.IOException; @@ -71,7 +70,7 @@ make a debugger break point where desired (after sync complete) //This test is uncommented because technically it is flaky. //It depends on a live server to operate and the login is hardcoded here. //Uncomment in order to quickly test changes vs a real server, but keep it uncommented after. - @Test +// @Test public void response_successful_on_sync_meta_data_once() throws Exception { d2.userModule().logIn(username, password, url).blockingGet(); diff --git a/core/src/main/assets/migrations/101.sql b/core/src/main/assets/migrations/101.sql index 30cb71622e..500048d629 100644 --- a/core/src/main/assets/migrations/101.sql +++ b/core/src/main/assets/migrations/101.sql @@ -1 +1 @@ -CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, tableReference TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); \ No newline at end of file +CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/101.sql b/core/src/main/assets/snapshots/101.sql index d085191812..97d20251bc 100644 --- a/core/src/main/assets/snapshots/101.sql +++ b/core/src/main/assets/snapshots/101.sql @@ -110,4 +110,4 @@ CREATE TABLE ProgramStageAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREME CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, attribute)); CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); -CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, tableReference TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); +CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java index 5df3ea057a..a2b19de9d3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflict.java @@ -67,13 +67,9 @@ public abstract class DataValueConflict extends BaseObject { @Nullable public abstract String orgUnit(); - @Nullable - public abstract String tableReference(); - @Nullable public abstract String errorCode(); - // TODO legible description chade id by data elemtn type @Nullable public abstract String displayDescription(); @@ -112,8 +108,6 @@ public static abstract class Builder extends BaseObject.Builder { public abstract Builder orgUnit(String orgUnit); - public abstract Builder tableReference(String tableReference); - public abstract Builder errorCode(String errorCode); public abstract Builder displayDescription(String displayDescription); diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt index c59559f881..04c40955a9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt @@ -54,7 +54,6 @@ object DataValueConflictTableInfo { DATA_ELEMENT, PERIOD, ORG_UNIT, - TABLE_REFERENCE, ERROR_CODE, DISPLAY_DESCRIPTION, STATUS, @@ -70,7 +69,6 @@ object DataValueConflictTableInfo { const val DATA_ELEMENT = "dataElement" const val PERIOD = "period" const val ORG_UNIT = "orgUnit" - const val TABLE_REFERENCE = "tableReference" const val ERROR_CODE = "errorCode" const val DISPLAY_DESCRIPTION = "displayDescription" const val STATUS = "status" diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt index 8463f521af..2d5175cf72 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStore.kt @@ -45,11 +45,10 @@ internal object DataValueConflictStore { w.bind(5, o.dataElement()) w.bind(6, o.period()) w.bind(7, o.orgUnit()) - w.bind(8, o.tableReference()) - w.bind(9, o.errorCode()) - w.bind(10, o.displayDescription()) - w.bind(11, o.status()) - w.bind(12, o.created()) + w.bind(8, o.errorCode()) + w.bind(9, o.displayDescription()) + w.bind(10, o.status()) + w.bind(11, o.created()) } @JvmStatic diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt index 47bcbe5498..be04f163f3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt @@ -76,10 +76,6 @@ internal class DataValueImportHandler @Inject constructor( private fun deleteDataValueConflicts(dataValues: List) { dataValues.forEach { dataValue -> val whereClause = WhereClauseBuilder() - .appendKeyStringValue( - DataValueConflictTableInfo.Columns.TABLE_REFERENCE, - DataValueTableInfo.TABLE_INFO.name() - ) .appendKeyStringValue( DataValueConflictTableInfo.Columns.ATTRIBUTE_OPTION_COMBO, dataValue.attributeOptionCombo() diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt index 198d4ac62e..d2939b44d3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -57,7 +57,6 @@ internal interface DataValueImportConflictItem { .dataElement(dataValue.dataElement()) .orgUnit(dataValue.organisationUnit()) .period(dataValue.period()) - .tableReference(DataValueTableInfo.TABLE_INFO.name()) .status(ImportStatus.WARNING) .displayDescription(displayDescription) .created(Date()) From 582fe1985cde284b1168e249c3267fb4ee7cb9e9 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 9 Jun 2021 13:34:41 +0200 Subject: [PATCH 082/308] [ANDROSDK-1379] DataValueConflictStoreIntegrationShould.kt --- .../ObjectStoreAbstractIntegrationShould.java | 3 +- ...DataValueConflictStoreIntegrationShould.kt | 48 ++++++++++++++++ .../internal/DataValueImportHandler.kt | 1 - .../conflicts/DataValueImportConflictItem.kt | 1 - .../datavalue/DataValueConflictSamples.kt | 57 +++++++++++++++++++ 5 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStoreIntegrationShould.kt create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueConflictSamples.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/ObjectStoreAbstractIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/ObjectStoreAbstractIntegrationShould.java index 30687bce89..aa071723b8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/ObjectStoreAbstractIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/ObjectStoreAbstractIntegrationShould.java @@ -74,8 +74,7 @@ public void insert_and_select_first_object() { @Test public void insert_as_content_values_and_select_first_object() { - long rowsInserted = databaseAdapter.insert(tableInfo.name(), null, object.toContentValues()); - assertThat(rowsInserted).isEqualTo(1); + databaseAdapter.insert(tableInfo.name(), null, object.toContentValues()); M objectFromDb = store.selectFirst(); assertEqualsIgnoreId(objectFromDb); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStoreIntegrationShould.kt new file mode 100644 index 0000000000..e40b85fdd9 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValueConflictStoreIntegrationShould.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2021, 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.core.datavalue.internal + +import org.hisp.dhis.android.core.data.database.ObjectStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.data.datavalue.DataValueConflictSamples +import org.hisp.dhis.android.core.datavalue.DataValueConflict +import org.hisp.dhis.android.core.datavalue.DataValueConflictTableInfo +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class DataValueConflictStoreIntegrationShould : ObjectStoreAbstractIntegrationShould( + DataValueConflictStore.create(TestDatabaseAdapterFactory.get()), + DataValueConflictTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() +) { + override fun buildObject(): DataValueConflict { + return DataValueConflictSamples.get() + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt index be04f163f3..13bb86803f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueImportHandler.kt @@ -38,7 +38,6 @@ import org.hisp.dhis.android.core.common.State.WARNING import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict import org.hisp.dhis.android.core.datavalue.DataValueConflictTableInfo -import org.hisp.dhis.android.core.datavalue.DataValueTableInfo import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.DataValueImportSummary import org.hisp.dhis.android.core.imports.internal.ImportConflict diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt index d2939b44d3..796ddb3504 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/conflicts/DataValueImportConflictItem.kt @@ -31,7 +31,6 @@ package org.hisp.dhis.android.core.datavalue.internal.conflicts import java.util.Date import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.DataValueConflict -import org.hisp.dhis.android.core.datavalue.DataValueTableInfo import org.hisp.dhis.android.core.imports.ImportStatus import org.hisp.dhis.android.core.imports.internal.ImportConflict diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueConflictSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueConflictSamples.kt new file mode 100644 index 0000000000..d96550f294 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueConflictSamples.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.datavalue + +import java.text.ParseException +import java.util.Date +import org.hisp.dhis.android.core.common.BaseIdentifiableObject +import org.hisp.dhis.android.core.datavalue.DataValueConflict + +object DataValueConflictSamples { + + fun get(): DataValueConflict { + return DataValueConflict.builder() + .value("KKK") + .attributeOptionCombo("HllvX50cXC0") + .categoryOptionCombo("Prlt0C1RF0s") + .created(getDate("021-06-02T12:38:53.743")) + .dataElement("UOlfIjgN8X6") + .period("202101") + .orgUnit("DiszpKrYNg8").build() + } + + private fun getDate(dateStr: String): Date? { + return try { + BaseIdentifiableObject.DATE_FORMAT.parse(dateStr) + } catch (e: ParseException) { + e.printStackTrace() + null + } + } +} From 40c80230a95c8b9cdf26aae07527c82802aab337 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 31 May 2021 14:26:19 +0200 Subject: [PATCH 083/308] [ANDROSDK-1385] Analytic models --- .../android/core/analytics/AnalyticsModule.kt | 6 + .../core/analytics/AnalyticsModuleImpl.kt | 13 +- .../analytics/AnalyticsPackageDIModule.kt | 2 + .../aggregated/AggregatedEntityDIModule.kt | 50 +++++ .../analytics/aggregated/AnalyticsModel.kt | 79 +++++++ .../aggregated/AnalyticsRepository.kt | 43 ++++ .../aggregated/DimensionalResponse.kt | 41 ++++ .../aggregated/GridAnalyticsResponse.kt | 58 +++++ .../aggregated/VisualizationsRepository.kt | 41 ++++ .../aggregated/mock/AggregatedSamples.kt | 44 ++++ .../aggregated/mock/AnalyticsTester.java | 52 +++++ .../aggregated/mock/AnalyticsTestterKt.kt | 55 +++++ .../mock/DimensionalResponseSamples.kt | 98 +++++++++ .../mock/GridAnalyticsResponseSamples.kt | 129 +++++++++++ .../mock/MockAnalyticsRepository.kt | 51 +++++ .../mock/MockVisualizationsRepository.kt | 48 ++++ .../aggregated/mock/visualization.json | 206 ++++++++++++++++++ .../core/common/RelativeOrganisationUnit.kt | 34 +++ 18 files changed, 1048 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt index 491be7606d..c27be745d1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt @@ -27,9 +27,15 @@ */ package org.hisp.dhis.android.core.analytics +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository import org.hisp.dhis.android.core.analytics.linelist.EventLineListRepository interface AnalyticsModule { fun eventLineList(): EventLineListRepository + + fun analytics(): AnalyticsRepository + + fun visualizations(): VisualizationsRepository } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt index 04603c76d3..2075fae4a8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt @@ -28,13 +28,22 @@ package org.hisp.dhis.android.core.analytics import dagger.Reusable -import javax.inject.Inject +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository import org.hisp.dhis.android.core.analytics.linelist.EventLineListRepository +import javax.inject.Inject @Reusable internal class AnalyticsModuleImpl @Inject constructor( - private val eventLineListRepository: EventLineListRepository + private val eventLineListRepository: EventLineListRepository, + private val analyticsRepository: AnalyticsRepository, + private val visualizationsRepository: VisualizationsRepository ) : AnalyticsModule { override fun eventLineList(): EventLineListRepository = eventLineListRepository + + override fun analytics(): AnalyticsRepository = analyticsRepository + + override fun visualizations(): VisualizationsRepository = visualizationsRepository + } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsPackageDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsPackageDIModule.kt index d4026a608a..cba24254d5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsPackageDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsPackageDIModule.kt @@ -30,10 +30,12 @@ package org.hisp.dhis.android.core.analytics import dagger.Module import dagger.Provides import dagger.Reusable +import org.hisp.dhis.android.core.analytics.aggregated.AggregatedEntityDIModule import org.hisp.dhis.android.core.analytics.linelist.LineListEntityDIModule @Module( includes = [ + AggregatedEntityDIModule::class, LineListEntityDIModule::class ] ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt new file mode 100644 index 0000000000..7406b97c1c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.mock.MockVisualizationsRepository + +@Module +internal class AggregatedEntityDIModule { + + @Provides + @Reusable + fun analytics(impl: MockAnalyticsRepository): AnalyticsRepository { + return impl + } + + @Provides + @Reusable + fun visualizations(impl: MockVisualizationsRepository): VisualizationsRepository { + return impl + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt new file mode 100644 index 0000000000..44f5d82271 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit +import org.hisp.dhis.android.core.common.RelativePeriod +import org.hisp.dhis.android.core.period.PeriodType +import java.util.* + +sealed class MetadataItem(val id: String, val displayName: String) { + class DataElement(uid: String, displayName: String) : MetadataItem(uid, displayName) + class Indicator(uid: String, displayName: String) : MetadataItem(uid, displayName) + class ProgramIndicator(uid: String, displayName: String) : MetadataItem(uid, displayName) + class Category(uid: String, displayName: String) : MetadataItem(uid, displayName) + class CategoryOption(uid: String, displayName: String, val category: String) : MetadataItem(uid, displayName) + class CategoryOptionGroupSet(uid: String, displayName: String) : MetadataItem(uid, displayName) + class CategoryOptionGroup(uid: String, displayName: String, val categoryOptionGroupSet: String) : MetadataItem(uid, displayName) + class OrganisationUnit(uid: String, displayName: String) : MetadataItem(uid, displayName) + class Period(periodId: String, val periodType: PeriodType, val startData: Date, val endDate: Date) : MetadataItem(periodId, periodId) +} + +sealed class Dimension { + object Data : Dimension() + object Period : Dimension() + object OrganisationUnit : Dimension() + class Category(val uid: String) : Dimension() + class CategoryOptionGroupSet(val uid: String) : Dimension() +} + +sealed class DimensionItem(val dimension: Dimension) { + sealed class DataItem : DimensionItem(Dimension.Data) { + data class DataElement(val uid: String) : DataItem() + data class DataElementOperand(val uid: String, val categoryOptionCombo: String) : DataItem() + data class Indicator(val uid: String) : DataItem() + data class ProgramIndicator(val uid: String) : DataItem() + } + + sealed class PeriodItem : DimensionItem(Dimension.Period) { + data class Absolute(val periodId: String) : PeriodItem() + data class Relative(val relative: RelativePeriod) : PeriodItem() + } + + sealed class OrganisationUnitItem : DimensionItem(Dimension.OrganisationUnit) { + data class Absolute(val uids: List) : OrganisationUnitItem() + data class Relative(val relative: RelativeOrganisationUnit) : OrganisationUnitItem() + data class Level(val uid: String) : OrganisationUnitItem() + data class Group(val uid: String) : OrganisationUnitItem() + } + + class CategoryItem(val uid: String, val categoryOptions: List) : DimensionItem(Dimension.Category(uid)) + + class CategoryOptionGroupSetItem(val uid: String, val categoryOptionGroups: List) : DimensionItem(Dimension.CategoryOptionGroupSet(uid)) +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt new file mode 100644 index 0000000000..9cfae90648 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +import io.reactivex.Single + +interface AnalyticsRepository { + + fun withDimension(dimensionItem: DimensionItem): AnalyticsRepository + + fun withFilter(dimensionItem: DimensionItem): AnalyticsRepository + + fun evaluate(): Single + + fun blockingEvaluate(): DimensionalResponse + +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt new file mode 100644 index 0000000000..108f1db7a2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +data class DimensionalResponse( + val metadata: Map, + val dimensions: List, + val filters: List, + val values: List +) + +data class DimensionalValue( + val dimensions: List, + val value: String? +) \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt new file mode 100644 index 0000000000..23cf826fcf --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +data class GridAnalyticsResponse( + val metadata: Map, + val headers: GridHeader, + val dimensions: GridDimension, + val filters: List, + val values: List> +) + +data class GridHeader( + val columns: List>, + val rows: List> +) + +data class GridHeaderItem( + val id: String, + val width: Int +) + +data class GridDimension( + val columns: List, + val rows: List +) + +data class GridResponseValue( + val columns: List, + val rows: List, + val value: String? +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt new file mode 100644 index 0000000000..eb291fca8a --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +import io.reactivex.Single + +interface VisualizationsRepository { + + fun withVisualization(visualization: String): VisualizationsRepository + + fun evaluate(): Single + + fun blockingEvaluate(): GridAnalyticsResponse + +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt new file mode 100644 index 0000000000..1ee41b1394 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock + +object AggregatedSamples { + val dataElement1 = "fbfJHSPpUQD" //ANC 1st visit + val dataElement2 = "cYeuwXTCPkU" //ANC 2nd visit + + val cc1 = "fMZEcRHuamy" //Fixed / Outreach + val co1 = "pq2XI5kz2BY" //Fixed + val co2 = "PT59n8BQbqM" //Outreach + + val period1 = "202103" + val period2 = "202102" + + val orgunit1 = "DiszpKrYNg8" //Ngelehun + val orgunit2 = "g8upMTyEZGZ" //Njandama +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java new file mode 100644 index 0000000000..a0453011e2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock; + +import org.hisp.dhis.android.core.analytics.aggregated.Dimension; +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem; +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse; + +import java.util.ArrayList; +import java.util.List; + +public class AnalyticsTester { + + void test() { + DimensionalResponse response = DimensionalSamples.INSTANCE.getSample1(); + + DimensionItem dataElement = new DimensionItem.DataItem.DataElement("uid"); + DimensionItem cat = new DimensionItem.CategoryItem("uid", new ArrayList<>()); + + List items = new ArrayList<>(); + + items.add(dataElement); + items.add(cat); + + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt new file mode 100644 index 0000000000..50f2c69b99 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock + +import org.hisp.dhis.android.core.analytics.aggregated.Dimension +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem + +object AnalyticsTestterKt { + + + fun test() { + val response = DimensionalSamples.sample1 + + val item = DimensionItem.DataItem.DataElement("uid") + val cat = DimensionItem.CategoryItem("uid", listOf("option")) + + val items = listOf(item, cat) + + items.forEach { it -> + when(it.dimension) { + is Dimension.Data -> "" + } + } + + item.dimension + } + + +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt new file mode 100644 index 0000000000..298d2ed1dc --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock + +import org.hisp.dhis.android.core.analytics.aggregated.Dimension +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue +import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period2 +import org.hisp.dhis.android.core.period.PeriodType +import java.util.* + + +object DimensionalSamples { + val sample1 = DimensionalResponse( + metadata = mapOf( + dataElement1 to MetadataItem.DataElement(dataElement1, "ANC 1st visit"), + dataElement2 to MetadataItem.DataElement(dataElement2, "ANC 2nd visit"), + co1 to MetadataItem.CategoryOption(co1, "Fixed", cc1), + co2 to MetadataItem.CategoryOption(co2, "Outreach", cc1), + cc1 to MetadataItem.Category(cc1, "Fixed / Outreach"), + period1 to MetadataItem.Period(period1, PeriodType.Daily, Date(), Date()), + period2 to MetadataItem.Period(period2, PeriodType.Daily, Date(), Date()), + orgunit1 to MetadataItem.OrganisationUnit(orgunit1, "Ngelehun CHC"), + orgunit2 to MetadataItem.OrganisationUnit(orgunit2, "Njandama MCHP") + ), + dimensions = listOf(Dimension.Data, Dimension.Category(co1), Dimension.Period), + filters = listOf(orgunit1, orgunit2), + values = listOf( + DimensionalValue( + listOf(dataElement1, co1, period1), + "34.5" + ), + DimensionalValue( + listOf(dataElement1, co2, period1), + "10.0" + ), + DimensionalValue( + listOf(dataElement2, co1, period1), + "13" + ), + DimensionalValue( + listOf(dataElement2, co2, period1), + "15" + ), + DimensionalValue( + listOf(dataElement1, co1, period2), + "34.5" + ), + DimensionalValue( + listOf(dataElement1, co2, period2), + "10.0" + ), + DimensionalValue( + listOf(dataElement2, co1, period2), + "13" + ), + DimensionalValue( + listOf(dataElement2, co2, period2), + "15" + ) + ) + ) +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt new file mode 100644 index 0000000000..b19658d3f5 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock + +import org.hisp.dhis.android.core.analytics.aggregated.* +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period1 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period2 +import org.hisp.dhis.android.core.period.PeriodType +import java.util.* + +object GridSamples { + val sample1 = GridAnalyticsResponse( + metadata = mapOf( + dataElement1 to MetadataItem.DataElement(dataElement1, "ANC 1st visit"), + dataElement2 to MetadataItem.DataElement(dataElement2, "ANC 2nd visit"), + co1 to MetadataItem.CategoryOption(co1, "Fixed", cc1), + co2 to MetadataItem.CategoryOption(co2, "Outreach", cc1), + cc1 to MetadataItem.Category(cc1, "Fixed / Outreach"), + period1 to MetadataItem.Period(period1, PeriodType.Daily, Date(), Date()), + period2 to MetadataItem.Period(period2, PeriodType.Daily, Date(), Date()), + orgunit1 to MetadataItem.OrganisationUnit(orgunit1, "Ngelehun CHC"), + orgunit2 to MetadataItem.OrganisationUnit(orgunit2, "Njandama MCHP") + ), + headers = GridHeader( + columns = listOf( + listOf( + GridHeaderItem(dataElement1, 2), + GridHeaderItem(dataElement2, 2) + ), + listOf( + GridHeaderItem(co1, 1), + GridHeaderItem(co2, 1), + GridHeaderItem(co1, 1), + GridHeaderItem(co2, 1) + ) + ), + rows = listOf( + listOf( + GridHeaderItem(period1, 1), + GridHeaderItem(period2, 1) + ) + ) + ), + dimensions = GridDimension( + columns = listOf(Dimension.Data, Dimension.Category(co1)), + rows = listOf(Dimension.Period) + ), + filters = listOf(orgunit1, orgunit2), + values = listOf( + listOf( + GridResponseValue( + listOf(dataElement1, co1), + listOf(period1), + "34.5" + ), + GridResponseValue( + listOf(dataElement1, co2), + listOf(period1), + "10.0" + ), + GridResponseValue( + listOf(dataElement2, co1), + listOf(period1), + "13" + ), + GridResponseValue( + listOf(dataElement2, co2), + listOf(period1), + "15" + ) + ), + listOf( + GridResponseValue( + listOf(dataElement1, co1), + listOf(period2), + "34.5" + ), + GridResponseValue( + listOf(dataElement1, co2), + listOf(period2), + "10.0" + ), + GridResponseValue( + listOf(dataElement2, co1), + listOf(period2), + "13" + ), + GridResponseValue( + listOf(dataElement2, co2), + listOf(period2), + "15" + ) + ) + ) + ) +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt new file mode 100644 index 0000000000..5c8087e55c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock + +import dagger.Reusable +import io.reactivex.Single +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse +import javax.inject.Inject + +@Reusable +class MockAnalyticsRepository @Inject constructor() : AnalyticsRepository { + + override fun withDimension(dimensionItem: DimensionItem): AnalyticsRepository = this + + override fun withFilter(dimensionItem: DimensionItem): AnalyticsRepository = this + + override fun evaluate(): Single { + return Single.fromCallable { blockingEvaluate() } + } + + override fun blockingEvaluate(): DimensionalResponse = DimensionalSamples.sample1 + +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt new file mode 100644 index 0000000000..e07b83fc41 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock + +import dagger.Reusable +import io.reactivex.Single +import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse +import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository +import javax.inject.Inject + +@Reusable +class MockVisualizationsRepository @Inject constructor() : VisualizationsRepository { + + override fun withVisualization(visualization: String): VisualizationsRepository = TODO() + + override fun evaluate(): Single { + return Single.fromCallable { blockingEvaluate() } + } + + override fun blockingEvaluate(): GridAnalyticsResponse = GridSamples.sample1 + +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json new file mode 100644 index 0000000000..01c0ec5ff1 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json @@ -0,0 +1,206 @@ +{ + "lastUpdated": "2021-05-27T09:52:38.766", + "id": "ZYZiA8uPVks", + "created": "2021-05-27T09:51:29.415", + "name": "ANC by orgunit", + "displayName": "ANC by orgunit", + "displayFormName": "ANC by orgunit", + "publicAccess": "--------", + "type": "COLUMN", + + "subscribed": false, + "favorite": false, + + "legendDisplayStyle": "FILL", + "hideEmptyColumns": false, + "rowSubTotals": false, + "cumulativeValues": false, + "showDimensionLabels": false, + "sortOrder": 0, + "fontSize": "NORMAL", + "topLimit": 0, + "noSpaceBetweenColumns": false, + + "showHierarchy": false, + "percentStackedValues": false, + + + "hideTitle": false, + "colorSet": "DEFAULT", + "skipRounding": false, + "showData": true, + "numberType": "VALUE", + "hideEmptyRows": false, + "parentGraphMap": { + "jUb8gELQApl": "ImspTQPwCqd", + "O6uvpzGd5pu": "ImspTQPwCqd", + "lc3eMKXaEfw": "ImspTQPwCqd", + "fdc6uOvgoji": "ImspTQPwCqd" + }, + "displayDensity": "NORMAL", + "regressionType": "NONE", + "completedOnly": false, + "colTotals": false, + "hideEmptyRowItems": "NONE", + "aggregationType": "DEFAULT", + "hideSubtitle": false, + "hideLegend": false, + "externalAccess": false, + "legendDisplayStrategy": "FIXED", + "colSubTotals": false, + "rowTotals": false, + "digitGroupSeparator": "SPACE", + "regression": false, + "fontStyle": {}, + "access": { + "read": true, + "update": true, + "externalize": true, + "delete": true, + "write": true, + "manage": true + }, + "lastUpdatedBy": { + "displayName": "John Traore", + "id": "xE7jOejl9FI", + "username": "admin" + }, + "user": { + "displayName": "John Traore", + "id": "xE7jOejl9FI", + "username": "admin" + }, + "translations": [], + "yearlySeries": [], + + + "filterDimensions": [ + "dx" + ], + "columnDimensions": [ + "ou" + ], + "rowDimensions": [ + "pe" + ], + + + "relativePeriods": { + "thisYear": false, + "quartersLastYear": false, + "last30Days": false, + "last52Weeks": false, + "thisWeek": false, + "last90Days": false, + "last60Days": false, + "lastMonth": false, + "last14Days": false, + "biMonthsThisYear": false, + "monthsThisYear": false, + "last2SixMonths": false, + "yesterday": false, + "thisQuarter": false, + "last12Months": true, + "last5FinancialYears": false, + "thisSixMonth": false, + "lastQuarter": false, + "thisFinancialYear": false, + "last4Weeks": false, + "last3Months": false, + "thisDay": false, + "thisMonth": false, + "last5Years": false, + "last6BiMonths": false, + "last4BiWeeks": false, + "lastFinancialYear": false, + "lastBiWeek": false, + "weeksThisYear": false, + "last6Months": false, + "last3Days": false, + "quartersThisYear": false, + "monthsLastYear": false, + "lastWeek": false, + "last7Days": false, + "last180Days": false, + "thisBimonth": false, + "lastBimonth": false, + "lastSixMonth": false, + "thisBiWeek": false, + "lastYear": false, + "last12Weeks": false, + "last4Quarters": false + }, + "dataElementGroupSetDimensions": [], + "attributeDimensions": [], + "dataElementDimensions": [], + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "fbfJHSPpUQD" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "cYeuwXTCPkU" + } + } + ], + "categoryOptionGroupSetDimensions": [], + "organisationUnitGroupSetDimensions": [], + "categoryDimensions": [], + "programIndicatorDimensions": [], + "organisationUnitLevels": [], + "userOrganisationUnit": false, + "userOrganisationUnitChildren": false, + "userOrganisationUnitGrandChildren": false, + "reportingParams": { + "parentOrganisationUnit": false, + "reportingPeriod": false, + "organisationUnit": false, + "grandParentOrganisationUnit": false + }, + "organisationUnits": [ + { + "id": "O6uvpzGd5pu" + }, + { + "id": "fdc6uOvgoji" + }, + { + "id": "lc3eMKXaEfw" + }, + { + "id": "jUb8gELQApl" + } + ], + "periods": [], + "series": [], + + + + "interpretations": [], + "userGroupAccesses": [], + "subscribers": [], + "optionalAxes": [], + "itemOrganisationUnitGroups": [], + "attributeValues": [], + "userAccesses": [], + "favorites": [], + "columns": [ + { + "id": "ou" + } + ], + "filters": [ + { + "id": "dx" + } + ], + "rows": [ + { + "id": "pe" + } + ] +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt b/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt new file mode 100644 index 0000000000..b8269758a2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.common + +enum class RelativeOrganisationUnit { + USER_ORGUNIT, + USER_ORGUNIT_CHILDREN, + USER_ORGUNIT_GRANDCHILDREN +} From d81c2b18577634da02b69d907f7081a4541fe39b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 16 Jun 2021 16:47:10 +0200 Subject: [PATCH 084/308] [ANDROSDK-1385] Add visualization sample --- .../visualization}/visualization.json | 348 ++++++++++++------ 1 file changed, 230 insertions(+), 118 deletions(-) rename core/src/{main/java/org/hisp/dhis/android/core/analytics/aggregated/mock => sharedTest/resources/visualization}/visualization.json (52%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json b/core/src/sharedTest/resources/visualization/visualization.json similarity index 52% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json rename to core/src/sharedTest/resources/visualization/visualization.json index 01c0ec5ff1..3b59a760fb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/visualization.json +++ b/core/src/sharedTest/resources/visualization/visualization.json @@ -1,90 +1,30 @@ { - "lastUpdated": "2021-05-27T09:52:38.766", - "id": "ZYZiA8uPVks", - "created": "2021-05-27T09:51:29.415", - "name": "ANC by orgunit", - "displayName": "ANC by orgunit", - "displayFormName": "ANC by orgunit", - "publicAccess": "--------", - "type": "COLUMN", - - "subscribed": false, - "favorite": false, - - "legendDisplayStyle": "FILL", + "id": "PYBH8ZaAQnC", + "name": "Android SDK Visualization sample", + "displayName": "Android SDK Visualization sample", + "description": "Sample visualization for the Android SDK", + "displayDescription": "Sample visualization for the Android SDK", + "displayFormName": "Android SDK Visualization sample", + "lastUpdated": "2021-06-16T14:26:50.195", + "created": "2021-06-16T14:26:50.195", + "type": "PIVOT_TABLE", + "hideTitle": false, + "hideSubtitle": false, "hideEmptyColumns": false, + "hideEmptyRows": false, + "hideEmptyRowItems": "NONE", + "hideLegend": false, + "showHierarchy": false, + "rowTotals": false, "rowSubTotals": false, - "cumulativeValues": false, + "colTotals": false, + "colSubTotals": false, "showDimensionLabels": false, - "sortOrder": 0, - "fontSize": "NORMAL", - "topLimit": 0, - "noSpaceBetweenColumns": false, - - "showHierarchy": false, "percentStackedValues": false, - - - "hideTitle": false, - "colorSet": "DEFAULT", + "noSpaceBetweenColumns": false, "skipRounding": false, - "showData": true, - "numberType": "VALUE", - "hideEmptyRows": false, - "parentGraphMap": { - "jUb8gELQApl": "ImspTQPwCqd", - "O6uvpzGd5pu": "ImspTQPwCqd", - "lc3eMKXaEfw": "ImspTQPwCqd", - "fdc6uOvgoji": "ImspTQPwCqd" - }, "displayDensity": "NORMAL", - "regressionType": "NONE", - "completedOnly": false, - "colTotals": false, - "hideEmptyRowItems": "NONE", - "aggregationType": "DEFAULT", - "hideSubtitle": false, - "hideLegend": false, - "externalAccess": false, - "legendDisplayStrategy": "FIXED", - "colSubTotals": false, - "rowTotals": false, - "digitGroupSeparator": "SPACE", - "regression": false, - "fontStyle": {}, - "access": { - "read": true, - "update": true, - "externalize": true, - "delete": true, - "write": true, - "manage": true - }, - "lastUpdatedBy": { - "displayName": "John Traore", - "id": "xE7jOejl9FI", - "username": "admin" - }, - "user": { - "displayName": "John Traore", - "id": "xE7jOejl9FI", - "username": "admin" - }, - "translations": [], - "yearlySeries": [], - - - "filterDimensions": [ - "dx" - ], - "columnDimensions": [ - "ou" - ], - "rowDimensions": [ - "pe" - ], - - + "digitGroupSeparator": "COMMA", "relativePeriods": { "thisYear": false, "quartersLastYear": false, @@ -130,14 +70,56 @@ "last12Weeks": false, "last4Quarters": false }, - "dataElementGroupSetDimensions": [], - "attributeDimensions": [], - "dataElementDimensions": [], + "categoryDimensions": [ + { + "category": { + "id": "fMZEcRHuamy" + }, + "categoryOptions": [ + { + "id": "qkPbeWaFsnU" + }, + { + "id": "wbrDrL2aYEc" + } + ] + }, + { + "category": { + "id": "fkAkrdC7eJF" + }, + "categoryOptions": [ + { + "id": "FbLZS3ueWbQ" + }, + { + "id": "rEq3Hkd3XXH" + }, + { + "id": "ZZxYuoTCcDd" + }, + { + "id": "dUm5jaCTPBb" + } + ] + } + ], + "filterDimensions": [ + "ou" + ], + "rowDimensions": [ + "pe" + ], + "columnDimensions": [ + "dx", + "fMZEcRHuamy", + "fkAkrdC7eJF" + ], "dataDimensionItems": [ { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "fbfJHSPpUQD" + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "Uvn6LCg7dVU" } }, { @@ -145,62 +127,192 @@ "dataElement": { "id": "cYeuwXTCPkU" } + }, + { + "dataDimensionItemType": "DATA_ELEMENT_OPERAND", + "dataElementOperand": { + "lastUpdated": "2021-06-16T14:27:07.790", + "id": "Jtf34kNZhzP.pq2XI5kz2BY", + "created": "2021-06-16T14:27:07.790", + "name": "ANC 3rd visit Fixed", + "shortName": "ANC 3rd visit Fixed", + "aggregationType": "SUM", + "displayName": "ANC 3rd visit Fixed", + "displayShortName": "ANC 3rd visit Fixed", + "externalAccess": false, + "periodOffset": 0, + "dimensionItem": "Jtf34kNZhzP.pq2XI5kz2BY", + "sharing": { + "external": false, + "users": {}, + "userGroups": {} + }, + "displayFormName": "ANC 3rd visit Fixed", + "favorite": false, + "dimensionItemType": "DATA_ELEMENT_OPERAND", + "access": { + "read": true, + "update": true, + "externalize": false, + "delete": true, + "write": true, + "manage": true + }, + "categoryOptionCombo": { + "id": "pq2XI5kz2BY" + }, + "dataElement": { + "id": "Jtf34kNZhzP" + }, + "favorites": [], + "translations": [], + "userGroupAccesses": [], + "attributeValues": [], + "userAccesses": [], + "legendSets": [] + } + }, + { + "dataDimensionItemType": "PROGRAM_INDICATOR", + "programIndicator": { + "id": "p2Zxg0wcPQ3" + } } ], - "categoryOptionGroupSetDimensions": [], - "organisationUnitGroupSetDimensions": [], - "categoryDimensions": [], - "programIndicatorDimensions": [], - "organisationUnitLevels": [], + "organisationUnitLevels": [ + 3 + ], "userOrganisationUnit": false, "userOrganisationUnitChildren": false, "userOrganisationUnitGrandChildren": false, - "reportingParams": { - "parentOrganisationUnit": false, - "reportingPeriod": false, - "organisationUnit": false, - "grandParentOrganisationUnit": false - }, "organisationUnits": [ { - "id": "O6uvpzGd5pu" + "id": "YuQRtpLP10I" }, { - "id": "fdc6uOvgoji" + "id": "vWbkYPRmKyS" + } + ], + "columns": [ + { + "id": "dx" }, { - "id": "lc3eMKXaEfw" + "id": "fMZEcRHuamy" }, { - "id": "jUb8gELQApl" + "id": "fkAkrdC7eJF" } ], - "periods": [], - "series": [], - - - - "interpretations": [], - "userGroupAccesses": [], - "subscribers": [], - "optionalAxes": [], - "itemOrganisationUnitGroups": [], - "attributeValues": [], - "userAccesses": [], - "favorites": [], - "columns": [ + "periods": [ { - "id": "ou" + "id": "202102" + }, + { + "id": "202103" + }, + { + "id": "2021S2" } ], "filters": [ { - "id": "dx" + "id": "ou" } ], "rows": [ { "id": "pe" } - ] + ], + + + + "yearlySeries": [], + "reportingParams": { + "parentOrganisationUnit": false, + "reportingPeriod": false, + "organisationUnit": false, + "grandParentOrganisationUnit": false + }, + "completedOnly": false, + "cumulativeValues": false, + "regression": false, + "regressionType": "NONE", + "numberType": "VALUE", + "aggregationType": "DEFAULT", + + + + + "legend": { + "hidden": false + }, + "legendDisplayStrategy": "FIXED", + "legendDisplayStyle": "FILL", + "fontSize": "NORMAL", + "favorite": false, + "sortOrder": 0, + "topLimit": 0, + "colorSet": "DEFAULT", + "showData": true, + "externalAccess": false, + "fontStyle": {}, + "parentGraphMap": { + "YuQRtpLP10I": "ImspTQPwCqd/O6uvpzGd5pu", + "vWbkYPRmKyS": "ImspTQPwCqd/O6uvpzGd5pu" + }, + "sharing": { + "owner": "xE7jOejl9FI", + "external": false, + "users": {}, + "userGroups": {}, + "public": "--------" + }, + "publicAccess": "--------", + "access": { + "read": true, + "update": true, + "externalize": true, + "delete": true, + "write": true, + "manage": true + }, + "lastUpdatedBy": { + "displayName": "John Traore", + "name": "John Traore", + "id": "xE7jOejl9FI", + "username": "admin" + }, + "createdBy": { + "displayName": "John Traore", + "name": "John Traore", + "id": "xE7jOejl9FI", + "username": "admin" + }, + "user": { + "displayName": "John Traore", + "name": "John Traore", + "id": "xE7jOejl9FI", + "username": "admin" + }, + "dataElementGroupSetDimensions": [], + "axes": [], + "attributeDimensions": [], + "translations": [], + "interpretations": [], + "userGroupAccesses": [], + "subscribers": [], + "optionalAxes": [], + "series": [], + "attributeValues": [], + "itemOrganisationUnitGroups": [], + "dataElementDimensions": [], + "programIndicatorDimensions": [], + "userAccesses": [], + "favorites": [], + "subscribed": false, + "categoryOptionGroupSetDimensions": [], + "organisationUnitGroupSetDimensions": [], + "href": "https://play.dhis2.org/2.36.0/api/visualizations/PYBH8ZaAQnC" } \ No newline at end of file From b6ba202d5f7d584f27696bb3cc3ee1dc99238330 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 16 Jun 2021 16:58:43 +0200 Subject: [PATCH 085/308] [ANDROSDK-1385] Klint --- .../core/analytics/AnalyticsModuleImpl.kt | 3 +- .../analytics/aggregated/AnalyticsModel.kt | 22 ++++++-- .../aggregated/AnalyticsRepository.kt | 3 +- .../aggregated/DimensionalResponse.kt | 2 +- .../aggregated/VisualizationsRepository.kt | 3 +- .../aggregated/mock/AggregatedSamples.kt | 20 +++---- .../aggregated/mock/AnalyticsTester.java | 52 ------------------ .../aggregated/mock/AnalyticsTestterKt.kt | 55 ------------------- .../mock/DimensionalResponseSamples.kt | 7 +-- .../mock/GridAnalyticsResponseSamples.kt | 6 +- .../mock/MockAnalyticsRepository.kt | 7 +-- .../mock/MockVisualizationsRepository.kt | 7 +-- .../core/common/RelativeOrganisationUnit.kt | 2 +- 13 files changed, 44 insertions(+), 145 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt index 2075fae4a8..c364ef1887 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.analytics import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository import org.hisp.dhis.android.core.analytics.linelist.EventLineListRepository -import javax.inject.Inject @Reusable internal class AnalyticsModuleImpl @Inject constructor( @@ -45,5 +45,4 @@ internal class AnalyticsModuleImpl @Inject constructor( override fun analytics(): AnalyticsRepository = analyticsRepository override fun visualizations(): VisualizationsRepository = visualizationsRepository - } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index 44f5d82271..fe8701b722 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.analytics.aggregated +import java.util.* import org.hisp.dhis.android.core.common.RelativeOrganisationUnit import org.hisp.dhis.android.core.common.RelativePeriod import org.hisp.dhis.android.core.period.PeriodType -import java.util.* sealed class MetadataItem(val id: String, val displayName: String) { class DataElement(uid: String, displayName: String) : MetadataItem(uid, displayName) @@ -40,9 +40,18 @@ sealed class MetadataItem(val id: String, val displayName: String) { class Category(uid: String, displayName: String) : MetadataItem(uid, displayName) class CategoryOption(uid: String, displayName: String, val category: String) : MetadataItem(uid, displayName) class CategoryOptionGroupSet(uid: String, displayName: String) : MetadataItem(uid, displayName) - class CategoryOptionGroup(uid: String, displayName: String, val categoryOptionGroupSet: String) : MetadataItem(uid, displayName) + class CategoryOptionGroup( + uid: String, + displayName: String, + val categoryOptionGroupSet: String + ) : MetadataItem(uid, displayName) class OrganisationUnit(uid: String, displayName: String) : MetadataItem(uid, displayName) - class Period(periodId: String, val periodType: PeriodType, val startData: Date, val endDate: Date) : MetadataItem(periodId, periodId) + class Period( + periodId: String, + val periodType: PeriodType, + val startData: Date, + val endDate: Date + ) : MetadataItem(periodId, periodId) } sealed class Dimension { @@ -75,5 +84,8 @@ sealed class DimensionItem(val dimension: Dimension) { class CategoryItem(val uid: String, val categoryOptions: List) : DimensionItem(Dimension.Category(uid)) - class CategoryOptionGroupSetItem(val uid: String, val categoryOptionGroups: List) : DimensionItem(Dimension.CategoryOptionGroupSet(uid)) -} \ No newline at end of file + class CategoryOptionGroupSetItem( + val uid: String, + val categoryOptionGroups: List + ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid)) +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt index 9cfae90648..03c69807d2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepository.kt @@ -39,5 +39,4 @@ interface AnalyticsRepository { fun evaluate(): Single fun blockingEvaluate(): DimensionalResponse - -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt index 108f1db7a2..a79eaa9565 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt @@ -38,4 +38,4 @@ data class DimensionalResponse( data class DimensionalValue( val dimensions: List, val value: String? -) \ No newline at end of file +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt index eb291fca8a..2e0ed90264 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt @@ -37,5 +37,4 @@ interface VisualizationsRepository { fun evaluate(): Single fun blockingEvaluate(): GridAnalyticsResponse - -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt index 1ee41b1394..5b7c729c8d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt @@ -29,16 +29,16 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock object AggregatedSamples { - val dataElement1 = "fbfJHSPpUQD" //ANC 1st visit - val dataElement2 = "cYeuwXTCPkU" //ANC 2nd visit + const val dataElement1 = "fbfJHSPpUQD" // ANC 1st visit + const val dataElement2 = "cYeuwXTCPkU" // ANC 2nd visit - val cc1 = "fMZEcRHuamy" //Fixed / Outreach - val co1 = "pq2XI5kz2BY" //Fixed - val co2 = "PT59n8BQbqM" //Outreach + const val cc1 = "fMZEcRHuamy" // Fixed / Outreach + const val co1 = "pq2XI5kz2BY" // Fixed + const val co2 = "PT59n8BQbqM" // Outreach - val period1 = "202103" - val period2 = "202102" + const val period1 = "202103" + const val period2 = "202102" - val orgunit1 = "DiszpKrYNg8" //Ngelehun - val orgunit2 = "g8upMTyEZGZ" //Njandama -} \ No newline at end of file + const val orgunit1 = "DiszpKrYNg8" // Ngelehun + const val orgunit2 = "g8upMTyEZGZ" // Njandama +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java deleted file mode 100644 index a0453011e2..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTester.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock; - -import org.hisp.dhis.android.core.analytics.aggregated.Dimension; -import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem; -import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse; - -import java.util.ArrayList; -import java.util.List; - -public class AnalyticsTester { - - void test() { - DimensionalResponse response = DimensionalSamples.INSTANCE.getSample1(); - - DimensionItem dataElement = new DimensionItem.DataItem.DataElement("uid"); - DimensionItem cat = new DimensionItem.CategoryItem("uid", new ArrayList<>()); - - List items = new ArrayList<>(); - - items.add(dataElement); - items.add(cat); - - } -} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt deleted file mode 100644 index 50f2c69b99..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AnalyticsTestterKt.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.analytics.aggregated.mock - -import org.hisp.dhis.android.core.analytics.aggregated.Dimension -import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem - -object AnalyticsTestterKt { - - - fun test() { - val response = DimensionalSamples.sample1 - - val item = DimensionItem.DataItem.DataElement("uid") - val cat = DimensionItem.CategoryItem("uid", listOf("option")) - - val items = listOf(item, cat) - - items.forEach { it -> - when(it.dimension) { - is Dimension.Data -> "" - } - } - - item.dimension - } - - -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt index 298d2ed1dc..ed1c6ff391 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock +import java.util.* import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue @@ -42,10 +43,8 @@ import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.or import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period2 import org.hisp.dhis.android.core.period.PeriodType -import java.util.* - -object DimensionalSamples { +object DimensionalResponseSamples { val sample1 = DimensionalResponse( metadata = mapOf( dataElement1 to MetadataItem.DataElement(dataElement1, "ANC 1st visit"), @@ -95,4 +94,4 @@ object DimensionalSamples { ) ) ) -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt index b19658d3f5..05ccce346b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock +import java.util.* import org.hisp.dhis.android.core.analytics.aggregated.* import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co1 @@ -39,9 +40,8 @@ import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.or import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period2 import org.hisp.dhis.android.core.period.PeriodType -import java.util.* -object GridSamples { +object GridAnalyticsResponseSamples { val sample1 = GridAnalyticsResponse( metadata = mapOf( dataElement1 to MetadataItem.DataElement(dataElement1, "ANC 1st visit"), @@ -126,4 +126,4 @@ object GridSamples { ) ) ) -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt index 5c8087e55c..ad81a9c467 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsRepository.kt @@ -30,10 +30,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock import dagger.Reusable import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse -import javax.inject.Inject @Reusable class MockAnalyticsRepository @Inject constructor() : AnalyticsRepository { @@ -46,6 +46,5 @@ class MockAnalyticsRepository @Inject constructor() : AnalyticsRepository { return Single.fromCallable { blockingEvaluate() } } - override fun blockingEvaluate(): DimensionalResponse = DimensionalSamples.sample1 - -} \ No newline at end of file + override fun blockingEvaluate(): DimensionalResponse = DimensionalResponseSamples.sample1 +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt index e07b83fc41..348b0aa9f7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt @@ -30,9 +30,9 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock import dagger.Reusable import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository -import javax.inject.Inject @Reusable class MockVisualizationsRepository @Inject constructor() : VisualizationsRepository { @@ -43,6 +43,5 @@ class MockVisualizationsRepository @Inject constructor() : VisualizationsReposit return Single.fromCallable { blockingEvaluate() } } - override fun blockingEvaluate(): GridAnalyticsResponse = GridSamples.sample1 - -} \ No newline at end of file + override fun blockingEvaluate(): GridAnalyticsResponse = GridAnalyticsResponseSamples.sample1 +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt b/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt index b8269758a2..3b9924be03 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/RelativeOrganisationUnit.kt @@ -27,7 +27,7 @@ */ package org.hisp.dhis.android.core.common -enum class RelativeOrganisationUnit { +enum class RelativeOrganisationUnit { USER_ORGUNIT, USER_ORGUNIT_CHILDREN, USER_ORGUNIT_GRANDCHILDREN From d89870566852aedd1c72b75366e09a1e973b0a5a Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 17 Jun 2021 14:40:25 +0200 Subject: [PATCH 086/308] [ANDROSDK-1395] Refactor state to syncState; keep state in TEIs and enrollments --- .../enrollment/CreateEnrollmentUtils.java | 2 +- .../android/core/event/CreateEventUtils.java | 2 +- .../CreateTrackedEntityInstanceUtils.java | 2 +- core/src/main/assets/migrations/102.sql | 38 +++++++++++++++++++ .../assets/snapshots/{101.sql => 102.sql} | 16 ++++---- .../internal/BaseDatabaseOpenHelper.java | 2 +- .../IdentifiableDataObjectStoreImpl.kt | 6 +-- ...dentifiableDeletableDataObjectStoreImpl.kt | 6 +-- .../internal/IdentifiableDataHandlerImpl.kt | 4 +- .../android/core/common/BaseDataObject.java | 12 ++++-- .../dhis/android/core/common/DataColumns.java | 1 + .../dhis/android/core/common/DataObject.java | 1 + .../internal/DataStatePropagatorImpl.java | 2 +- .../dataset/DataSetCompleteRegistration.java | 2 +- ...pleteRegistrationCollectionRepository.java | 2 +- ...tCompleteRegistrationObjectRepository.java | 6 +-- .../DataSetCompleteRegistrationTableInfo.java | 2 +- .../DataSetCompleteRegistrationStoreImpl.java | 8 ++-- .../DataSetInstanceSQLStatementBuilder.java | 4 +- ...SetInstanceSummarySQLStatementBuilder.java | 2 +- .../android/core/datavalue/DataValue.java | 2 +- .../DataValueCollectionRepository.java | 2 +- .../datavalue/DataValueObjectRepository.java | 6 +-- .../core/datavalue/DataValueTableInfo.java | 2 +- .../datavalue/internal/DataValueHandler.kt | 2 +- .../datavalue/internal/DataValueStore.java | 8 ++-- .../android/core/enrollment/Enrollment.java | 11 ++++++ .../EnrollmentObjectRepository.java | 1 + .../core/enrollment/EnrollmentTableInfo.java | 1 + ...NewTrackerImporterEnrollmentTransformer.kt | 2 +- .../internal/EnrollmentEntityDIModule.java | 2 +- .../internal/EnrollmentHandler.java | 6 +-- .../internal/EnrollmentImportHandler.java | 4 +- .../EnrollmentProjectionTransformer.java | 1 + .../internal/EnrollmentStoreImpl.java | 5 ++- .../core/event/EventCollectionRepository.java | 2 +- .../core/event/EventObjectRepository.java | 2 +- .../android/core/event/EventTableInfo.java | 2 +- .../NewTrackerImporterEventTransformer.kt | 2 +- .../core/event/internal/EventHandler.java | 4 +- .../core/event/internal/EventPostNoteStore.kt | 2 +- .../internal/EventProjectionTransformer.java | 2 +- .../core/event/internal/EventStoreImpl.java | 8 ++-- .../FileResourceCollectionRepository.java | 2 +- .../fileresource/FileResourceTableInfo.java | 2 +- .../internal/FileResourceCallFactory.java | 4 +- .../internal/FileResourcePostCall.java | 2 +- .../FileResourceProjectionTransformer.java | 2 +- .../internal/FileResourceStoreImpl.java | 2 +- .../note/NewTrackerImporterNoteTransformer.kt | 2 +- .../dhis/android/core/note/NoteTableInfo.java | 2 +- .../internal/NoteProjectionTransformer.java | 2 +- .../android/core/note/internal/NoteStore.java | 2 +- .../note/internal/NoteUniquenessManager.java | 4 +- .../RelationshipCollectionRepository.java | 2 +- .../relationship/RelationshipTableInfo.java | 2 +- .../RelationshipDHISVersionManager.java | 4 +- .../internal/RelationshipStoreImpl.java | 2 +- ...rackerImporterTranckedEntityTransformer.kt | 2 +- .../trackedentity/TrackedEntityInstance.java | 12 ++++++ ...TrackedEntityInstanceObjectRepository.java | 1 + .../TrackedEntityInstanceTableInfo.java | 1 + ...porterTrackedEntityPostPayloadGenerator.kt | 2 +- .../TrackedEntityInstanceEntityDIModule.java | 2 +- .../TrackedEntityInstanceHandler.java | 5 ++- ...ackedEntityInstancePostPayloadGenerator.kt | 2 +- ...edEntityInstanceProjectionTransformer.java | 1 + .../TrackedEntityInstanceStoreImpl.java | 5 ++- .../TrackedEntityInstanceLocalQueryHelper.kt | 4 +- .../internal/JobReportEventHandler.kt | 4 +- 70 files changed, 177 insertions(+), 99 deletions(-) create mode 100644 core/src/main/assets/migrations/102.sql rename core/src/main/assets/snapshots/{101.sql => 102.sql} (92%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/CreateEnrollmentUtils.java b/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/CreateEnrollmentUtils.java index b74664a236..d33baeee84 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/CreateEnrollmentUtils.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/CreateEnrollmentUtils.java @@ -61,7 +61,7 @@ public static ContentValues create(@NonNull String uid, @NonNull String programU enrollment.put(Columns.FOLLOW_UP, FOLLOW_UP); enrollment.put(Columns.GEOMETRY_TYPE, GEOMETRY_TYPE.getFeatureType()); enrollment.put(Columns.GEOMETRY_COORDINATES, GEOMETRY_COORDINATES); - enrollment.put(Columns.STATE, STATE.name()); + enrollment.put(Columns.SYNC_STATE, STATE.name()); enrollment.put(Columns.CREATED, DATE); enrollment.put(Columns.LAST_UPDATED, DATE); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/CreateEventUtils.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/CreateEventUtils.java index d64fc9693e..721fe14299 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/CreateEventUtils.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/CreateEventUtils.java @@ -71,7 +71,7 @@ public static ContentValues create(@NonNull String uid, event.put(Columns.EVENT_DATE, DATE); event.put(Columns.COMPLETE_DATE, DATE); event.put(Columns.DUE_DATE, DATE); - event.put(Columns.STATE, State.TO_POST.name()); + event.put(Columns.SYNC_STATE, State.TO_POST.name()); return event; } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/CreateTrackedEntityInstanceUtils.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/CreateTrackedEntityInstanceUtils.java index 0e8e499a51..5b81f8223a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/CreateTrackedEntityInstanceUtils.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/CreateTrackedEntityInstanceUtils.java @@ -50,7 +50,7 @@ public static ContentValues create(@NonNull String uid, trackedEntityInstance.put(Columns.LAST_UPDATED, DATE); trackedEntityInstance.put(Columns.ORGANISATION_UNIT, organisationUnit); trackedEntityInstance.put(Columns.TRACKED_ENTITY_TYPE, trackedEntityType); - trackedEntityInstance.put(Columns.STATE, STATE.name()); + trackedEntityInstance.put(Columns.SYNC_STATE, STATE.name()); return trackedEntityInstance; } } \ No newline at end of file diff --git a/core/src/main/assets/migrations/102.sql b/core/src/main/assets/migrations/102.sql new file mode 100644 index 0000000000..3079b52449 --- /dev/null +++ b/core/src/main/assets/migrations/102.sql @@ -0,0 +1,38 @@ +# Rename state column to syncState + +ALTER TABLE DataValue RENAME TO DataValue_Old; +CREATE TABLE DataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, period TEXT NOT NULL, organisationUnit TEXT NOT NULL, categoryOptionCombo TEXT NOT NULL, attributeOptionCombo TEXT NOT NULL, value TEXT, storedBy TEXT, created TEXT, lastUpdated TEXT, comment TEXT, followUp INTEGER, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId), FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo)); +INSERT INTO DataValue (_id, dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo, value, storedBy, created, lastUpdated, comment, followUp, syncState, deleted) SELECT _id, dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo, value, storedBy, created, lastUpdated, comment, followUp, state, deleted FROM DataValue_Old; +DROP TABLE DataValue_Old; + + +ALTER TABLE DataSetCompleteRegistration RENAME TO DataSetCompleteRegistration_Old; +CREATE TABLE DataSetCompleteRegistration (_id INTEGER PRIMARY KEY AUTOINCREMENT, period TEXT NOT NULL, dataSet TEXT NOT NULL, organisationUnit TEXT NOT NULL, attributeOptionCombo TEXT, date TEXT, storedBy TEXT, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataSet) REFERENCES DataSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (period, dataSet, organisationUnit, attributeOptionCombo)); +INSERT INTO DataSetCompleteRegistration(_id, period, dataSet, organisationUnit, attributeOptionCombo, date, storedBy, syncState, deleted) SELECT _id, period, dataSet, organisationUnit, attributeOptionCombo, date, storedBy, state, deleted FROM DataSetCompleteRegistration_Old; +DROP TABLE DataSetCompleteRegistration_Old; + +ALTER TABLE Relationship RENAME TO Relationship_Old; +CREATE TABLE Relationship (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, name TEXT, created TEXT, lastUpdated TEXT, relationshipType TEXT NOT NULL, syncState TEXT, deleted INTEGER, FOREIGN KEY (relationshipType) REFERENCES RelationshipType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +INSERT INTO Relationship (_id, uid, name, created, lastUpdated, relationshipType, syncState, deleted) SELECT _id, uid, name, created, lastUpdated, relationshipType, state, deleted FROM Relationship_Old; +DROP TABLE Relationship_Old; + +ALTER TABLE Note RENAME TO Note_Old; +CREATE TABLE Note (_id INTEGER PRIMARY KEY AUTOINCREMENT, noteType TEXT, event TEXT, enrollment TEXT, value TEXT, storedBy TEXT, storedDate TEXT, uid TEXT, syncState TEXT, deleted INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (noteType, event, enrollment, value, storedBy, storedDate)); +INSERT INTO Note (_id, noteType, event, enrollment, value, storedBy, storedDate, uid, syncState, deleted) SELECT _id, noteType, event, enrollment, value, storedBy, storedDate, uid, state, deleted FROM Note_Old; +DROP TABLE Note_Old; + +ALTER TABLE FileResource RENAME TO FileResource_Old; +CREATE TABLE FileResource (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, name TEXT, created TEXT, lastUpdated TEXT, contentType TEXT, contentLength INTEGER, path TEXT, syncState TEXT); +INSERT INTO FileResource (_id, uid, name, created, lastUpdated, contentType, contentLength, path, syncState) SELECT _id, uid, name, created, lastUpdated, contentType, contentLength, path, state FROM FileResource_Old; +DROP TABLE FileResource_Old; + +ALTER TABLE TrackedEntityInstance ADD COLUMN syncState TEXT; +UPDATE TrackedEntityInstance SET syncState = state; + +ALTER TABLE Enrollment ADD COLUMN syncState TEXT; +UPDATE Enrollment SET syncState = state; + +ALTER TABLE Event RENAME TO Event_Old; +CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +INSERT INTO Event (_id, uid, enrollment, created, lastUpdated, createdAtClient, lastUpdatedAtClient, status, geometryType, geometryCoordinates, program, programStage, organisationUnit, eventDate, completedDate, dueDate, syncState, attributeOptionCombo, deleted, assignedUser) SELECT _id, uid, enrollment, created, lastUpdated, createdAtClient, lastUpdatedAtClient, status, geometryType, geometryCoordinates, program, programStage, organisationUnit, eventDate, completedDate, dueDate, state, attributeOptionCombo, deleted, assignedUser FROM Event_Old; +DROP TABLE Event_Old; diff --git a/core/src/main/assets/snapshots/101.sql b/core/src/main/assets/snapshots/102.sql similarity index 92% rename from core/src/main/assets/snapshots/101.sql rename to core/src/main/assets/snapshots/102.sql index 97d20251bc..736844e91b 100644 --- a/core/src/main/assets/snapshots/101.sql +++ b/core/src/main/assets/snapshots/102.sql @@ -29,7 +29,7 @@ CREATE TABLE Indicator (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL CREATE TABLE DataSetIndicatorLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataSet TEXT NOT NULL, indicator TEXT NOT NULL, FOREIGN KEY (dataSet) REFERENCES DataSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (indicator) REFERENCES Indicator (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataSet, indicator)); CREATE TABLE Period (_id INTEGER PRIMARY KEY AUTOINCREMENT, periodId TEXT, periodType TEXT, startDate TEXT, endDate TEXT, UNIQUE (periodId)); CREATE TABLE ValueTypeDeviceRendering (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, objectTable TEXT, deviceType TEXT, type TEXT, min INTEGER, max INTEGER, step INTEGER, decimalPoints INTEGER, UNIQUE (uid, deviceType)); -CREATE TABLE Note (_id INTEGER PRIMARY KEY AUTOINCREMENT, noteType TEXT, event TEXT, enrollment TEXT, value TEXT, storedBy TEXT, storedDate TEXT, uid TEXT, state TEXT, deleted INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (noteType, event, enrollment, value, storedBy, storedDate)); +CREATE TABLE Note (_id INTEGER PRIMARY KEY AUTOINCREMENT, noteType TEXT, event TEXT, enrollment TEXT, value TEXT, storedBy TEXT, storedDate TEXT, uid TEXT, syncState TEXT, deleted INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (noteType, event, enrollment, value, storedBy, storedDate)); CREATE TABLE Legend (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, startValue REAL, endValue REAL, color TEXT, legendSet TEXT, FOREIGN KEY (legendSet) REFERENCES LegendSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE LegendSet (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, symbolizer TEXT); CREATE TABLE ProgramIndicatorLegendSetLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, programIndicator TEXT NOT NULL, legendSet TEXT NOT NULL, FOREIGN KEY (programIndicator) REFERENCES ProgramIndicator (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (legendSet) REFERENCES LegendSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (programIndicator, legendSet)); @@ -53,7 +53,7 @@ CREATE TABLE ForeignKeyViolation (_id INTEGER PRIMARY KEY AUTOINCREMENT, fromTab CREATE TABLE D2Error (_id INTEGER PRIMARY KEY AUTOINCREMENT, resourceType TEXT, uid TEXT, url TEXT, errorComponent TEXT, errorCode TEXT, errorDescription TEXT, httpErrorCode INTEGER, created TEXT); CREATE TABLE Authority (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT); CREATE TABLE TrackedEntityTypeAttribute (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackedEntityType TEXT, trackedEntityAttribute TEXT, displayInList INTEGER, mandatory INTEGER, searchable INTEGER, sortOrder INTEGER, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityAttribute) REFERENCES TrackedEntityAttribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE Relationship (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, name TEXT, created TEXT, lastUpdated TEXT, relationshipType TEXT NOT NULL, state TEXT, deleted INTEGER, FOREIGN KEY (relationshipType) REFERENCES RelationshipType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE Relationship (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, name TEXT, created TEXT, lastUpdated TEXT, relationshipType TEXT NOT NULL, syncState TEXT, deleted INTEGER, FOREIGN KEY (relationshipType) REFERENCES RelationshipType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataElement (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, valueType TEXT, zeroIsSignificant INTEGER, aggregationType TEXT, formName TEXT, domainType TEXT, displayFormName TEXT, optionSet TEXT, categoryCombo TEXT NOT NULL, fieldMask TEXT, color TEXT, icon TEXT, FOREIGN KEY (optionSet) REFERENCES OptionSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryCombo) REFERENCES CategoryCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE OptionGroup (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, optionSet TEXT NOT NULL, FOREIGN KEY (optionSet) REFERENCES OptionSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE OptionGroupOptionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, optionGroup TEXT NOT NULL, option TEXT NOT NULL, FOREIGN KEY (optionGroup) REFERENCES OptionGroup (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (option) REFERENCES Option (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (optionGroup, option)); @@ -68,14 +68,14 @@ CREATE TABLE UserOrganisationUnit (_id INTEGER PRIMARY KEY AUTOINCREMENT, user T CREATE TABLE RelationshipType (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, fromToName TEXT, toFromName TEXT, bidirectional INTEGER, accessDataWrite INTEGER ); CREATE TABLE ProgramStage (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, executionDateLabel TEXT, allowGenerateNextVisit INTEGER, validCompleteOnly INTEGER, reportDateToUse TEXT, openAfterEnrollment INTEGER, repeatable INTEGER, formType TEXT, displayGenerateEventBox INTEGER, generatedByEnrollmentDate INTEGER, autoGenerateEvent INTEGER, sortOrder INTEGER, hideDueDate INTEGER, blockEntryForm INTEGER, minDaysFromStart INTEGER, standardInterval INTEGER, program TEXT NOT NULL, periodType TEXT, accessDataWrite INTEGER, remindCompleted INTEGER, description TEXT, displayDescription TEXT, featureType TEXT, color TEXT, icon TEXT, enableUserAssignment INTEGER, dueDateLabel TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Program (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, version INTEGER, onlyEnrollOnce INTEGER, enrollmentDateLabel TEXT, displayIncidentDate INTEGER, incidentDateLabel TEXT, registration INTEGER, selectEnrollmentDatesInFuture INTEGER, dataEntryMethod INTEGER, ignoreOverdueEvents INTEGER, selectIncidentDatesInFuture INTEGER, useFirstStageDuringRegistration INTEGER, displayFrontPageList INTEGER, programType TEXT, relatedProgram TEXT, trackedEntityType TEXT, categoryCombo TEXT, accessDataWrite INTEGER, expiryDays INTEGER, completeEventsExpiryDays INTEGER, expiryPeriodType TEXT, minAttributesRequiredToSearch INTEGER, maxTeiCountToReturn INTEGER, featureType TEXT, accessLevel TEXT, color TEXT, icon TEXT, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryCombo) REFERENCES CategoryCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, state TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, state TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, state TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE DataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, period TEXT NOT NULL, organisationUnit TEXT NOT NULL, categoryOptionCombo TEXT NOT NULL, attributeOptionCombo TEXT NOT NULL, value TEXT, storedBy TEXT, created TEXT, lastUpdated TEXT, comment TEXT, followUp INTEGER, state TEXT, deleted INTEGER, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId), FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo)); +CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, state TEXT, syncState TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, state TEXT, syncState TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE DataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, period TEXT NOT NULL, organisationUnit TEXT NOT NULL, categoryOptionCombo TEXT NOT NULL, attributeOptionCombo TEXT NOT NULL, value TEXT, storedBy TEXT, created TEXT, lastUpdated TEXT, comment TEXT, followUp INTEGER, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId), FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo)); CREATE TABLE TrackedEntityDataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, event TEXT NOT NULL, dataElement TEXT NOT NULL, storedBy TEXT, value TEXT, created TEXT, lastUpdated TEXT, providedElsewhere INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE TrackedEntityAttributeValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, created TEXT, lastUpdated TEXT, value TEXT, trackedEntityAttribute TEXT NOT NULL, trackedEntityInstance TEXT NOT NULL, FOREIGN KEY (trackedEntityAttribute) REFERENCES trackedEntityAttribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE FileResource (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, name TEXT, created TEXT, lastUpdated TEXT, contentType TEXT, contentLength INTEGER, path TEXT, state TEXT); -CREATE TABLE DataSetCompleteRegistration (_id INTEGER PRIMARY KEY AUTOINCREMENT, period TEXT NOT NULL, dataSet TEXT NOT NULL, organisationUnit TEXT NOT NULL, attributeOptionCombo TEXT, date TEXT, storedBy TEXT, state TEXT, deleted INTEGER, FOREIGN KEY (dataSet) REFERENCES DataSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (period, dataSet, organisationUnit, attributeOptionCombo)); +CREATE TABLE FileResource (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, name TEXT, created TEXT, lastUpdated TEXT, contentType TEXT, contentLength INTEGER, path TEXT, syncState TEXT); +CREATE TABLE DataSetCompleteRegistration (_id INTEGER PRIMARY KEY AUTOINCREMENT, period TEXT NOT NULL, dataSet TEXT NOT NULL, organisationUnit TEXT NOT NULL, attributeOptionCombo TEXT, date TEXT, storedBy TEXT, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataSet) REFERENCES DataSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (period, dataSet, organisationUnit, attributeOptionCombo)); CREATE TABLE SectionGreyedFieldsLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, section TEXT NOT NULL, dataElementOperand TEXT NOT NULL, categoryOptionCombo TEXT, FOREIGN KEY (section) REFERENCES Section (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (dataElementOperand) REFERENCES DataElementOperand (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (section, dataElementOperand, categoryOptionCombo)); 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); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index a7adfeb070..d7856a9fa6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 101; + static final int VERSION = 102; private final AssetManager assetManager; private final int targetVersion; diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt index ca0458eda7..49bf15e92a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt @@ -55,9 +55,9 @@ internal open class IdentifiableDataObjectStoreImpl( if (setStateStatement == null) { val whereUid = " WHERE " + IdentifiableColumns.UID + " =?" val setState = "UPDATE " + tableName + " SET " + - DataColumns.STATE + " =?" + whereUid + DataColumns.SYNC_STATE + " =?" + whereUid setStateStatement = databaseAdapter.compileStatement(setState) - selectStateQuery = "SELECT " + DataColumns.STATE + " FROM " + tableName + whereUid + selectStateQuery = "SELECT " + DataColumns.SYNC_STATE + " FROM " + tableName + whereUid existsQuery = "SELECT 1 FROM $tableName$whereUid" } } @@ -88,7 +88,7 @@ internal open class IdentifiableDataObjectStoreImpl( override fun setState(uids: List, state: State): Int { val updates = ContentValues() - updates.put(DataColumns.STATE, state.toString()) + updates.put(DataColumns.SYNC_STATE, state.toString()) val whereClause = WhereClauseBuilder() .appendInKeyStringValues(IdentifiableColumns.UID, uids) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt index c93c4f8fbf..31da56b7e3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt @@ -57,8 +57,8 @@ internal open class IdentifiableDeletableDataObjectStoreImpl( if (setStateIfUploadingStatement == null) { val whereUid = " WHERE " + IdentifiableColumns.UID + " =?" val setState = "UPDATE " + tableName + " SET " + - DataColumns.STATE + " =?" + whereUid - val setStateIfUploading = setState + " AND " + DataColumns.STATE + EQ + "'" + State.UPLOADING + "'" + DataColumns.SYNC_STATE + " =?" + whereUid + val setStateIfUploading = setState + " AND " + DataColumns.SYNC_STATE + EQ + "'" + State.UPLOADING + "'" setStateIfUploadingStatement = databaseAdapter.compileStatement(setStateIfUploading) val setDeleted = "UPDATE " + tableName + " SET " + DeletableDataColumns.DELETED + " = 1" + whereUid @@ -87,7 +87,7 @@ internal open class IdentifiableDeletableDataObjectStoreImpl( val whereClause = WhereClauseBuilder() .appendKeyStringValue(IdentifiableColumns.UID, uid) .appendKeyNumberValue(DeletableDataColumns.DELETED, 1) - .appendKeyStringValue(DataColumns.STATE, State.UPLOADING) + .appendKeyStringValue(DataColumns.SYNC_STATE, State.UPLOADING) .build() deleted = deleteWhere(whereClause) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt index 9b744af6ab..fed7651835 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt @@ -161,7 +161,7 @@ internal abstract class IdentifiableDataHandlerImpl( relationships ) { relationship: Relationship -> relationship.toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .deleted(false) .build()!! } @@ -254,7 +254,7 @@ internal abstract class IdentifiableDataHandlerImpl( if (storedObjectUids.isNotEmpty()) { val syncedObjectUidsWhereClause2 = WhereClauseBuilder() .appendInKeyStringValues(IdentifiableColumns.UID, storedObjectUids) - .appendInKeyStringValues(DataColumns.STATE, states) + .appendInKeyStringValues(DataColumns.SYNC_STATE, states) .build() return store.selectUidsWhere(syncedObjectUidsWhereClause2) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java b/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java index e23dcdd0db..299810b74d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java @@ -40,12 +40,18 @@ public abstract class BaseDataObject extends BaseObject implements DataObject { @Override @Nullable - @ColumnName(DataColumns.STATE) + public State state() { + return syncState(); + } + + @Override + @Nullable + @ColumnName(DataColumns.SYNC_STATE) @ColumnAdapter(StateColumnAdapter.class) - public abstract State state(); + public abstract State syncState(); @JsonPOJOBuilder(withPrefix = "") protected static abstract class Builder extends BaseObject.Builder { - public abstract T state(@Nullable State state); + public abstract T syncState(@Nullable State syncState); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java b/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java index b62952a521..897e5a851b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java @@ -30,4 +30,5 @@ public class DataColumns extends CoreColumns { public static final String STATE = "state"; + public static final String SYNC_STATE = "syncState"; } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java b/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java index 24fec9e1c0..4b59f588ca 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java @@ -30,4 +30,5 @@ public interface DataObject extends CoreObject { State state(); + State syncState(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java index 383b131b0b..340df60862 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java @@ -153,7 +153,7 @@ private Event setEventStateForUpdate(String eventUid) { if (event != null) { Date now = new Date(); Event updatedEvent = event.toBuilder() - .state(getStateForUpdate(event.state())) + .syncState(getStateForUpdate(event.state())) .lastUpdated(getMaxDate(event.lastUpdated(), now)) .lastUpdatedAtClient(getMaxDate(event.lastUpdatedAtClient(), now)) .build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistration.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistration.java index 68e3e2f342..a9cfe4e1c7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistration.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistration.java @@ -94,7 +94,7 @@ public static Builder builder() { public abstract static class Builder extends BaseDeletableDataObject.Builder { public Builder() { - state(State.SYNCED); + syncState(State.SYNCED); } public abstract Builder period(@NonNull String period); diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java index 9ecf0c2482..64bd9a7f1a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java @@ -138,7 +138,7 @@ public BooleanFilterConnector b } public EnumFilterConnector byState() { - return cf.enumC(Columns.STATE); + return cf.enumC(Columns.SYNC_STATE); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java index ab55858a12..ddeb5e914c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java @@ -100,13 +100,13 @@ public void blockingSet() { .attributeOptionCombo(attributeOptionCombo) .date(new Date()) .storedBy(username) - .state(State.TO_POST) + .syncState(State.TO_POST) .deleted(false) .build()); } else { DataSetCompleteRegistration newRecord = dataSetCompleteRegistration.toBuilder() .deleted(false) - .state(dataSetCompleteRegistration.state() == State.TO_POST ? State.TO_POST : State.TO_UPDATE) + .syncState(dataSetCompleteRegistration.state() == State.TO_POST ? State.TO_POST : State.TO_UPDATE) .build(); dataSetCompleteRegistrationStore.updateWhere(newRecord); } @@ -134,7 +134,7 @@ public void blockingDelete() throws D2Error { } else { DataSetCompleteRegistration deletedRecord = dataSetCompleteRegistration.toBuilder() .deleted(true) - .state(State.TO_UPDATE) + .syncState(State.TO_UPDATE) .build(); dataSetCompleteRegistrationStore.updateWhere(deletedRecord); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationTableInfo.java index 559be1ccbc..70daf587ea 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationTableInfo.java @@ -68,7 +68,7 @@ public String[] all() { ATTRIBUTE_OPTION_COMBO, DATE, STORED_BY, - STATE, + SYNC_STATE, DELETED); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationStoreImpl.java index ab11686c66..d01f7d8b75 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationStoreImpl.java @@ -52,7 +52,7 @@ final class DataSetCompleteRegistrationStoreImpl extends w.bind(4, dataSetCompleteRegistration.attributeOptionCombo()); w.bind(5, dataSetCompleteRegistration.date()); w.bind(6, dataSetCompleteRegistration.storedBy()); - w.bind(7, dataSetCompleteRegistration.state()); + w.bind(7, dataSetCompleteRegistration.syncState()); w.bind(8, dataSetCompleteRegistration.deleted()); }; @@ -94,7 +94,7 @@ public static DataSetCompleteRegistrationStoreImpl create(DatabaseAdapter databa @Override public void setState(DataSetCompleteRegistration dataSetCompleteRegistration, State newState) { DataSetCompleteRegistration updatedDataSetCompleteRegistration - = dataSetCompleteRegistration.toBuilder().state(newState).build(); + = dataSetCompleteRegistration.toBuilder().syncState(newState).build(); updateWhere(updatedDataSetCompleteRegistration); } @@ -123,7 +123,7 @@ public boolean removeNotPresentAndSynced(Collection dataSetUids, "%" + rootOrgunitUid + "%"); whereClause.appendInSubQuery(DataSetCompleteRegistrationTableInfo.Columns.ORGANISATION_UNIT, subQuery); - whereClause.appendKeyStringValue(DataSetCompleteRegistrationTableInfo.Columns.STATE, State.SYNCED); + whereClause.appendKeyStringValue(DataSetCompleteRegistrationTableInfo.Columns.SYNC_STATE, State.SYNCED); return deleteWhere(whereClause.build()); } @@ -137,7 +137,7 @@ public boolean isBeingUpload(DataSetCompleteRegistration dscr) { dscr.organisationUnit()) .appendKeyStringValue(DataSetCompleteRegistrationTableInfo.Columns.ATTRIBUTE_OPTION_COMBO, dscr.attributeOptionCombo()) - .appendKeyStringValue(DataSetCompleteRegistrationTableInfo.Columns.STATE, State.UPLOADING) + .appendKeyStringValue(DataSetCompleteRegistrationTableInfo.Columns.SYNC_STATE, State.UPLOADING) .build(); return selectWhere(whereClause).size() > 0; } diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSQLStatementBuilder.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSQLStatementBuilder.java index 196ef89c8f..a574a612a5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSQLStatementBuilder.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSQLStatementBuilder.java @@ -131,8 +131,8 @@ public class DataSetInstanceSQLStatementBuilder implements ReadOnlySQLStatementB private static final String LAST_UPDATED = "MAX(" + LAST_UPDATED_VALUES + ", COALESCE(" + COMPLETION_DATE + ", 0))"; - private static final String VALUE_STATE = DATAVALUE_TABLE_ALIAS + "." + DataColumns.STATE; - private static final String COMPLETION_STATE = COMPLETE_TABLE_ALIAS + "." + DataColumns.STATE; + private static final String VALUE_STATE = DATAVALUE_TABLE_ALIAS + "." + DataColumns.SYNC_STATE; + private static final String COMPLETION_STATE = COMPLETE_TABLE_ALIAS + "." + DataColumns.SYNC_STATE; private static final String SELECT_VALUE_STATE_ORDERING = " MAX(CASE " + "WHEN " + VALUE_STATE + " IN ('" + State.SYNCED + "','" + State.SYNCED_VIA_SMS + "') THEN 1 " + diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java index 04ec96f363..ec467e2f34 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java @@ -44,7 +44,7 @@ public class DataSetInstanceSummarySQLStatementBuilder extends DataSetInstanceSQ private static final String DS_LIST_TABLE_ALIAS = "dslist"; private static final String DS_INSTANCE_ALIAS = "dsinstance"; - private static final String STATE = DataColumns.STATE; + private static final String STATE = DataColumns.SYNC_STATE; private static final String SELECT_STATE_ORDERING = " MAX(CASE " + "WHEN " + STATE + " IN ('" + State.SYNCED + "','" + State.SYNCED_VIA_SMS + "') THEN 1 " + diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValue.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValue.java index 243666f3c3..333441cd14 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValue.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValue.java @@ -113,7 +113,7 @@ public static DataValue.Builder builder() { public abstract static class Builder extends BaseDeletableDataObject.Builder { public Builder() { - state(State.SYNCED); + syncState(State.SYNCED); } public abstract DataValue.Builder dataElement(@NonNull String dataElement); diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java index 5145f0340e..ed75943360 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java @@ -148,7 +148,7 @@ public BooleanFilterConnector byFollowUp() { } public EnumFilterConnector byState() { - return cf.enumC(Columns.STATE); + return cf.enumC(Columns.SYNC_STATE); } public BooleanFilterConnector byDeleted() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java index 92eed12f76..55774889c5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java @@ -98,7 +98,7 @@ public void blockingDelete() throws D2Error { if (dataValue.state() == State.TO_POST) { super.delete(dataValue); } else { - setObject(dataValue.toBuilder().deleted(true).state(State.TO_UPDATE).build()); + setObject(dataValue.toBuilder().deleted(true).syncState(State.TO_UPDATE).build()); } } @@ -108,11 +108,11 @@ private DataValue.Builder setBuilder() { DataValue dataValue = blockingGetWithoutChildren(); State state = dataValue.state() == State.TO_POST ? State.TO_POST : State.TO_UPDATE; return dataValue.toBuilder() - .state(state) + .syncState(state) .lastUpdated(date); } else { return DataValue.builder() - .state(State.TO_POST) + .syncState(State.TO_POST) .created(date) .lastUpdated(date) .followUp(Boolean.FALSE) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueTableInfo.java index 37fa7f955e..f6094575e5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueTableInfo.java @@ -78,7 +78,7 @@ public String[] all() { LAST_UPDATED, COMMENT, FOLLOW_UP, - STATE, + SYNC_STATE, DELETED); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueHandler.kt index 0a88285ff6..a69634d29b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueHandler.kt @@ -85,7 +85,7 @@ internal class DataValueHandler(store: ObjectWithoutUidStore) : Objec get() { val whereClause = WhereClauseBuilder() .appendNotInKeyStringValues( - DataValueTableInfo.Columns.STATE, + DataValueTableInfo.Columns.SYNC_STATE, Arrays.asList(State.SYNCED.name, State.SYNCED_VIA_SMS.name) ) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java index a760c7b476..702d5a3f78 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/internal/DataValueStore.java @@ -58,7 +58,7 @@ public class DataValueStore extends ObjectWithoutUidStoreImpl { w.bind(9, dataValue.lastUpdated()); w.bind(10, dataValue.comment()); w.bind(11, dataValue.followUp()); - w.bind(12, dataValue.state()); + w.bind(12, dataValue.syncState()); w.bind(13, dataValue.deleted()); }; @@ -95,7 +95,7 @@ public static DataValueStore create(DatabaseAdapter databaseAdapter) { Collection getDataValuesWithState(State state) { String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(Columns.STATE, state.name()).build(); + .appendKeyStringValue(Columns.SYNC_STATE, state.name()).build(); return selectWhere(whereClause); } @@ -105,7 +105,7 @@ Collection getDataValuesWithState(State state) { */ public void setState(DataValue dataValue, State newState) { - DataValue updatedDataValue = dataValue.toBuilder().state(newState).build(); + DataValue updatedDataValue = dataValue.toBuilder().syncState(newState).build(); updateWhere(updatedDataValue); } @@ -116,7 +116,7 @@ public boolean exists(DataValue dataValue) { boolean isDataValueBeingUpload(DataValue dataValue) { String whereClause = uniqueWhereClauseBuilder(dataValue) - .appendKeyStringValue(Columns.STATE, State.UPLOADING) + .appendKeyStringValue(Columns.SYNC_STATE, State.UPLOADING) .build(); return selectWhere(whereClause).size() > 0; } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java index 3431964569..3e5a26a72b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java @@ -43,6 +43,7 @@ import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbDateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbGeometryColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.EnrollmentStatusColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreCoordinatesColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreEventListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNoteListColumnAdapter; @@ -50,8 +51,10 @@ import org.hisp.dhis.android.core.arch.helpers.CoordinateHelper; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; import org.hisp.dhis.android.core.common.Coordinates; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentFields; import org.hisp.dhis.android.core.event.Event; import org.hisp.dhis.android.core.note.Note; @@ -154,6 +157,12 @@ public abstract class Enrollment extends BaseDeletableDataObject implements Obje @ColumnAdapter(IgnoreRelationshipListColumnAdapter.class) abstract List relationships(); + @Override + @Nullable + @ColumnName(DataColumns.STATE) + @ColumnAdapter(StateColumnAdapter.class) + public abstract State state(); + public static Builder builder() { return new $$AutoValue_Enrollment.Builder(); } @@ -211,6 +220,8 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder relationships); + public abstract Builder state(State state); + abstract Enrollment autoBuild(); // Auxiliary fields to access values diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java index d408339d4b..f116a8609d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java @@ -95,6 +95,7 @@ private Enrollment.Builder updateBuilder() { return enrollment.toBuilder() .state(state) + .syncState(state) .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java index 08efea9239..5d3e2b4c20 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java @@ -85,6 +85,7 @@ public String[] all() { TRACKED_ENTITY_INSTANCE, GEOMETRY_TYPE, GEOMETRY_COORDINATES, + SYNC_STATE, STATE, DELETED ); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt index b4e9c0ba51..fa30fc2ad7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt @@ -48,7 +48,7 @@ internal class NewTrackerImporterEnrollmentTransformer : Transformer relationshipOrphanCleaner(EnrollmentRela @Reusable OrphanCleaner eventOrphanCleaner(DatabaseAdapter databaseAdapter) { return new DataOrphanCleanerImpl<>(EventTableInfo.TABLE_INFO.name(), EventTableInfo.Columns.ENROLLMENT, - DataColumns.STATE, databaseAdapter); + DataColumns.SYNC_STATE, databaseAdapter); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java index 2e70f233f1..a26bd8446c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java @@ -90,12 +90,12 @@ final class EnrollmentHandler extends IdentifiableDataHandlerImpl { @Override protected Enrollment addRelationshipState(Enrollment o) { - return o.toBuilder().state(State.RELATIONSHIP).build(); + return o.toBuilder().state(State.RELATIONSHIP).syncState(State.RELATIONSHIP).build(); } @Override protected Enrollment addSyncedState(Enrollment o) { - return o.toBuilder().state(State.SYNCED).build(); + return o.toBuilder().state(State.SYNCED).syncState(State.SYNCED).build(); } @Override @@ -121,7 +121,7 @@ protected void afterObjectHandled(Enrollment enrollment, HandleAction action, Bo if (action != HandleAction.Delete) { eventHandler.handleMany(EnrollmentInternalAccessor.accessEvents(enrollment), event -> event.toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .build(), overwrite); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java index 289874454f..bcd6b9a61d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java @@ -144,11 +144,11 @@ private void handleNoteImportSummary(String enrollmentUid, State state) { State newNoteState = state.equals(State.SYNCED) ? State.SYNCED : State.TO_POST; String whereClause = new WhereClauseBuilder() .appendInKeyStringValues( - DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) + DataColumns.SYNC_STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build(); List notes = noteStore.selectWhere(whereClause); for (Note note : notes) { - noteStore.update(note.toBuilder().state(newNoteState).build()); + noteStore.update(note.toBuilder().syncState(newNoteState).build()); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java index f09da8ae7c..59b263be15 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java @@ -47,6 +47,7 @@ public Enrollment transform(EnrollmentCreateProjection projection) { return Enrollment.builder() .uid(generatedUid) .state(State.TO_POST) + .syncState(State.TO_POST) .created(creationDate) .lastUpdated(creationDate) .createdAtClient(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java index e84b7d0958..452a6718ea 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java @@ -68,8 +68,9 @@ public final class EnrollmentStoreImpl w.bind(13, o.trackedEntityInstance()); w.bind(14, o.geometry() == null ? null : o.geometry().type()); w.bind(15, o.geometry() == null ? null : o.geometry().coordinates()); - w.bind(16, o.state()); - w.bind(17, o.deleted()); + w.bind(16, o.syncState()); + w.bind(17, o.state()); + w.bind(18, o.deleted()); }; private EnrollmentStoreImpl(DatabaseAdapter databaseAdapter, diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java index 8d46ea8664..b75ae19c95 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java @@ -175,7 +175,7 @@ public DateFilterConnector byDueDate() { } public EnumFilterConnector byState() { - return cf.enumC(Columns.STATE); + return cf.enumC(Columns.SYNC_STATE); } public StringFilterConnector byAttributeOptionComboUid() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java index 2163f9762f..5f408e6c10 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java @@ -98,7 +98,7 @@ private Event.Builder updateBuilder() { state = state == State.TO_POST ? state : State.TO_UPDATE; return event.toBuilder() - .state(state) + .syncState(state) .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java index 41f34399f2..5c237e6c56 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java @@ -87,7 +87,7 @@ public String[] all() { EVENT_DATE, COMPLETE_DATE, DUE_DATE, - STATE, + SYNC_STATE, ATTRIBUTE_OPTION_COMBO, DELETED, ASSIGNED_USER diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt index 0a69898b7c..8e80ac223d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt @@ -50,7 +50,7 @@ internal class NewTrackerImporterEventTransformer : Transformer { val whereNotesClause = WhereClauseBuilder() .appendInKeyStringValues( - DataColumns.STATE, State.uploadableStatesIncludingError().map { it.name } + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } ) .appendKeyStringValue(NoteTableInfo.Columns.NOTE_TYPE, Note.NoteType.EVENT_NOTE) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java index 4249672b8c..1d5d68415a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java @@ -46,7 +46,7 @@ public Event transform(EventCreateProjection projection) { return Event.builder() .uid(generatedUid) - .state(State.TO_POST) + .syncState(State.TO_POST) .created(creationDate) .lastUpdated(creationDate) .createdAtClient(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java index 7079151eb4..05f0c94c2c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java @@ -72,7 +72,7 @@ public final class EventStoreImpl extends IdentifiableDeletableDataObjectStoreIm w.bind(13, o.eventDate()); w.bind(14, o.completedDate()); w.bind(15, o.dueDate()); - w.bind(16, o.state()); + w.bind(16, o.syncState()); w.bind(17, o.attributeOptionCombo()); w.bind(18, o.deleted()); w.bind(19, o.assignedUser()); @@ -89,7 +89,7 @@ private EventStoreImpl(DatabaseAdapter databaseAdapter, public Map> queryEventsAttachedToEnrollmentToPost() { String eventsAttachedToEnrollmentsQuery = new WhereClauseBuilder() .appendIsNotNullValue(Columns.ENROLLMENT) - .appendInKeyStringValues(Columns.STATE, EnumHelper.asStringList(State.uploadableStates())).build(); + .appendInKeyStringValues(Columns.SYNC_STATE, EnumHelper.asStringList(State.uploadableStates())).build(); List eventList = selectWhere(eventsAttachedToEnrollmentsQuery); @@ -106,7 +106,7 @@ public List querySingleEventsToPost() { String states = CollectionsHelper.commaAndSpaceSeparatedArrayValues( CollectionsHelper.withSingleQuotationMarksArray(EnumHelper.asStringList(State.uploadableStates()))); String singleEventsToPostQuery = QUERY_SINGLE_EVENTS + - " AND (Event.state IN (" + states + "))"; + " AND (" + Columns.SYNC_STATE + " IN (" + states + "))"; return eventListFromQuery(singleEventsToPostQuery); } @@ -165,7 +165,7 @@ public int countTeisWhereEvents(String whereClause) { @Override public List queryMissingRelationshipsUids() { String whereRelationshipsClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.RELATIONSHIP) + .appendKeyStringValue(DataColumns.SYNC_STATE, State.RELATIONSHIP) .appendIsNullValue(EventTableInfo.Columns.ORGANISATION_UNIT) .build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java index 6038234813..3f25055fc8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java @@ -157,6 +157,6 @@ public StringFilterConnector byPath() { } public EnumFilterConnector byState() { - return cf.enumC(Columns.STATE); + return cf.enumC(Columns.SYNC_STATE); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceTableInfo.java index c75d404878..835f29f3e8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceTableInfo.java @@ -70,7 +70,7 @@ public String[] all() { CONTENT_TYPE, CONTENT_LENGTH, PATH, - STATE); + SYNC_STATE); } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallFactory.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallFactory.java index 293327945c..29fb6a06a0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallFactory.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallFactory.java @@ -116,7 +116,7 @@ private void downloadAttributeValueFiles(final List } handler.handleMany(fileResources, fileResource -> fileResource.toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .build()); } @@ -146,7 +146,7 @@ private void downloadDataValueFiles(final List trackedEn } handler.handleMany(fileResources, fileResource -> fileResource.toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .build()); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourcePostCall.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourcePostCall.java index d7304c1228..257f3aa3c1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourcePostCall.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourcePostCall.java @@ -207,7 +207,7 @@ private File updateFile(File file, FileResource fileResource, Context context) { private void updateFileResource(FileResource fileResource, FileResource downloadedFileResource, File file) { fileResourceStore.delete(fileResource.uid()); fileResourceHandler.handle(downloadedFileResource.toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .path(file.getAbsolutePath()) .build()); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceProjectionTransformer.java index cf5895b526..1e13e36d61 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceProjectionTransformer.java @@ -43,7 +43,7 @@ public FileResource transform(File file) { Date creationDate = new Date(); return FileResource.builder() - .state(State.TO_POST) + .syncState(State.TO_POST) .name(file.getName()) .created(creationDate) .lastUpdated(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceStoreImpl.java index 1e4f2b971b..1c119a9fed 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceStoreImpl.java @@ -49,7 +49,7 @@ public final class FileResourceStoreImpl extends IdentifiableDataObjectStoreImpl w.bind(5, o.contentType()); w.bind(6, o.contentLength()); w.bind(7, o.path()); - w.bind(8, o.state()); + w.bind(8, o.syncState()); }; private FileResourceStoreImpl(DatabaseAdapter databaseAdapter, diff --git a/core/src/main/java/org/hisp/dhis/android/core/note/NewTrackerImporterNoteTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/note/NewTrackerImporterNoteTransformer.kt index 0f3d2c18a2..fd9bcc5727 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/note/NewTrackerImporterNoteTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/note/NewTrackerImporterNoteTransformer.kt @@ -41,7 +41,7 @@ internal class NewTrackerImporterNoteTransformer : Transformer buildUniqueCollection(Collection notes, Note.NoteType not NoteTableInfo.Columns.EVENT; String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.TO_POST) + .appendKeyStringValue(DataColumns.SYNC_STATE, State.TO_POST) .appendKeyStringValue(ownerColumn, ownerUid).build(); List toPostNotes = noteStore.selectWhere(whereClause); @@ -76,7 +76,7 @@ public Set buildUniqueCollection(Collection notes, Note.NoteType not for (Note note : notes) { uniqueNotes.add(note.toBuilder() .id(null) - .state(State.SYNCED) + .syncState(State.SYNCED) .build()); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 4ec7d98255..0ffca401fc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -134,7 +134,7 @@ public String blockingAdd(Relationship relationship) throws D2Error { if (isUpdatableState(fromState)) { relationshipHandler.handle(relationshipWithUid, r -> r.toBuilder() - .state(State.TO_POST) + .syncState(State.TO_POST) .deleted(false) .build()); dataStatePropagator.propagateRelationshipUpdate(from); diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTableInfo.java index 54b31e431a..fb359e507d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTableInfo.java @@ -67,7 +67,7 @@ public String[] all() { CREATED, LAST_UPDATED, RELATIONSHIP_TYPE, - STATE, + SYNC_STATE, DELETED ); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManager.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManager.java index eb07cd685d..e445082eb5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManager.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManager.java @@ -83,7 +83,7 @@ Relationship229Compatible to229Compatible(Relationship relationship, String teiU .name(relationship.name()) .created(relationship.created()) .lastUpdated(relationship.lastUpdated()) - .state(relationship.state()) + .syncState(relationship.syncState()) .deleted(relationship.deleted()); if (versionManager.is2_29()) { @@ -108,7 +108,7 @@ public Relationship from229Compatible(Relationship229Compatible relationship229C .name(relationship229Compatible.name()) .created(relationship229Compatible.created()) .lastUpdated(relationship229Compatible.lastUpdated()) - .state(relationship229Compatible.state()) + .syncState(relationship229Compatible.syncState()) .deleted(relationship229Compatible.deleted()); if (versionManager.is2_29()) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java index 8ae929243d..2a397799bf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java @@ -49,7 +49,7 @@ public final class RelationshipStoreImpl extends IdentifiableDeletableDataObject w.bind(3, o.created()); w.bind(4, o.lastUpdated()); w.bind(5, o.relationshipType()); - w.bind(6, o.state()); + w.bind(6, o.syncState()); w.bind(7, o.deleted()); }; diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt index 03ef092a7e..8a0e5e60d1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt @@ -43,7 +43,7 @@ internal class NewTrackerImporterTranckedEntityTransformer : .organisationUnit(o.organisationUnit()) .trackedEntityType(o.trackedEntityType()) .geometry(o.geometry()) - .state(o.state()) + .syncState(o.syncState()) .build() } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java index 532776b495..089ed71811 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java @@ -37,18 +37,22 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.gabrielittner.auto.value.cursor.ColumnAdapter; +import com.gabrielittner.auto.value.cursor.ColumnName; 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.DbGeometryColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreEnrollmentListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreRelationship229CompatibleListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreStringColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreTrackedEntityAttributeValueListColumnAdapter; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.FeatureType; import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.Enrollment; import org.hisp.dhis.android.core.relationship.internal.Relationship229Compatible; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceFields; @@ -121,6 +125,12 @@ public abstract class TrackedEntityInstance extends BaseDeletableDataObject impl @ColumnAdapter(IgnoreEnrollmentListColumnAdapter.class) abstract List enrollments(); + @Override + @Nullable + @ColumnName(DataColumns.STATE) + @ColumnAdapter(StateColumnAdapter.class) + public abstract State state(); + public static Builder builder() { return new $$AutoValue_TrackedEntityInstance.Builder(); } @@ -164,6 +174,8 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder trackedEntityAttributeValues); + public abstract Builder state(State state); + abstract Builder relationships(List relationships); abstract Builder enrollments(List enrollments); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java index 9fd6ef70f0..850dd5a707 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java @@ -79,6 +79,7 @@ private TrackedEntityInstance.Builder updateBuilder() throws D2Error { return trackedEntityInstance.toBuilder() .state(state) + .syncState(state) .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java index 4c145370e4..a25637a034 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java @@ -73,6 +73,7 @@ public String[] all() { TRACKED_ENTITY_TYPE, GEOMETRY_TYPE, GEOMETRY_COORDINATES, + SYNC_STATE, STATE, DELETED ); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index 199c226445..d2bbd80b55 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -96,7 +96,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter private fun getNotes(): List { val whereNotesClause = WhereClauseBuilder() .appendInKeyStringValues( - DataColumns.STATE, State.uploadableStatesIncludingError().map { it.name } + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } ) .build() val notesTransformer = NewTrackerImporterNoteTransformer() diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceEntityDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceEntityDIModule.java index dd24838f17..af3343b038 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceEntityDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceEntityDIModule.java @@ -80,7 +80,7 @@ TrackedEntityInstanceUidHelper uidHelper(TrackedEntityInstanceUidHelperImpl impl @Reusable OrphanCleaner enrollmentOrphanCleaner(DatabaseAdapter databaseAdapter) { return new DataOrphanCleanerImpl<>(EnrollmentTableInfo.TABLE_INFO.name(), - EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, DataColumns.STATE, databaseAdapter); + EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, DataColumns.SYNC_STATE, databaseAdapter); } @Provides diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java index 6467dc6c16..e7cc2cecae 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java @@ -106,6 +106,7 @@ protected void afterObjectHandled(final TrackedEntityInstance trackedEntityInsta if (enrollments != null) { enrollmentHandler.handleMany(enrollments, enrollment -> enrollment.toBuilder() .state(State.SYNCED) + .syncState(State.SYNCED) .build(), overwrite); } @@ -122,12 +123,12 @@ protected void afterObjectHandled(final TrackedEntityInstance trackedEntityInsta @Override protected TrackedEntityInstance addRelationshipState(TrackedEntityInstance o) { - return o.toBuilder().state(State.RELATIONSHIP).build(); + return o.toBuilder().state(State.RELATIONSHIP).syncState(State.RELATIONSHIP).build(); } @Override protected TrackedEntityInstance addSyncedState(TrackedEntityInstance o) { - return o.toBuilder().state(State.SYNCED).build(); + return o.toBuilder().state(State.SYNCED).syncState(State.SYNCED).build(); } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt index 3c038854ec..e2f2367c08 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt @@ -78,7 +78,7 @@ internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constr val attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost() val whereNotesClause = WhereClauseBuilder() .appendInKeyStringValues( - DataColumns.STATE, State.uploadableStatesIncludingError().map { it.name } + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } ) .build() val notes = noteStore.selectWhere(whereNotesClause) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java index 9fe8d772ac..e7c825bb7e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java @@ -47,6 +47,7 @@ public TrackedEntityInstance transform(TrackedEntityInstanceCreateProjection pro return TrackedEntityInstance.builder() .uid(generatedUid) .state(State.TO_POST) + .syncState(State.TO_POST) .created(creationDate) .lastUpdated(creationDate) .createdAtClient(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java index 31b1fc1edd..7ec1b2b4c0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java @@ -55,8 +55,9 @@ public final class TrackedEntityInstanceStoreImpl w.bind(7, o.trackedEntityType()); w.bind(8, o.geometry() == null ? null : o.geometry().type()); w.bind(9, o.geometry() == null ? null : o.geometry().coordinates()); - w.bind(10, o.state()); - w.bind(11, o.deleted()); + w.bind(10, o.syncState()); + w.bind(11, o.state()); + w.bind(12, o.deleted()); }; public TrackedEntityInstanceStoreImpl(DatabaseAdapter databaseAdapter, diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt index fd8e4773e7..0201fd7200 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt @@ -126,9 +126,9 @@ internal class TrackedEntityInstanceLocalQueryHelper @Inject constructor( } if (scope.states() == null) { - where.appendNotKeyStringValue(dot(teiAlias, DataColumns.STATE), State.RELATIONSHIP.name) + where.appendNotKeyStringValue(dot(teiAlias, DataColumns.SYNC_STATE), State.RELATIONSHIP.name) } else { - where.appendInKeyEnumValues(dot(teiAlias, DataColumns.STATE), scope.states()) + where.appendInKeyEnumValues(dot(teiAlias, DataColumns.SYNC_STATE), scope.states()) } if (!scope.includeDeleted()) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index 1ccec87d9d..aedcf41259 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -51,11 +51,11 @@ internal class JobReportEventHandler @Inject internal constructor( val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST val whereClause = WhereClauseBuilder() .appendInKeyStringValues( - DataColumns.STATE, State.uploadableStatesIncludingError().map { it.name } + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } ) .appendKeyStringValue(NoteTableInfo.Columns.EVENT, eventUid).build() for (note in noteStore.selectWhere(whereClause)) { - noteStore.update(note.toBuilder().state(newNoteState).build()) + noteStore.update(note.toBuilder().syncState(newNoteState).build()) } } From 3f46d1385a25a77c5584032f94ddf773da6afc64 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 18 Jun 2021 16:33:52 +0200 Subject: [PATCH 087/308] [ANDROSDK-1395] Adapt repositories --- ...eteRegistrationPostCallRealIntegrationShould.java | 2 +- .../DataValuePostCallMockIntegrationShould.kt | 6 +++--- .../DataValuePostCallRealIntegrationShould.java | 2 +- .../EventEndpointCallMockIntegrationShould.kt | 2 +- .../internal/EventPostCallRealIntegrationShould.java | 2 +- ...entPostPayloadGeneratorMockIntegrationShould.java | 12 ++++++------ .../event/internal/EventStoreIntegrationShould.java | 4 ++-- .../note/internal/NoteStoreIntegrationShould.java | 2 +- ...hipCollectionRepositoryMockIntegrationShould.java | 11 +++++++++++ ...TrackedEntityDataValueStoreIntegrationShould.java | 10 +++++----- ...ackedEntityInstanceCallMockIntegrationShould.java | 2 +- ...dEntityInstancePostCallRealIntegrationShould.java | 6 ++++-- ...ncePostPayloadGeneratorMockIntegrationShould.java | 11 ++++++++--- ...lueCollectionRepositoryMockIntegrationShould.java | 2 +- ...entCollectionRepositoryMockIntegrationShould.java | 2 +- ...rceCollectionRepositoryMockIntegrationShould.java | 2 +- ...oteCollectionRepositoryMockIntegrationShould.java | 7 +++++++ core/src/main/assets/snapshots/102.sql | 4 ++-- ...aSetCompleteRegistrationCollectionRepository.java | 12 +++++++++++- .../datavalue/DataValueCollectionRepository.java | 12 +++++++++++- .../enrollment/EnrollmentCollectionRepository.java | 4 ++++ .../core/event/EventCollectionRepository.java | 12 +++++++++++- .../event/search/EventCollectionRepositoryAdapter.kt | 2 +- .../FileResourceCollectionRepository.java | 12 +++++++++++- .../android/core/note/NoteCollectionRepository.java | 5 +++++ .../RelationshipCollectionRepository.java | 5 +++++ .../localdbrepository/internal/DataSetsStore.java | 2 +- .../internal/FileResourceCleaner.java | 2 +- .../internal/LocalDbRepositoryImpl.java | 2 +- .../TrackedEntityInstanceCollectionRepository.java | 4 ++++ .../internal/TrackedEntityDataValueStoreImpl.java | 3 ++- .../search/TrackedEntityInstanceLocalQueryHelper.kt | 4 ++-- .../android/core/data/datavalue/DataValueSamples.kt | 2 +- .../core/data/fileresource/FileResourceSamples.java | 2 +- .../dhis/android/core/data/note/NoteSamples.java | 2 +- .../core/data/relationship/RelationshipSamples.java | 4 ++-- .../core/data/trackedentity/EventSamples.java | 2 +- .../internal/TrackedEntityInstanceHandlerShould.java | 2 ++ 38 files changed, 135 insertions(+), 49 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationPostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationPostCallRealIntegrationShould.java index a4dfea2c65..e83c6398ce 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationPostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/dataset/internal/DataSetCompleteRegistrationPostCallRealIntegrationShould.java @@ -177,7 +177,7 @@ private DataSetCompleteRegistration getTestDataSetCompleteRegistrationWith(State .organisationUnit("DiszpKrYNg8") .date(dateFormat.parse("2010-03-02")) .storedBy("android") - .state(state) + .syncState(state) .build(); } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt index 7ccbbc0ca4..dfa70a8428 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallMockIntegrationShould.kt @@ -28,7 +28,7 @@ class DataValuePostCallMockIntegrationShould : BaseMockIntegrationTestMetadataEn d2.dataValueModule().dataValues().blockingUpload() // Then all data set should be properly synced - val synced = d2.dataValueModule().dataValues().byState().eq(State.SYNCED).blockingGet() + val synced = d2.dataValueModule().dataValues().bySyncState().eq(State.SYNCED).blockingGet() assertThat(synced.size).isEqualTo(2) } @@ -42,7 +42,7 @@ class DataValuePostCallMockIntegrationShould : BaseMockIntegrationTestMetadataEn d2.dataValueModule().dataValues().blockingUpload() // Then one data set should marked as WARNING - val warnings = d2.dataValueModule().dataValues().byState().eq(State.WARNING).blockingGet() + val warnings = d2.dataValueModule().dataValues().bySyncState().eq(State.WARNING).blockingGet() assertThat(warnings.size).isEqualTo(1) } @@ -56,7 +56,7 @@ class DataValuePostCallMockIntegrationShould : BaseMockIntegrationTestMetadataEn d2.dataValueModule().dataValues().blockingUpload() // Then all data values should be marked as WARNING - val warnings = d2.dataValueModule().dataValues().byState().eq(State.WARNING).blockingGet() + val warnings = d2.dataValueModule().dataValues().bySyncState().eq(State.WARNING).blockingGet() assertThat(warnings.size).isEqualTo(2) } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallRealIntegrationShould.java index ed56f105d3..37fbe55ed9 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/datavalue/internal/DataValuePostCallRealIntegrationShould.java @@ -109,7 +109,7 @@ private DataValue getTestDataValueWith(State state, int value) { .period(d2.periodModule().periods().one().blockingGet().periodId()) .organisationUnit(d2.organisationUnitModule().organisationUnits().one().blockingGet().uid()) .value(String.valueOf(value)) - .state(state) + .syncState(state) .build(); } } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt index 325e4267cc..3b22ec3190 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt @@ -83,7 +83,7 @@ class EventEndpointCallMockIntegrationShould : BaseMockIntegrationTestMetadataEn assertThat(events.size).isEqualTo(1) EventStoreImpl.create(d2.databaseAdapter()).update( event.toBuilder() - .state(state).status(EventStatus.SKIPPED).build() + .syncState(state).status(EventStatus.SKIPPED).build() ) enqueue("event/events_1.json") diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java index 23e810c7bc..7ce9542bbf 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java @@ -160,7 +160,7 @@ private void createDummyDataToPost(String eventUid) { eventStore.insert(Event.builder().uid(eventUid).created(new Date()).lastUpdated(new Date()) .status(EventStatus.ACTIVE).program(programUid) .programStage(programStageUid).organisationUnit(orgUnitUid).eventDate(new Date()) - .completedDate(new Date()).dueDate(new Date()).state(State.TO_POST) + .completedDate(new Date()).dueDate(new Date()).syncState(State.TO_POST) .attributeOptionCombo(attributeOptionCombo).build()); TrackedEntityDataValue trackedEntityDataValue = TrackedEntityDataValue.builder() diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java index 82c702d52f..3517f60a21 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java @@ -149,7 +149,7 @@ public void recreate_events_with_filters() { List events = payloadGenerator.getEvents( d2.eventModule().events().byProgramUid().eq(program.uid()) - .byState().in(State.uploadableStates()).blockingGet()); + .bySyncState().in(State.uploadableStates()).blockingGet()); assertThat(events.size()).isEqualTo(3); assertThat(UidsHelper.getUidsList(events).containsAll(Lists.newArrayList(event1, event2, event3))) @@ -189,7 +189,7 @@ private void storeEvents() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.TO_POST) + .syncState(State.TO_POST) .trackedEntityDataValues(Collections.singletonList(dataValue1)) .build(); @@ -200,7 +200,7 @@ private void storeEvents() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.TO_POST) + .syncState(State.TO_POST) .trackedEntityDataValues(Collections.singletonList(dataValue2)) .build(); @@ -211,7 +211,7 @@ private void storeEvents() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.TO_POST) + .syncState(State.TO_POST) .trackedEntityDataValues(Collections.singletonList(dataValue3)) .build(); @@ -222,7 +222,7 @@ private void storeEvents() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.ERROR) + .syncState(State.ERROR) .trackedEntityDataValues(Collections.singletonList(dataValue4)) .build(); @@ -250,7 +250,7 @@ private void storeSingleEvent(String eventUid, Program program, State state, Boo .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(state) + .syncState(state) .deleted(deleted) .build()); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java index b834ca1a4c..54c3c37504 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java @@ -61,7 +61,7 @@ protected Event buildObjectToUpdate() { @Override protected Event buildObjectWithToDeleteState() { return EventSamples.get().toBuilder() - .state(State.TO_UPDATE) + .syncState(State.TO_UPDATE) .deleted(true) .build(); } @@ -69,7 +69,7 @@ protected Event buildObjectWithToDeleteState() { @Override protected Event buildObjectWithSyncedState() { return EventSamples.get().toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .build(); } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/note/internal/NoteStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/note/internal/NoteStoreIntegrationShould.java index 054a300d7f..59606ef528 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/note/internal/NoteStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/note/internal/NoteStoreIntegrationShould.java @@ -53,7 +53,7 @@ protected Note buildObject() { @Override protected Note buildObjectToUpdate() { return NoteSamples.getNote().toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) .build(); } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepositoryMockIntegrationShould.java index a7548b18f3..66a810a937 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepositoryMockIntegrationShould.java @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.relationship; import org.hisp.dhis.android.core.common.BaseNameableObject; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; import org.junit.Test; @@ -101,6 +102,16 @@ public void filter_by_relationship_type() { assertThat(relationships.size()).isEqualTo(1); } + @Test + public void filter_by_sync_state() { + List relationships = + d2.relationshipModule().relationships() + .bySyncState().eq(State.SYNCED) + .blockingGet(); + + assertThat(relationships.size()).isEqualTo(3); + } + @Test public void get_by_item() { RelationshipItem item = RelationshipItem.builder().trackedEntityInstance( diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java index bd5d6115e4..5844c15ac9 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java @@ -125,8 +125,8 @@ public void select_data_values_by_event_uid() { @Test public void select_single_events_data_values() { EventStore eventStore = EventStoreImpl.create(TestDatabaseAdapterFactory.get()); - eventStore.insert(EventSamples.get().toBuilder().uid("event_1").enrollment(null).state(State.TO_POST).build()); - eventStore.insert(EventSamples.get().toBuilder().uid("event_2").state(State.TO_POST).build()); + eventStore.insert(EventSamples.get().toBuilder().uid("event_1").enrollment(null).syncState(State.TO_POST).build()); + eventStore.insert(EventSamples.get().toBuilder().uid("event_2").syncState(State.TO_POST).build()); assertThat(eventStore.count()).isEqualTo(2); store.insert(TrackedEntityDataValueSamples.get() @@ -150,7 +150,7 @@ public void select_tracker_data_values() { TrackedEntityInstanceStore trackedEntityInstanceStore = TrackedEntityInstanceStoreImpl .create(TestDatabaseAdapterFactory.get()); TrackedEntityInstance trackedEntityInstance = TrackedEntityInstance.builder().uid("tei_uid") - .organisationUnit("organisation_unit_uid").trackedEntityType("tei_type").state(State.TO_POST).build(); + .organisationUnit("organisation_unit_uid").trackedEntityType("tei_type").syncState(State.TO_POST).build(); trackedEntityInstanceStore.insert(trackedEntityInstance); EnrollmentStore enrollmentStore = EnrollmentStoreImpl.create(TestDatabaseAdapterFactory.get()); @@ -159,8 +159,8 @@ public void select_tracker_data_values() { enrollmentStore.insert(enrollment); EventStore eventStore = EventStoreImpl.create(TestDatabaseAdapterFactory.get()); - eventStore.insert(EventSamples.get().toBuilder().uid("event_1").state(State.TO_POST).build()); - eventStore.insert(EventSamples.get().toBuilder().uid("event_2").enrollment(null).state(State.TO_POST).build()); + eventStore.insert(EventSamples.get().toBuilder().uid("event_1").syncState(State.TO_POST).build()); + eventStore.insert(EventSamples.get().toBuilder().uid("event_2").enrollment(null).syncState(State.TO_POST).build()); assertThat(eventStore.count()).isEqualTo(2); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java index 930755a420..9e9bfb0a5f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java @@ -219,7 +219,7 @@ private TrackedEntityInstance getDownloadedTei(String teiUid) { List downloadedEventsWithoutValuesAndDeleteFalse = new ArrayList<>(); for (Event event : downloadedEventsWithoutValues) { downloadedEventsWithoutValuesAndDeleteFalse.add( - event.toBuilder().id(null).deleted(false).state(null).build()); + event.toBuilder().id(null).deleted(false).syncState(null).build()); } List dataValueList = TrackedEntityDataValueStoreImpl.create(databaseAdapter).selectAll(); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java index 40e92137c6..5bda5fa910 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java @@ -506,6 +506,7 @@ private void insertATei(String uid, TrackedEntityInstance tei, Geometry geometry .uid(uid) .geometry(geometry) .state(State.TO_POST) + .syncState(State.TO_POST) .build(); trackedEntityInstanceStore.insert(trackedEntityInstance); @@ -526,6 +527,7 @@ private void createDummyDataToPost(String orgUnitUid, String programUid, String .trackedEntityType(trackedEntityUid) .geometry(geometry) .state(State.TO_POST) + .syncState(State.TO_POST) .build(); trackedEntityInstanceStore.insert(trackedEntityInstance); @@ -535,7 +537,7 @@ private void createDummyDataToPost(String orgUnitUid, String programUid, String .program(programUid).incidentDate(refDate).completedDate(refDate).enrollmentDate(refDate) .followUp(Boolean.FALSE).status(EnrollmentStatus.ACTIVE).trackedEntityInstance(trackedEntityInstanceUid) .geometry(Geometry.builder().type(FeatureType.POINT).coordinates("[10.33, 12.231]").build()) - .state(State.TO_POST).build(); + .state(State.TO_POST).syncState(State.TO_POST).build(); enrollmentStore.insert(enrollment); @@ -544,7 +546,7 @@ private void createDummyDataToPost(String orgUnitUid, String programUid, String .status(EventStatus.ACTIVE).program(programUid) .geometry(Geometry.builder().type(FeatureType.POINT).coordinates("[12.21, 13.21]").build()) .programStage(programStageUid).organisationUnit(orgUnitUid).eventDate(refDate).dueDate(refDate) - .completedDate(refDate).state(State.TO_POST).attributeOptionCombo(categoryComboOptionUid) + .completedDate(refDate).syncState(State.TO_POST).attributeOptionCombo(categoryComboOptionUid) .build(); eventStore.insert(event); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java index 0f9d6d8494..95319a2df5 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java @@ -365,7 +365,7 @@ private void storeTrackedEntityInstance() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.TO_UPDATE) + .syncState(State.TO_UPDATE) .trackedEntityDataValues(Collections.singletonList(dataValue1)) .build(); @@ -375,6 +375,7 @@ private void storeTrackedEntityInstance() { .program(program.uid()) .organisationUnit(orgUnit.uid()) .state(State.TO_POST) + .syncState(State.TO_POST) .trackedEntityInstance(teiId) .build(); @@ -386,7 +387,7 @@ private void storeTrackedEntityInstance() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.SYNCED_VIA_SMS) + .syncState(State.SYNCED_VIA_SMS) .trackedEntityDataValues(Collections.singletonList(dataValue2)) .build(); @@ -396,6 +397,7 @@ private void storeTrackedEntityInstance() { .program(program.uid()) .organisationUnit(orgUnit.uid()) .state(State.TO_POST) + .syncState(State.TO_POST) .trackedEntityInstance(teiId) .build(); @@ -407,7 +409,7 @@ private void storeTrackedEntityInstance() { .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.ERROR) + .syncState(State.ERROR) .trackedEntityDataValues(Collections.singletonList(dataValue3)) .build(); @@ -417,6 +419,7 @@ private void storeTrackedEntityInstance() { .program(program.uid()) .organisationUnit(orgUnit.uid()) .state(State.SYNCED) + .syncState(State.SYNCED) .trackedEntityInstance(teiId) .build(); @@ -426,6 +429,7 @@ private void storeTrackedEntityInstance() { .trackedEntityType(teiType.uid()) .organisationUnit(orgUnit.uid()) .state(State.TO_POST) + .syncState(State.TO_POST) .build(); TrackedEntityInstanceStoreImpl.create(databaseAdapter).insert(tei); @@ -450,6 +454,7 @@ private void storeSimpleTrackedEntityInstance(String teiUid, State state) { .trackedEntityType(teiType.uid()) .organisationUnit(orgUnit.uid()) .state(state) + .syncState(state) .build()); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java index 5487539d3d..e7f77d6e44 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueCollectionRepositoryMockIntegrationShould.java @@ -179,7 +179,7 @@ public void filter_by_follow_up() { public void filter_by_state() { List dataValues = d2.dataValueModule().dataValues() - .byState().eq(State.SYNCED) + .bySyncState().eq(State.SYNCED) .blockingGet(); assertThat(dataValues.size()).isEqualTo(5); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java index e33bbbf769..9690a3d35b 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/event/EventCollectionRepositoryMockIntegrationShould.java @@ -221,7 +221,7 @@ public void filter_by_due_date() throws ParseException { public void filter_by_state() { List events = d2.eventModule().events() - .byState().eq(State.SYNCED) + .bySyncState().eq(State.SYNCED) .blockingGet(); assertThat(events.size()).isEqualTo(4); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java index 6133d83f6a..bee2c81041 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/fileresource/FileResourceCollectionRepositoryMockIntegrationShould.java @@ -138,7 +138,7 @@ public void filter_by_state() throws D2Error, IOException { d2.fileResourceModule().fileResources().blockingAdd(getFile()); List fileResources = d2.fileResourceModule().fileResources() - .byState().eq(State.TO_POST) + .bySyncState().eq(State.TO_POST) .blockingGet(); assertThat(fileResources.size()).isEqualTo(1); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java index f2757892c8..1da29745be 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/note/NoteCollectionRepositoryMockIntegrationShould.java @@ -28,6 +28,7 @@ package org.hisp.dhis.android.testapp.note; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.note.Note; import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; @@ -88,6 +89,12 @@ public void filter_by_stored_by() { assertThat(notes.size()).isEqualTo(10); } + @Test + public void filter_by_state() { + List notes = d2.noteModule().notes().bySyncState().eq(State.SYNCED).blockingGet(); + assertThat(notes.size()).isEqualTo(10); + } + @Test public void filter_by_stored_date() { List notes = d2.noteModule().notes().byStoredDate().eq("2018-03-19T15:20:55.058").blockingGet(); diff --git a/core/src/main/assets/snapshots/102.sql b/core/src/main/assets/snapshots/102.sql index 736844e91b..fbb5ecd89a 100644 --- a/core/src/main/assets/snapshots/102.sql +++ b/core/src/main/assets/snapshots/102.sql @@ -68,8 +68,8 @@ CREATE TABLE UserOrganisationUnit (_id INTEGER PRIMARY KEY AUTOINCREMENT, user T CREATE TABLE RelationshipType (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, fromToName TEXT, toFromName TEXT, bidirectional INTEGER, accessDataWrite INTEGER ); CREATE TABLE ProgramStage (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, executionDateLabel TEXT, allowGenerateNextVisit INTEGER, validCompleteOnly INTEGER, reportDateToUse TEXT, openAfterEnrollment INTEGER, repeatable INTEGER, formType TEXT, displayGenerateEventBox INTEGER, generatedByEnrollmentDate INTEGER, autoGenerateEvent INTEGER, sortOrder INTEGER, hideDueDate INTEGER, blockEntryForm INTEGER, minDaysFromStart INTEGER, standardInterval INTEGER, program TEXT NOT NULL, periodType TEXT, accessDataWrite INTEGER, remindCompleted INTEGER, description TEXT, displayDescription TEXT, featureType TEXT, color TEXT, icon TEXT, enableUserAssignment INTEGER, dueDateLabel TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Program (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, version INTEGER, onlyEnrollOnce INTEGER, enrollmentDateLabel TEXT, displayIncidentDate INTEGER, incidentDateLabel TEXT, registration INTEGER, selectEnrollmentDatesInFuture INTEGER, dataEntryMethod INTEGER, ignoreOverdueEvents INTEGER, selectIncidentDatesInFuture INTEGER, useFirstStageDuringRegistration INTEGER, displayFrontPageList INTEGER, programType TEXT, relatedProgram TEXT, trackedEntityType TEXT, categoryCombo TEXT, accessDataWrite INTEGER, expiryDays INTEGER, completeEventsExpiryDays INTEGER, expiryPeriodType TEXT, minAttributesRequiredToSearch INTEGER, maxTeiCountToReturn INTEGER, featureType TEXT, accessLevel TEXT, color TEXT, icon TEXT, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryCombo) REFERENCES CategoryCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, state TEXT, syncState TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, state TEXT, syncState TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, state TEXT, deleted INTEGER, syncState TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, state TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, syncState TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, period TEXT NOT NULL, organisationUnit TEXT NOT NULL, categoryOptionCombo TEXT NOT NULL, attributeOptionCombo TEXT NOT NULL, value TEXT, storedBy TEXT, created TEXT, lastUpdated TEXT, comment TEXT, followUp INTEGER, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId), FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo)); CREATE TABLE TrackedEntityDataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, event TEXT NOT NULL, dataElement TEXT NOT NULL, storedBy TEXT, value TEXT, created TEXT, lastUpdated TEXT, providedElsewhere INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java index 64bd9a7f1a..e9928386d3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationCollectionRepository.java @@ -99,7 +99,7 @@ public DataSetCompleteRegistrationObjectRepository value(final String period, @Override public Observable upload() { return Observable.fromCallable(() -> - byState().in(State.uploadableStatesIncludingError()).blockingGetWithoutChildren() + bySyncState().in(State.uploadableStatesIncludingError()).blockingGetWithoutChildren() ).flatMap(postCall::uploadDataSetCompleteRegistrations); } @@ -137,7 +137,17 @@ public BooleanFilterConnector b return cf.bool(Columns.DELETED); } + /** + * @deprecated Use {@link #bySyncState()} instead. + * + * @return + */ + @Deprecated public EnumFilterConnector byState() { + return bySyncState(); + } + + public EnumFilterConnector bySyncState() { return cf.enumC(Columns.SYNC_STATE); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java index ed75943360..79d2e35f04 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueCollectionRepository.java @@ -73,7 +73,7 @@ public final class DataValueCollectionRepository @Override public Observable upload() { return Observable.fromCallable(() -> - byState().in(State.uploadableStatesIncludingError()).blockingGetWithoutChildren() + bySyncState().in(State.uploadableStatesIncludingError()).blockingGetWithoutChildren() ).flatMap(postCall::uploadDataValues); } @@ -147,7 +147,17 @@ public BooleanFilterConnector byFollowUp() { return cf.bool(Columns.FOLLOW_UP); } + /** + * @deprecated Use {@link #bySyncState()} instead. + * + * @return + */ + @Deprecated public EnumFilterConnector byState() { + return bySyncState(); + } + + public EnumFilterConnector bySyncState() { return cf.enumC(Columns.SYNC_STATE); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java index 666221b5cf..d5e03c5f0e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java @@ -138,6 +138,10 @@ public EnumFilterConnector byState() { return cf.enumC(DataColumns.STATE); } + public EnumFilterConnector bySyncState() { + return cf.enumC(DataColumns.SYNC_STATE); + } + public BooleanFilterConnector byDeleted() { return cf.bool(EnrollmentTableInfo.Columns.DELETED); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java index b75ae19c95..005089eb21 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java @@ -96,7 +96,7 @@ public final class EventCollectionRepository public Observable upload() { return Observable.concat( jobQueryCall.queryPendingJobs(), - Observable.fromCallable(() -> byState().in(State.uploadableStates()) + Observable.fromCallable(() -> bySyncState().in(State.uploadableStates()) .byEnrollmentUid().isNull() .blockingGetWithoutChildren()) .flatMap(postCall::uploadEvents) @@ -174,7 +174,17 @@ public DateFilterConnector byDueDate() { return cf.simpleDate(Columns.DUE_DATE); } + /** + * @deprecated Use {@link #bySyncState()} instead. + * + * @return + */ + @Deprecated public EnumFilterConnector byState() { + return bySyncState(); + } + + public EnumFilterConnector bySyncState() { return cf.enumC(Columns.SYNC_STATE); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/search/EventCollectionRepositoryAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/event/search/EventCollectionRepositoryAdapter.kt index 0ecdc8d5d8..25aed980ef 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/search/EventCollectionRepositoryAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/search/EventCollectionRepositoryAdapter.kt @@ -86,7 +86,7 @@ internal class EventCollectionRepositoryAdapter @Inject constructor( repository = repository.byDeleted().isFalse } - scope.states()?.let { repository = repository.byState().`in`(it) } + scope.states()?.let { repository = repository.bySyncState().`in`(it) } scope.attributeOptionCombos()?.let { repository = repository.byAttributeOptionComboUid().`in`(it) } return repository diff --git a/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java index 3f25055fc8..5ffe4cdc73 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/fileresource/FileResourceCollectionRepository.java @@ -91,7 +91,7 @@ public final class FileResourceCollectionRepository @Override public Observable upload() { - return Observable.fromCallable(() -> byState().in(State.uploadableStates()) + return Observable.fromCallable(() -> bySyncState().in(State.uploadableStates()) .blockingGetWithoutChildren()) .flatMap(postCall::uploadFileResources); } @@ -156,7 +156,17 @@ public StringFilterConnector byPath() { return cf.string(Columns.PATH); } + /** + * @deprecated Use {@link #bySyncState()} instead. + * + * @return + */ + @Deprecated public EnumFilterConnector byState() { + return bySyncState(); + } + + public EnumFilterConnector bySyncState() { return cf.enumC(Columns.SYNC_STATE); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/note/NoteCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/note/NoteCollectionRepository.java index 31bdaadc72..22180203eb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/note/NoteCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/note/NoteCollectionRepository.java @@ -40,6 +40,7 @@ import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; import org.hisp.dhis.android.core.arch.repositories.scope.internal.RepositoryScopeHelper; import org.hisp.dhis.android.core.common.IdentifiableColumns; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.note.NoteTableInfo.Columns; @@ -95,6 +96,10 @@ public StringFilterConnector byStoredDate() { return cf.string(Columns.STORED_DATE); } + public EnumFilterConnector bySyncState() { + return cf.enumC(Columns.SYNC_STATE); + } + @Override public ReadOnlyObjectRepository uid(String uid) { RepositoryScope updatedScope = RepositoryScopeHelper.withUidFilterItem(scope, uid); diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 0ffca401fc..0914122663 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.repositories.collection.ReadWriteWithUidCollectionRepository; import org.hisp.dhis.android.core.arch.repositories.collection.internal.BaseReadOnlyWithUidCollectionRepositoryImpl; import org.hisp.dhis.android.core.arch.repositories.filters.internal.DateFilterConnector; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.EnumFilterConnector; import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; import org.hisp.dhis.android.core.arch.repositories.filters.internal.StringFilterConnector; import org.hisp.dhis.android.core.arch.repositories.object.ReadWriteObjectRepository; @@ -248,6 +249,10 @@ public StringFilterConnector byRelationshipTyp return cf.string(RelationshipTableInfo.Columns.RELATIONSHIP_TYPE); } + public EnumFilterConnector bySyncState() { + return cf.enumC(RelationshipTableInfo.Columns.SYNC_STATE); + } + public RelationshipCollectionRepository withItems() { return cf.withChild(RelationshipFields.ITEMS); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/DataSetsStore.java b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/DataSetsStore.java index 164da654c6..c04753dcd2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/DataSetsStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/DataSetsStore.java @@ -72,7 +72,7 @@ Single> getDataValues(String dataSetUid, String orgUnit, .byAttributeOptionComboUid().eq(attributeOptionComboUid); List dataValues = baseDataValuesRepo - .byState().in(Arrays.asList(State.uploadableStates())) + .bySyncState().in(Arrays.asList(State.uploadableStates())) .blockingGet(); // TODO Workaround to prevent empty lists. Not supported in compression library diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/FileResourceCleaner.java b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/FileResourceCleaner.java index 5a34a37891..c6d9854690 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/FileResourceCleaner.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/FileResourceCleaner.java @@ -126,7 +126,7 @@ Single removeFileAttributeValues(TrackedEntityInstance in private boolean isExistingAndNotSyncedFileResource(String resourceUid) { return fileResourceModule.fileResources() - .byState().notIn(State.SYNCED) + .bySyncState().notIn(State.SYNCED) .uid(resourceUid) .blockingExists(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java index a65f61701a..704dc08749 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java @@ -257,7 +257,7 @@ private Single getTrackedEntityInstance(String instanceUi private Single> getEventsForEnrollment(String enrollmentUid) { return eventModule.events() .byEnrollmentUid().eq(enrollmentUid) - .byState().in(State.uploadableStates()) + .bySyncState().in(State.uploadableStates()) .withTrackedEntityDataValues() .get() .flatMapObservable(Observable::fromIterable) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java index df2b8eb566..b46b98761d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java @@ -145,6 +145,10 @@ public EnumFilterConnector byS return cf.enumC(Columns.STATE); } + public EnumFilterConnector bySyncState() { + return cf.enumC(Columns.SYNC_STATE); + } + public BooleanFilterConnector byDeleted() { return cf.bool(Columns.DELETED); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java index 15941fcd67..25969f38c2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java @@ -42,6 +42,7 @@ import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.State; +import org.hisp.dhis.android.core.event.EventTableInfo; import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue; import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValueTableInfo; @@ -129,7 +130,7 @@ public Map> querySingleEventsTrackedEntityD private String eventInUploadableState() { String states = CollectionsHelper.commaAndSpaceSeparatedArrayValues( CollectionsHelper.withSingleQuotationMarksArray(EnumHelper.asStringList(State.uploadableStates()))); - return "(Event.state IN (" + states + "))"; + return "(Event." + EventTableInfo.Columns.SYNC_STATE + " IN (" + states + "))"; } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt index 0201fd7200..fd8e4773e7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt @@ -126,9 +126,9 @@ internal class TrackedEntityInstanceLocalQueryHelper @Inject constructor( } if (scope.states() == null) { - where.appendNotKeyStringValue(dot(teiAlias, DataColumns.SYNC_STATE), State.RELATIONSHIP.name) + where.appendNotKeyStringValue(dot(teiAlias, DataColumns.STATE), State.RELATIONSHIP.name) } else { - where.appendInKeyEnumValues(dot(teiAlias, DataColumns.SYNC_STATE), scope.states()) + where.appendInKeyEnumValues(dot(teiAlias, DataColumns.STATE), scope.states()) } if (!scope.includeDeleted()) { diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueSamples.kt index 310bfb9c35..600ccdc3c0 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueSamples.kt +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datavalue/DataValueSamples.kt @@ -45,7 +45,7 @@ object DataValueSamples { return DataValue.builder() .id(1L) - .state(State.TO_POST) + .syncState(State.TO_POST) .deleted(false) .dataElement(dataElement) .period(period) diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/fileresource/FileResourceSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/fileresource/FileResourceSamples.java index 248ff9bde5..65843bb120 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/fileresource/FileResourceSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/fileresource/FileResourceSamples.java @@ -43,7 +43,7 @@ public static FileResource get() { .uid("file_resource_uid") .created(getDate("2014-08-20T12:28:56.409")) .lastUpdated(getDate("2015-10-14T13:36:53.063")) - .state(State.TO_POST) + .syncState(State.TO_POST) .contentLength(1024L) .contentType("image/*") .path("path") diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/note/NoteSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/note/NoteSamples.java index a6e0b46bf2..2c8f6c317a 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/note/NoteSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/note/NoteSamples.java @@ -43,7 +43,7 @@ public static Note getNote() { .storedBy("user") .storedDate("2018-03-19T15:20:55.058") .uid("noteUId") - .state(State.TO_POST) + .syncState(State.TO_POST) .build(); } } \ No newline at end of file diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java index 1bff3fb60c..433b4b909b 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java @@ -64,7 +64,7 @@ public class RelationshipSamples { .created(CREATED) .lastUpdated(LAST_UPDATED) .name(NAME) - .state(STATE) + .syncState(STATE) .deleted(DELETED); private static Relationship.Builder commonBuilder = Relationship @@ -72,7 +72,7 @@ public class RelationshipSamples { .created(CREATED) .lastUpdated(LAST_UPDATED) .name(NAME) - .state(STATE) + .syncState(STATE) .deleted(DELETED); public Relationship229Compatible get229Compatible() { diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java index 70559219a6..8f22db7505 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java @@ -64,7 +64,7 @@ public static Event get(String uid, String enrollment, String organisationUnit, .completedDate(getDate("2014-08-20T12:28:56.409")) .dueDate(getDate("2014-08-20T12:28:56.409")) .attributeOptionCombo(attributeOptionCombo) - .state(State.TO_POST) + .syncState(State.TO_POST) .deleted(false) .build(); } diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java index 4edef305b1..d7ed958f46 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java @@ -124,6 +124,7 @@ public void setUp() throws Exception { when(trackedEntityInstance.uid()).thenReturn(TEI_UID); when(trackedEntityInstance.toBuilder()).thenReturn(teiBuilder); when(teiBuilder.state(State.SYNCED)).thenReturn(teiBuilder); + when(teiBuilder.syncState(State.SYNCED)).thenReturn(teiBuilder); when(teiBuilder.build()).thenReturn(trackedEntityInstance); when(TrackedEntityInstanceInternalAccessor.accessEnrollments(trackedEntityInstance)) .thenReturn(Collections.singletonList(enrollment)); @@ -223,6 +224,7 @@ public void invoke_relationship_handler_with_relationship_from_version_manager() when(relationshipVersionManager.getRelativeTei(relationship229Compatible, TEI_UID)).thenReturn(relative); when(relative.toBuilder()).thenReturn(relativeBuilder); when(relativeBuilder.state(any(State.class))).thenReturn(relativeBuilder); + when(relativeBuilder.syncState(any(State.class))).thenReturn(relativeBuilder); when(relativeBuilder.build()).thenReturn(relative); trackedEntityInstanceHandler.handleMany(Collections.singletonList(trackedEntityInstance), false, From 5f1a9552028f401d12a4f4e125dfa531a8029553 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 18 Jun 2021 17:10:25 +0200 Subject: [PATCH 088/308] [androsdk-1383] Visualization pojo --- .../core/visualization/Visualization.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java new file mode 100644 index 0000000000..e45225fe79 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.BaseIdentifiableObject; +import org.hisp.dhis.android.core.common.CoreObject; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_Visualization.Builder.class) +public abstract class Visualization extends BaseIdentifiableObject implements CoreObject { + + @Nullable + @JsonProperty() + public abstract String description(); + + @Nullable + @JsonProperty() + public abstract String displayDescription(); + + @Nullable + @JsonProperty() + public abstract String displayFormName(); + + public static Builder builder() { + return new $$AutoValue_Visualization.Builder(); + } + + public static Visualization create(Cursor cursor) { + return AutoValue_Visualization.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder extends BaseIdentifiableObject.Builder { + + public abstract Builder id(Long id); + + public abstract Builder description(String description); + + public abstract Builder displayDescription(String displayDescription); + + public abstract Builder displayFormName(String displayFormName); + + public abstract Visualization build(); + } +} \ No newline at end of file From 7d4a8d2d000da49595aa6006ca839aa88db457ec Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 22 Jun 2021 18:40:34 +0200 Subject: [PATCH 089/308] [ANDROSDK-1395] Adapt state propagation --- .../DataStatePropagatorIntegrationShould.java | 16 +- ...PayloadGeneratorMockIntegrationShould.java | 6 +- ...InstancePostCallRealIntegrationShould.java | 6 +- ...PayloadGeneratorMockIntegrationShould.java | 14 +- .../internal/DeletableStoreWithState.kt | 2 +- .../IdentifiableDataObjectStoreImpl.kt | 6 +- ...dentifiableDeletableDataObjectStoreImpl.kt | 2 +- .../arch/db/stores/internal/ObjectStore.kt | 4 + .../db/stores/internal/ObjectStoreImpl.kt | 5 + .../arch/db/stores/internal/StoreUtils.kt | 2 +- .../arch/db/stores/internal/StoreWithState.kt | 6 +- .../internal/IdentifiableDataHandlerImpl.kt | 2 +- ...dWriteWithUidDataObjectRepositoryImpl.java | 2 +- ...Propagator.java => DataStatePropagator.kt} | 37 +-- .../internal/DataStatePropagatorImpl.java | 218 ------------------ .../internal/DataStatePropagatorImpl.kt | 203 ++++++++++++++++ ...SetInstanceSummarySQLStatementBuilder.java | 2 +- .../internal/EnrollmentImportHandler.java | 194 ---------------- .../internal/EnrollmentImportHandler.kt | 161 +++++++++++++ .../enrollment/internal/EnrollmentStore.java | 3 + .../internal/EnrollmentStoreImpl.java | 13 ++ .../event/internal/EventImportHandler.java | 162 ------------- .../core/event/internal/EventImportHandler.kt | 126 ++++++++++ .../event/internal/EventPostStateManager.kt | 2 +- .../RelationshipCollectionRepository.java | 2 +- .../internal/RelationshipDeleteCall.java | 2 +- .../internal/LocalDbRepositoryImpl.java | 8 +- .../internal/StatePersistorHelper.kt | 2 +- .../TrackedEntityInstanceImportHandler.java | 171 -------------- .../TrackedEntityInstanceImportHandler.kt | 128 ++++++++++ .../internal/TrackedEntityInstanceStore.java | 3 + .../TrackedEntityInstanceStoreImpl.java | 14 ++ .../internal/JobReportEnrollmentHandler.kt | 2 +- .../internal/JobReportEventHandler.kt | 2 +- .../internal/JobReportTrackedEntityHandler.kt | 2 +- .../EnrollmentImportHandlerShould.java | 16 +- .../internal/EventImportHandlerShould.java | 20 +- ...ckedEntityInstanceImportHandlerShould.java | 8 +- 38 files changed, 746 insertions(+), 828 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/common/internal/{DataStatePropagator.java => DataStatePropagator.kt} (63%) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java index c2d1e6e51c..d9cce95215 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java @@ -131,17 +131,17 @@ public void reset_enrollment_and_event_states_if_uploading() throws D2Error { String eventUid2 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid1)); String eventUid3 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid2)); - enrollmentStore.setState(enrolmentUid1, State.UPLOADING); - eventStore.setState(eventUid1, State.UPLOADING); + enrollmentStore.setSyncState(enrolmentUid1, State.UPLOADING); + eventStore.setSyncState(eventUid1, State.UPLOADING); propagator.resetUploadingEnrollmentAndEventStates(teiUid); - assertThat(enrollmentStore.getState(enrolmentUid1)).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.getState(enrolmentUid2)).isEqualTo(State.TO_POST); + assertThat(enrollmentStore.getSyncState(enrolmentUid1)).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.getSyncState(enrolmentUid2)).isEqualTo(State.TO_POST); - assertThat(eventStore.getState(eventUid1)).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.getState(eventUid2)).isEqualTo(State.TO_POST); - assertThat(eventStore.getState(eventUid3)).isEqualTo(State.TO_POST); + assertThat(eventStore.getSyncState(eventUid1)).isEqualTo(State.TO_UPDATE); + assertThat(eventStore.getSyncState(eventUid2)).isEqualTo(State.TO_POST); + assertThat(eventStore.getSyncState(eventUid3)).isEqualTo(State.TO_POST); trackedEntityInstanceStore.delete(teiUid); } @@ -302,7 +302,7 @@ private String createEnrollmentWithState(State state, String teiUid) throws D2Er private String createEventWithState(State state, String enrolmentUid) throws D2Error { String eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)); - eventStore.setState(eventUid, state); + eventStore.setSyncState(eventUid, state); return eventUid; } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java index 3517f60a21..42718494be 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java @@ -110,9 +110,9 @@ public void delete_old_import_conflicts() { d2.eventModule().events().blockingUpload(); assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(3); - eventStore.setState(event1Id, State.TO_POST); - eventStore.setState(event2Id, State.TO_POST); - eventStore.setState(event3Id, State.TO_POST); + eventStore.setSyncState(event1Id, State.TO_POST); + eventStore.setSyncState(event2Id, State.TO_POST); + eventStore.setSyncState(event3Id, State.TO_POST); dhis2MockServer.enqueueMockResponse("imports/web_response_with_event_import_conflicts2.json"); d2.eventModule().events().blockingUpload(); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java index 5bda5fa910..4facca0205 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java @@ -382,7 +382,7 @@ public void post_new_relationship_to_client_created_tei() throws Exception { String teiBUid = uidGenerator.generate(); insertATei(teiBUid, teiA, geometry); - trackedEntityInstanceStore.setState(teiA.uid(), State.TO_POST); + trackedEntityInstanceStore.setSyncState(teiA.uid(), State.TO_POST); Relationship newRelationship = RelationshipHelper.teiToTeiRelationship(teiA.uid(), teiBUid, relationshipType.uid()); @@ -481,8 +481,8 @@ public void post_a_tei_and_delete_one_event() throws Exception { Event event = eventStore.selectFirst(); String eventUid = event.uid(); - trackedEntityInstanceStore.setState(tei.uid(), State.TO_UPDATE); - enrollmentStore.setState(enrollment.uid(), State.TO_UPDATE); + trackedEntityInstanceStore.setSyncState(tei.uid(), State.TO_UPDATE); + enrollmentStore.setSyncState(enrollment.uid(), State.TO_UPDATE); d2.eventModule().events().uid(eventUid).blockingDelete(); d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java index 95319a2df5..4e49c4d80c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java @@ -147,6 +147,7 @@ public void build_payload_with_the_enrollments_events_and_values_set_for_upload( public void build_payload_without_events_marked_as_error() { storeTrackedEntityInstance(); + EnrollmentStoreImpl.create(databaseAdapter).setSyncState("enrollment3Id", State.TO_POST); EnrollmentStoreImpl.create(databaseAdapter).setState("enrollment3Id", State.TO_POST); List> partitions = getPartitions(); @@ -184,11 +185,14 @@ public void delete_old_import_conflicts() { assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(3); + TrackedEntityInstanceStoreImpl.create(databaseAdapter).setSyncState("teiId", State.TO_POST); TrackedEntityInstanceStoreImpl.create(databaseAdapter).setState("teiId", State.TO_POST); + EnrollmentStoreImpl.create(databaseAdapter).setSyncState("enrollment1Id", State.TO_POST); EnrollmentStoreImpl.create(databaseAdapter).setState("enrollment1Id", State.TO_POST); + EnrollmentStoreImpl.create(databaseAdapter).setSyncState("enrollment2Id", State.TO_POST); EnrollmentStoreImpl.create(databaseAdapter).setState("enrollment2Id", State.TO_POST); - EventStoreImpl.create(databaseAdapter).setState("event1Id", State.TO_POST); - EventStoreImpl.create(databaseAdapter).setState("event2Id", State.TO_POST); + EventStoreImpl.create(databaseAdapter).setSyncState("event1Id", State.TO_POST); + EventStoreImpl.create(databaseAdapter).setSyncState("event2Id", State.TO_POST); dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_3.json"); d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); @@ -247,14 +251,14 @@ public void mark_payload_as_uploading() { List> partitions = getPartitions(); TrackedEntityInstance instance = TrackedEntityInstanceStoreImpl.create(databaseAdapter).selectFirst(); - assertThat(instance.state()).isEqualTo(State.UPLOADING); + assertThat(instance.syncState()).isEqualTo(State.UPLOADING); List enrollments = EnrollmentStoreImpl.create(databaseAdapter).selectAll(); for (Enrollment enrollment : enrollments) { if ("enrollment1Id".equals(enrollment.uid()) || "enrollment2Id".equals(enrollment.uid())) { - assertThat(enrollment.state()).isEqualTo(State.UPLOADING); + assertThat(enrollment.syncState()).isEqualTo(State.UPLOADING); } else { - assertThat(enrollment.state()).isNotEqualTo(State.UPLOADING); + assertThat(enrollment.syncState()).isNotEqualTo(State.UPLOADING); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt index 1d3b861041..51acd83338 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt @@ -31,6 +31,6 @@ import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State internal interface DeletableStoreWithState : StoreWithState { - fun setStateOrDelete(uid: String, state: State): HandleAction + fun setSyncStateOrDelete(uid: String, state: State): HandleAction fun setDeleted(uid: String): Int } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt index 49bf15e92a..c9af00eaf3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDataObjectStoreImpl.kt @@ -75,7 +75,7 @@ internal open class IdentifiableDataObjectStoreImpl( } } - override fun setState(uid: String, state: State): Int { + override fun setSyncState(uid: String, state: State): Int { compileStatements() setStateStatement!!.bind(1, state) @@ -86,7 +86,7 @@ internal open class IdentifiableDataObjectStoreImpl( return updatedRow } - override fun setState(uids: List, state: State): Int { + override fun setSyncState(uids: List, state: State): Int { val updates = ContentValues() updates.put(DataColumns.SYNC_STATE, state.toString()) val whereClause = WhereClauseBuilder() @@ -95,7 +95,7 @@ internal open class IdentifiableDataObjectStoreImpl( return databaseAdapter.update(tableName, updates, whereClause, null) } - override fun getState(uid: String): State? { + override fun getSyncState(uid: String): State? { compileStatements() val cursor = databaseAdapter.rawQuery(selectStateQuery, uid) var state: State? = null diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt index 31da56b7e3..2ffaa46fc5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt @@ -81,7 +81,7 @@ internal open class IdentifiableDeletableDataObjectStoreImpl( } } - override fun setStateOrDelete(uid: String, state: State): HandleAction { + override fun setSyncStateOrDelete(uid: String, state: State): HandleAction { var deleted = false if (state == State.SYNCED) { val whereClause = WhereClauseBuilder() diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStore.kt index a0186fb696..a52331d770 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStore.kt @@ -27,6 +27,8 @@ */ package org.hisp.dhis.android.core.arch.db.stores.internal +import android.content.ContentValues + internal interface ObjectStore : ReadableStore { @Throws(RuntimeException::class) fun selectStringColumnsWhereClause(column: String, clause: String): List @@ -40,6 +42,8 @@ internal interface ObjectStore : ReadableStore { fun deleteById(o: O): Boolean fun deleteWhere(clause: String): Boolean + fun updateWhere(updates: ContentValues, whereClause: String): Int + @Throws(RuntimeException::class) fun deleteWhereIfExists(whereClause: String) val isReady: Boolean diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStoreImpl.kt index fe093e8a7c..6f1dc4f166 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/ObjectStoreImpl.kt @@ -27,6 +27,7 @@ */ package org.hisp.dhis.android.core.arch.db.stores.internal +import android.content.ContentValues import android.database.Cursor import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilder @@ -125,6 +126,10 @@ internal open class ObjectStoreImpl internal constructor( return databaseAdapter.delete(builder.tableName, clause, null) > 0 } + override fun updateWhere(updates: ContentValues, whereClause: String): Int { + return databaseAdapter.update(builder.tableName, updates, whereClause, null) + } + @Throws(RuntimeException::class) @Suppress("TooGenericExceptionCaught") override fun deleteWhereIfExists(whereClause: String) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreUtils.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreUtils.kt index 2ec705e899..6baaea5a80 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreUtils.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreUtils.kt @@ -41,7 +41,7 @@ internal object StoreUtils { * @return the state from the ImportStatus */ @JvmStatic - fun getState(importStatus: ImportStatus): State { + fun getSyncState(importStatus: ImportStatus): State { return when (importStatus) { ImportStatus.ERROR -> State.ERROR ImportStatus.SUCCESS -> State.SYNCED diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreWithState.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreWithState.kt index 664dc871d8..1e71b169da 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreWithState.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/StoreWithState.kt @@ -30,8 +30,8 @@ package org.hisp.dhis.android.core.arch.db.stores.internal import org.hisp.dhis.android.core.common.State internal interface StoreWithState { - fun setState(uid: String, state: State): Int - fun setState(uids: List, state: State): Int - fun getState(uid: String): State? + fun setSyncState(uid: String, state: State): Int + fun setSyncState(uids: List, state: State): Int + fun getSyncState(uid: String): State? fun exists(uid: String): Boolean } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt index fed7651835..9bf523e715 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt @@ -137,7 +137,7 @@ internal abstract class IdentifiableDataHandlerImpl( private fun relationshipTransformer(): (O) -> O { return { o: O -> - val currentState = store.getState(o.uid()) + val currentState = store.getSyncState(o.uid()) if (currentState == State.RELATIONSHIP || currentState == null) { addRelationshipState(o) } else { diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java index 09a3629d6f..7a81425ab6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java @@ -101,7 +101,7 @@ public void blockingDelete() throws D2Error { store.delete(object.uid()); } else { store.setDeleted(object.uid()); - store.setState(object.uid(), State.TO_UPDATE); + store.setSyncState(object.uid(), State.TO_UPDATE); propagateState(object); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.java b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt similarity index 63% rename from core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.java rename to core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index a6385479a4..d6262d302b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -25,30 +25,35 @@ * (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.common.internal -package org.hisp.dhis.android.core.common.internal; +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.relationship.RelationshipItem; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue; +interface DataStatePropagator { -public interface DataStatePropagator { - void propagateEnrollmentUpdate(Enrollment enrollment); + fun propagateEnrollmentUpdate(enrollment: Enrollment?) - void propagateEventUpdate(Event event); + fun propagateEventUpdate(event: Event?) - void propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue dataValue); + fun propagateTrackedEntityDataValueUpdate(dataValue: TrackedEntityDataValue?) - void propagateTrackedEntityAttributeUpdate(TrackedEntityAttributeValue trackedEntityAttributeValue); + fun propagateTrackedEntityAttributeUpdate(trackedEntityAttributeValue: TrackedEntityAttributeValue?) - void propagateNoteCreation(Note note); + fun propagateNoteCreation(note: Note?) - void propagateRelationshipUpdate(RelationshipItem item); + fun propagateRelationshipUpdate(item: RelationshipItem?) - void resetUploadingEnrollmentAndEventStates(String trackedEntityInstanceUid); + fun resetUploadingEnrollmentAndEventStates(trackedEntityInstanceUid: String?) - void resetUploadingEventStates(String enrollmentUid); + fun resetUploadingEventStates(enrollmentUid: String?) + + fun propagateEnrollmentError(enrollmentUid: String?, state: State?) + + fun propagateTrackedEntityInstanceError(trackedEntityInstanceUid: String?, state: State?) } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java deleted file mode 100644 index 340df60862..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.internal; - -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.EventTableInfo; -import org.hisp.dhis.android.core.event.internal.EventStore; -import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.relationship.RelationshipItem; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; - -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -@Reusable -public final class DataStatePropagatorImpl implements DataStatePropagator { - - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final EnrollmentStore enrollmentStore; - private final EventStore eventStore; - - @Inject - DataStatePropagatorImpl(TrackedEntityInstanceStore trackedEntityInstanceStore, - EnrollmentStore enrollmentStore, - EventStore eventStore) { - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.enrollmentStore = enrollmentStore; - this.eventStore = eventStore; - } - - @Override - public void propagateEnrollmentUpdate(Enrollment enrollment) { - if (enrollment != null) { - setTeiStateForUpdate(enrollment.trackedEntityInstance()); - } - } - - @Override - public void propagateEventUpdate(Event event) { - if (event != null && event.enrollment() != null) { - Enrollment enrollment = setEnrollmentStateForUpdate(event.enrollment()); - propagateEnrollmentUpdate(enrollment); - } - } - - @Override - public void propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue dataValue) { - Event event = setEventStateForUpdate(dataValue.event()); - propagateEventUpdate(event); - } - - @Override - public void propagateTrackedEntityAttributeUpdate(TrackedEntityAttributeValue trackedEntityAttributeValue) { - setTeiStateForUpdate(trackedEntityAttributeValue.trackedEntityInstance()); - } - - @Override - public void propagateNoteCreation(Note note) { - if (note.noteType() == Note.NoteType.ENROLLMENT_NOTE) { - Enrollment enrollment = setEnrollmentStateForUpdate(note.enrollment()); - propagateEnrollmentUpdate(enrollment); - } else if (note.noteType() == Note.NoteType.EVENT_NOTE) { - Event event = setEventStateForUpdate(note.event()); - propagateEventUpdate(event); - } - } - - @Override - public void propagateRelationshipUpdate(RelationshipItem item) { - if (item != null) { - if (item.hasTrackedEntityInstance()) { - setTeiStateForUpdate(item.trackedEntityInstance().trackedEntityInstance()); - } else if (item.hasEnrollment()) { - Enrollment enrollment = setEnrollmentStateForUpdate(item.enrollment().enrollment()); - propagateEnrollmentUpdate(enrollment); - } else if (item.hasEvent()) { - Event event = setEventStateForUpdate(item.event().event()); - propagateEventUpdate(event); - } - } - } - - private TrackedEntityInstance setTeiStateForUpdate(String trackedEntityInstanceUid) { - TrackedEntityInstance instance = trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid); - if (instance != null) { - Date now = new Date(); - TrackedEntityInstance updatedTEI = instance.toBuilder() - .state(getStateForUpdate(instance.state())) - .lastUpdated(getMaxDate(instance.lastUpdated(), now)) - .lastUpdatedAtClient(getMaxDate(instance.lastUpdatedAtClient(), now)) - .build(); - trackedEntityInstanceStore.update(updatedTEI); - instance = updatedTEI; - } - return instance; - } - - private Enrollment setEnrollmentStateForUpdate(String enrollmentUid) { - Enrollment enrollment = enrollmentStore.selectByUid(enrollmentUid); - if (enrollment != null) { - Date now = new Date(); - Enrollment updatedEnrollment = enrollment.toBuilder() - .state(getStateForUpdate(enrollment.state())) - .lastUpdated(getMaxDate(enrollment.lastUpdated(), now)) - .lastUpdatedAtClient(getMaxDate(enrollment.lastUpdatedAtClient(), now)) - .build(); - enrollmentStore.update(updatedEnrollment); - enrollment = updatedEnrollment; - } - return enrollment; - } - - private Event setEventStateForUpdate(String eventUid) { - Event event = eventStore.selectByUid(eventUid); - if (event != null) { - Date now = new Date(); - Event updatedEvent = event.toBuilder() - .syncState(getStateForUpdate(event.state())) - .lastUpdated(getMaxDate(event.lastUpdated(), now)) - .lastUpdatedAtClient(getMaxDate(event.lastUpdatedAtClient(), now)) - .build(); - eventStore.update(updatedEvent); - event = updatedEvent; - } - return event; - } - - public void resetUploadingEnrollmentAndEventStates(String trackedEntityInstanceUid) { - if (trackedEntityInstanceUid == null) { - return; - } - - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, trackedEntityInstanceUid) - .build(); - List enrollments = enrollmentStore.selectWhere(whereClause); - - for (Enrollment enrollment : enrollments) { - if (State.UPLOADING.equals(enrollment.state())) { - enrollmentStore.setState(enrollment.uid(), State.TO_UPDATE); - resetUploadingEventStates(enrollment.uid()); - } - } - } - - public void resetUploadingEventStates(String enrollmentUid) { - if (enrollmentUid == null) { - return; - } - - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(EventTableInfo.Columns.ENROLLMENT, enrollmentUid) - .build(); - List events = eventStore.selectWhere(whereClause); - - for (Event event : events) { - if (State.UPLOADING.equals(event.state())) { - eventStore.setState(event.uid(), State.TO_UPDATE); - } - } - } - - private Date getMaxDate(Date existing, Date today) { - if (existing == null) { - return today; - } else if (today == null || existing.after(today)) { - return existing; - } else { - return today; - } - } - - private State getStateForUpdate(State existingState) { - if (State.TO_POST.equals(existingState) || State.RELATIONSHIP.equals(existingState)) { - return existingState; - } else { - return State.TO_UPDATE; - } - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt new file mode 100644 index 0000000000..0e90efc256 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.EventTableInfo +import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore +import java.util.* +import javax.inject.Inject + +@Reusable +internal class DataStatePropagatorImpl @Inject internal constructor( + private val trackedEntityInstanceStore: TrackedEntityInstanceStore, + private val enrollmentStore: EnrollmentStore, + private val eventStore: EventStore +) : DataStatePropagator { + + override fun propagateEnrollmentUpdate(enrollment: Enrollment?) { + if (enrollment != null) { + setTeiState(enrollment.trackedEntityInstance(), getStateForUpdate) + } + } + + override fun propagateEventUpdate(event: Event?) { + if (event?.enrollment() != null) { + val enrollment = setEnrollmentState(event.enrollment(), getStateForUpdate) + propagateEnrollmentUpdate(enrollment) + } + } + + override fun propagateTrackedEntityDataValueUpdate(dataValue: TrackedEntityDataValue?) { + val event = setEventState(dataValue!!.event(), getStateForUpdate) + propagateEventUpdate(event) + } + + override fun propagateTrackedEntityAttributeUpdate(trackedEntityAttributeValue: TrackedEntityAttributeValue?) { + setTeiState(trackedEntityAttributeValue!!.trackedEntityInstance(), getStateForUpdate) + } + + override fun propagateNoteCreation(note: Note?) { + if (note!!.noteType() == Note.NoteType.ENROLLMENT_NOTE) { + val enrollment = setEnrollmentState(note.enrollment(), getStateForUpdate) + propagateEnrollmentUpdate(enrollment) + } else if (note.noteType() == Note.NoteType.EVENT_NOTE) { + val event = setEventState(note.event(), getStateForUpdate) + propagateEventUpdate(event) + } + } + + override fun propagateRelationshipUpdate(item: RelationshipItem?) { + if (item != null) { + if (item.hasTrackedEntityInstance()) { + setTeiState(item.trackedEntityInstance()!!.trackedEntityInstance(), getStateForUpdate) + } else if (item.hasEnrollment()) { + val enrollment = setEnrollmentState(item.enrollment()!!.enrollment(), getStateForUpdate) + propagateEnrollmentUpdate(enrollment) + } else if (item.hasEvent()) { + val event = setEventState(item.event()!!.event(), getStateForUpdate) + propagateEventUpdate(event) + } + } + } + + private fun setTeiState(trackedEntityInstanceUid: String?, getState: (State?) -> State): TrackedEntityInstance? { + var instance = trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid!!) + if (instance != null) { + val now = Date() + val updatedTEI = instance.toBuilder() + .state(getState(instance.state())) + .lastUpdated(getMaxDate(instance.lastUpdated(), now)) + .lastUpdatedAtClient(getMaxDate(instance.lastUpdatedAtClient(), now)) + .build() + trackedEntityInstanceStore.update(updatedTEI) + instance = updatedTEI + } + return instance + } + + private fun setEnrollmentState(enrollmentUid: String?, getState: (State?) -> State): Enrollment? { + var enrollment = enrollmentStore.selectByUid(enrollmentUid!!) + if (enrollment != null) { + val now = Date() + val updatedEnrollment = enrollment.toBuilder() + .state(getState(enrollment.state())) + .lastUpdated(getMaxDate(enrollment.lastUpdated(), now)) + .lastUpdatedAtClient(getMaxDate(enrollment.lastUpdatedAtClient(), now)) + .build() + enrollmentStore.update(updatedEnrollment) + enrollment = updatedEnrollment + } + return enrollment + } + + private fun setEventState(eventUid: String?, getState: (State?) -> State): Event? { + var event = eventStore.selectByUid(eventUid!!) + if (event != null) { + val now = Date() + val updatedEvent = event.toBuilder() + .syncState(getState(event.state())) + .lastUpdated(getMaxDate(event.lastUpdated(), now)) + .lastUpdatedAtClient(getMaxDate(event.lastUpdatedAtClient(), now)) + .build() + eventStore.update(updatedEvent) + event = updatedEvent + } + return event + } + + override fun resetUploadingEnrollmentAndEventStates(trackedEntityInstanceUid: String?) { + if (trackedEntityInstanceUid == null) { + return + } + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, trackedEntityInstanceUid) + .build() + val enrollments = enrollmentStore.selectWhere(whereClause) + for (enrollment in enrollments) { + if (State.UPLOADING == enrollment.syncState()) { + enrollmentStore.setSyncState(enrollment.uid(), State.TO_UPDATE) + resetUploadingEventStates(enrollment.uid()) + } + } + } + + override fun resetUploadingEventStates(enrollmentUid: String?) { + if (enrollmentUid == null) { + return + } + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EventTableInfo.Columns.ENROLLMENT, enrollmentUid) + .build() + val events = eventStore.selectWhere(whereClause) + for (event in events) { + if (State.UPLOADING == event.syncState()) { + eventStore.setSyncState(event.uid(), State.TO_UPDATE) + } + } + } + + override fun propagateEnrollmentError(enrollmentUid: String?, state: State?) { + val enrollment = setEnrollmentState(enrollmentUid) { state!! } + propagateTrackedEntityInstanceError(enrollment?.trackedEntityInstance(), state) + } + + override fun propagateTrackedEntityInstanceError(trackedEntityInstanceUid: String?, state: State?) { + setTeiState(trackedEntityInstanceUid) { state!! } + } + + private fun getMaxDate(existing: Date?, today: Date?): Date? { + return if (existing == null) { + today + } else if (today == null || existing.after(today)) { + existing + } else { + today + } + } + + private val getStateForUpdate = { existingState: State? -> + if (State.TO_POST == existingState || State.RELATIONSHIP == existingState) { + existingState + } else { + State.TO_UPDATE + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java index ec467e2f34..ddebf516cc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java @@ -44,7 +44,7 @@ public class DataSetInstanceSummarySQLStatementBuilder extends DataSetInstanceSQ private static final String DS_LIST_TABLE_ALIAS = "dslist"; private static final String DS_INSTANCE_ALIAS = "dsinstance"; - private static final String STATE = DataColumns.SYNC_STATE; + private static final String STATE = STATE_ALIAS; private static final String SELECT_STATE_ORDERING = " MAX(CASE " + "WHEN " + STATE + " IN ('" + State.SYNCED + "','" + State.SYNCED_VIA_SMS + "') THEN 1 " + diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java deleted file mode 100644 index bcd6b9a61d..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.enrollment.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; -import org.hisp.dhis.android.core.common.DataColumns; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.common.internal.DataStatePropagator; -import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; -import org.hisp.dhis.android.core.event.internal.EventImportHandler; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary; -import org.hisp.dhis.android.core.imports.internal.EventImportSummaries; -import org.hisp.dhis.android.core.imports.internal.ImportConflict; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.note.NoteTableInfo; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -import static org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getState; - -@Reusable -public class EnrollmentImportHandler { - private final EnrollmentStore enrollmentStore; - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final IdentifiableObjectStore noteStore; - private final EventImportHandler eventImportHandler; - private final TrackerImportConflictStore trackerImportConflictStore; - private final TrackerImportConflictParser trackerImportConflictParser; - private final DataStatePropagator dataStatePropagator; - - @Inject - public EnrollmentImportHandler(@NonNull EnrollmentStore enrollmentStore, - @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull IdentifiableObjectStore noteStore, - @NonNull EventImportHandler eventImportHandler, - @NonNull TrackerImportConflictStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser, - @NonNull DataStatePropagator dataStatePropagator) { - this.enrollmentStore = enrollmentStore; - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.noteStore = noteStore; - this.eventImportHandler = eventImportHandler; - this.trackerImportConflictStore = trackerImportConflictStore; - this.trackerImportConflictParser = trackerImportConflictParser; - this.dataStatePropagator = dataStatePropagator; - } - - public void handleEnrollmentImportSummary(List enrollmentImportSummaries, - String teiUid) { - if (enrollmentImportSummaries == null) { - return; - } - - State parentState = null; - for (EnrollmentImportSummary enrollmentImportSummary : enrollmentImportSummaries) { - if (enrollmentImportSummary == null) { - break; - } - - State state = getState(enrollmentImportSummary.status()); - - HandleAction handleAction = null; - - if (enrollmentImportSummary.reference() != null) { - handleAction = enrollmentStore.setStateOrDelete(enrollmentImportSummary.reference(), state); - if (state == State.ERROR || state == State.WARNING) { - parentState = parentState == State.ERROR ? State.ERROR : state; - dataStatePropagator.resetUploadingEventStates(enrollmentImportSummary.reference()); - } - - trackerImportConflictStore.deleteEnrollmentConflicts(enrollmentImportSummary.reference()); - } - - if (handleAction != HandleAction.Delete) { - handleNoteImportSummary(enrollmentImportSummary.reference(), state); - - storeEnrollmentImportConflicts(enrollmentImportSummary, teiUid); - - handleEventImportSummaries(enrollmentImportSummary, teiUid); - } - } - - updateParentState(parentState, teiUid); - } - - private void handleEventImportSummaries(EnrollmentImportSummary enrollmentImportSummary, - String teiUid) { - - if (enrollmentImportSummary.events() != null) { - EventImportSummaries eventImportSummaries = enrollmentImportSummary.events(); - - if (eventImportSummaries.importSummaries() != null) { - eventImportHandler.handleEventImportSummaries( - eventImportSummaries.importSummaries(), - enrollmentImportSummary.reference(), - teiUid); - - } - } - } - - private void handleNoteImportSummary(String enrollmentUid, State state) { - State newNoteState = state.equals(State.SYNCED) ? State.SYNCED : State.TO_POST; - String whereClause = new WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.SYNC_STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) - .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build(); - List notes = noteStore.selectWhere(whereClause); - for (Note note : notes) { - noteStore.update(note.toBuilder().syncState(newNoteState).build()); - } - } - - private void storeEnrollmentImportConflicts(EnrollmentImportSummary enrollmentImportSummary, - String teiUid) { - List trackerImportConflicts = new ArrayList<>(); - if (enrollmentImportSummary.description() != null) { - trackerImportConflicts.add(getConflictBuilder(teiUid, enrollmentImportSummary) - .conflict(enrollmentImportSummary.description()) - .displayDescription(enrollmentImportSummary.description()) - .value(enrollmentImportSummary.reference()) - .build()); - } - - if (enrollmentImportSummary.conflicts() != null) { - for (ImportConflict importConflict : enrollmentImportSummary.conflicts()) { - trackerImportConflicts.add(trackerImportConflictParser - .getEnrollmentConflict(importConflict, getConflictBuilder(teiUid, enrollmentImportSummary))); - } - } - - for (TrackerImportConflict trackerImportConflict : trackerImportConflicts) { - trackerImportConflictStore.insert(trackerImportConflict); - } - } - - - private void updateParentState(State parentState, String teiUid) { - if (parentState != null && teiUid != null) { - trackedEntityInstanceStore.setState(teiUid, parentState); - } - } - - private TrackerImportConflict.Builder getConflictBuilder(String trackedEntityInstanceUid, - EnrollmentImportSummary enrollmentImportSummary) { - return TrackerImportConflict.builder() - .trackedEntityInstance(trackedEntityInstanceUid) - .enrollment(enrollmentImportSummary.reference()) - .tableReference(EnrollmentTableInfo.TABLE_INFO.name()) - .status(enrollmentImportSummary.status()) - .created(new Date()); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt new file mode 100644 index 0000000000..a540e1cc48 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2004-2021, 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.core.enrollment.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper +import org.hisp.dhis.android.core.common.DataColumns +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo +import org.hisp.dhis.android.core.event.internal.EventImportHandler +import org.hisp.dhis.android.core.imports.TrackerImportConflict +import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore +import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.note.NoteTableInfo +import java.util.* +import javax.inject.Inject + +@Reusable +internal class EnrollmentImportHandler @Inject constructor( + private val enrollmentStore: EnrollmentStore, + private val noteStore: IdentifiableObjectStore, + private val eventImportHandler: EventImportHandler, + private val trackerImportConflictStore: TrackerImportConflictStore, + private val trackerImportConflictParser: TrackerImportConflictParser, + private val dataStatePropagator: DataStatePropagator +) { + + fun handleEnrollmentImportSummary( + enrollmentImportSummaries: List?, + teiUid: String + ) { + if (enrollmentImportSummaries == null) { + return + } + var parentState: State = State.SYNCED + + enrollmentImportSummaries.filterNotNull().forEach { enrollmentImportSummary -> + val syncState = getSyncState(enrollmentImportSummary.status()) + + enrollmentImportSummary.reference()?.let { enrollmentUid -> + val handleAction = enrollmentStore.setSyncStateOrDelete(enrollmentUid, syncState) + + if (syncState == State.ERROR || syncState == State.WARNING) { + parentState = if (parentState == State.ERROR) State.ERROR else syncState + dataStatePropagator.resetUploadingEventStates(enrollmentUid) + } + trackerImportConflictStore.deleteEnrollmentConflicts(enrollmentUid) + + if (handleAction !== HandleAction.Delete) { + handleNoteImportSummary(enrollmentUid, syncState) + storeEnrollmentImportConflicts(enrollmentImportSummary, teiUid) + handleEventImportSummaries(enrollmentImportSummary, teiUid) + } + } + } + + updateParentState(parentState, teiUid) + } + + private fun handleEventImportSummaries( + enrollmentImportSummary: EnrollmentImportSummary, + teiUid: String + ) { + enrollmentImportSummary.events()?.importSummaries()?.let { importSummaries -> + eventImportHandler.handleEventImportSummaries( + importSummaries, + enrollmentImportSummary.reference()!!, + teiUid + ) + } + } + + private fun handleNoteImportSummary(enrollmentUid: String, state: State) { + val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST + val whereClause = WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.SYNC_STATE, EnumHelper.asStringList(*State.uploadableStatesIncludingError()) + ) + .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build() + val notes = noteStore.selectWhere(whereClause) + for (note in notes) { + noteStore.update(note.toBuilder().syncState(newNoteState).build()) + } + } + + private fun storeEnrollmentImportConflicts( + enrollmentImportSummary: EnrollmentImportSummary, + teiUid: String + ) { + val trackerImportConflicts: MutableList = ArrayList() + + if (enrollmentImportSummary.description() != null) { + trackerImportConflicts.add( + getConflictBuilder(teiUid, enrollmentImportSummary) + .conflict(enrollmentImportSummary.description()) + .displayDescription(enrollmentImportSummary.description()) + .value(enrollmentImportSummary.reference()) + .build() + ) + } + + enrollmentImportSummary.conflicts()?.forEach { importConflict -> + trackerImportConflicts.add( + trackerImportConflictParser + .getEnrollmentConflict(importConflict, getConflictBuilder(teiUid, enrollmentImportSummary)) + ) + } + + trackerImportConflicts.forEach { trackerImportConflictStore.insert(it) } + } + + private fun updateParentState(parentState: State, teiUid: String?) { + if (parentState != State.SYNCED && teiUid != null) { + dataStatePropagator.propagateTrackedEntityInstanceError(teiUid, parentState) + } + } + + private fun getConflictBuilder( + trackedEntityInstanceUid: String, + enrollmentImportSummary: EnrollmentImportSummary + ): TrackerImportConflict.Builder { + return TrackerImportConflict.builder() + .trackedEntityInstance(trackedEntityInstanceUid) + .enrollment(enrollmentImportSummary.reference()) + .tableReference(EnrollmentTableInfo.TABLE_INFO.name()) + .status(enrollmentImportSummary.status()) + .created(Date()) + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java index 04f4fc9159..4cb7d33a9d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.enrollment.internal; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.Enrollment; import java.util.List; @@ -39,4 +40,6 @@ public interface EnrollmentStore extends IdentifiableDeletableDataObjectStore> queryEnrollmentsToPost(); List queryMissingRelationshipsUids(); + + int setState(String uid, State state); } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java index 452a6718ea..b046554fb6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.enrollment.internal; +import android.content.ContentValues; import android.database.Cursor; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; @@ -37,6 +38,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStoreImpl; import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.DataColumns; +import org.hisp.dhis.android.core.common.IdentifiableColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.Enrollment; import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; @@ -106,6 +108,17 @@ public List queryMissingRelationshipsUids() { return selectUidsWhere(whereRelationshipsClause); } + @Override + public int setState(String uid, State state) { + ContentValues updates = new ContentValues(); + updates.put(DataColumns.STATE, state.toString()); + String whereClause = new WhereClauseBuilder() + .appendKeyStringValue(IdentifiableColumns.UID, uid) + .build(); + + return updateWhere(updates, whereClause); + } + private void addEnrollmentToMap(Map> enrollmentMap, Enrollment enrollment) { if (enrollmentMap.get(enrollment.trackedEntityInstance()) == null) { enrollmentMap.put(enrollment.trackedEntityInstance(), new ArrayList<>()); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java deleted file mode 100644 index 23fa4dbf27..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.event.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; -import org.hisp.dhis.android.core.event.EventTableInfo; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.EventImportSummary; -import org.hisp.dhis.android.core.imports.internal.ImportConflict; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; -import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEventHandler; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -import static org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getState; - -@Reusable -public class EventImportHandler { - private final EventStore eventStore; - private final EnrollmentStore enrollmentStore; - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final TrackerImportConflictStore trackerImportConflictStore; - private final TrackerImportConflictParser trackerImportConflictParser; - private final JobReportEventHandler jobReportEventHandler; - - @Inject - public EventImportHandler(@NonNull EventStore eventStore, - @NonNull EnrollmentStore enrollmentStore, - @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull TrackerImportConflictStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser, - JobReportEventHandler jobReportEventHandler) { - this.eventStore = eventStore; - this.enrollmentStore = enrollmentStore; - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.trackerImportConflictStore = trackerImportConflictStore; - this.trackerImportConflictParser = trackerImportConflictParser; - this.jobReportEventHandler = jobReportEventHandler; - } - - public void handleEventImportSummaries(List eventImportSummaries, - String enrollmentUid, - String teiUid) { - if (eventImportSummaries == null) { - return; - } - - State parentState = null; - for (EventImportSummary eventImportSummary : eventImportSummaries) { - if (eventImportSummary == null) { - break; - } - - State state = getState(eventImportSummary.status()); - - HandleAction handleAction = null; - - if (eventImportSummary.reference() != null) { - handleAction = eventStore.setStateOrDelete(eventImportSummary.reference(), state); - if (state == State.ERROR || state == State.WARNING) { - parentState = parentState == State.ERROR ? State.ERROR : state; - } - - trackerImportConflictStore.deleteEventConflicts(eventImportSummary.reference()); - } - - if (handleAction != HandleAction.Delete) { - jobReportEventHandler.handleEventNotes(eventImportSummary.reference(), state); - - storeEventImportConflicts(eventImportSummary, teiUid, enrollmentUid); - } - } - - updateParentState(parentState, teiUid, enrollmentUid); - } - - private void storeEventImportConflicts(EventImportSummary importSummary, - String teiUid, - String enrollmentUid) { - List trackerImportConflicts = new ArrayList<>(); - if (importSummary.description() != null) { - trackerImportConflicts.add(getConflictBuilder(teiUid, enrollmentUid, importSummary) - .conflict(importSummary.description()) - .displayDescription(importSummary.description()) - .value(importSummary.reference()) - .build()); - } - - if (importSummary.conflicts() != null) { - for (ImportConflict importConflict : importSummary.conflicts()) { - trackerImportConflicts.add(trackerImportConflictParser - .getEventConflict(importConflict, getConflictBuilder(teiUid, enrollmentUid, importSummary))); - } - - } - - for (TrackerImportConflict trackerImportConflict : trackerImportConflicts) { - trackerImportConflictStore.insert(trackerImportConflict); - } - } - - private void updateParentState(State parentState, String teiUid, String enrollmentUid) { - if (parentState != null) { - if (teiUid != null) { - trackedEntityInstanceStore.setState(teiUid, parentState); - } - if (enrollmentUid != null) { - enrollmentStore.setState(enrollmentUid, parentState); - } - } - } - - private TrackerImportConflict.Builder getConflictBuilder(String trackedEntityInstanceUid, - String enrollmentUid, - EventImportSummary eventImportSummary) { - return TrackerImportConflict.builder() - .trackedEntityInstance(trackedEntityInstanceUid) - .enrollment(enrollmentUid) - .event(eventImportSummary.reference()) - .tableReference(EventTableInfo.TABLE_INFO.name()) - .status(eventImportSummary.status()) - .created(new Date()); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt new file mode 100644 index 0000000000..4d90e68fcd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2021, 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.core.event.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.event.EventTableInfo +import org.hisp.dhis.android.core.imports.TrackerImportConflict +import org.hisp.dhis.android.core.imports.internal.EventImportSummary +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore +import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEventHandler +import java.util.* +import javax.inject.Inject + +@Reusable +internal class EventImportHandler @Inject constructor( + private val eventStore: EventStore, + private val trackerImportConflictStore: TrackerImportConflictStore, + private val trackerImportConflictParser: TrackerImportConflictParser, + private val jobReportEventHandler: JobReportEventHandler, + private val dataStatePropagator: DataStatePropagator +) { + + fun handleEventImportSummaries( + eventImportSummaries: List?, + enrollmentUid: String?, + teiUid: String? + ) { + var parentState: State = State.SYNCED + + eventImportSummaries?.filterNotNull()?.forEach { eventImportSummary -> + val state = getSyncState(eventImportSummary.status()) + + eventImportSummary.reference()?.let { eventUid -> + val handleAction = eventStore.setSyncStateOrDelete(eventUid, state) + if (state == State.ERROR || state == State.WARNING) { + parentState = if (parentState == State.ERROR) State.ERROR else state + } + trackerImportConflictStore.deleteEventConflicts(eventUid) + + if (handleAction !== HandleAction.Delete) { + jobReportEventHandler.handleEventNotes(eventUid, state) + storeEventImportConflicts(eventImportSummary, teiUid, enrollmentUid) + } + } + } + + updateParentState(parentState, enrollmentUid) + } + + private fun storeEventImportConflicts( + importSummary: EventImportSummary, + teiUid: String?, + enrollmentUid: String? + ) { + val trackerImportConflicts: MutableList = ArrayList() + + if (importSummary.description() != null) { + trackerImportConflicts.add( + getConflictBuilder(teiUid, enrollmentUid, importSummary) + .conflict(importSummary.description()) + .displayDescription(importSummary.description()) + .value(importSummary.reference()) + .build() + ) + } + + importSummary.conflicts()?.forEach { importConflict -> + trackerImportConflicts.add( + trackerImportConflictParser + .getEventConflict(importConflict, getConflictBuilder(teiUid, enrollmentUid, importSummary)) + ) + } + + trackerImportConflicts.forEach { trackerImportConflictStore.insert(it) } + } + + private fun updateParentState(parentState: State, enrollmentUid: String?) { + if (parentState != State.SYNCED && enrollmentUid != null) { + dataStatePropagator.propagateEnrollmentError(enrollmentUid, parentState) + } + } + + private fun getConflictBuilder( + trackedEntityInstanceUid: String?, + enrollmentUid: String?, + eventImportSummary: EventImportSummary + ): TrackerImportConflict.Builder { + return TrackerImportConflict.builder() + .trackedEntityInstance(trackedEntityInstanceUid) + .enrollment(enrollmentUid) + .event(eventImportSummary.reference()) + .tableReference(EventTableInfo.TABLE_INFO.name()) + .status(eventImportSummary.status()) + .created(Date()) + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostStateManager.kt index 09b6636b06..a7ea02c9e0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostStateManager.kt @@ -41,7 +41,7 @@ internal class EventPostStateManager @Inject internal constructor( fun markObjectsAs(events: Collection, forcedState: State?) where T : ObjectWithUidInterface, T : DataObject { for (e in events) { - eventStore.setState(e.uid(), DataStateHelper.forcedOrOwn(e, forcedState)) + eventStore.setSyncState(e.uid(), DataStateHelper.forcedOrOwn(e, forcedState)) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 0914122663..61200edb63 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -131,7 +131,7 @@ public String blockingAdd(Relationship relationship) throws D2Error { } StoreWithState fromStore = storeSelector.getElementStore(from); - State fromState = fromStore.getState(from.elementUid()); + State fromState = fromStore.getSyncState(from.elementUid()); if (isUpdatableState(fromState)) { relationshipHandler.handle(relationshipWithUid, r -> r.toBuilder() diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java index eaa7478353..eda9b06bac 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java @@ -122,7 +122,7 @@ private Completable deleteRelationship(Relationship229Compatible relationship) { } else { // TODO Implement better handling // The relationship is marked as error, but there is no handling in the TEI. The TEI is being posted - relationshipStore.setState(relationship.uid(), State.ERROR); + relationshipStore.setSyncState(relationship.uid(), State.ERROR); } return httpResponse; } diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java index 704dc08749..e38aaf3d89 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java @@ -267,20 +267,20 @@ private Single> getEventsForEnrollment(String enrollmentUid) { @Override public Completable updateEventSubmissionState(String eventUid, State state) { - return Completable.fromAction(() -> eventStore.setState(eventUid, state)); + return Completable.fromAction(() -> eventStore.setSyncState(eventUid, state)); } @Override public Completable updateEnrollmentSubmissionState(TrackedEntityInstance tei, State state) { return Completable.fromAction(() -> { Enrollment enrollment = TrackedEntityInstanceInternalAccessor.accessEnrollments(tei).get(0); - enrollmentStore.setState(enrollment.uid(), state); - trackedEntityInstanceStore.setState(enrollment.trackedEntityInstance(), state); + enrollmentStore.setSyncState(enrollment.uid(), state); + trackedEntityInstanceStore.setSyncState(enrollment.trackedEntityInstance(), state); List events = EnrollmentInternalAccessor.accessEvents(enrollment); if (events != null && !events.isEmpty()) { List eventUids = UidsHelper.getUidsList(events); - eventStore.setState(eventUids, state); + eventStore.setSyncState(eventUids, state); } }); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt index 0e546fc2eb..4b20ff179d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt @@ -57,7 +57,7 @@ internal class StatePersistorHelper @Inject internal constructor() { fun persistStates(map: Map>, store: IdentifiableDeletableDataObjectStore<*>) { for ((key, value) in map) { - store.setState(value, key) + store.setSyncState(value, key) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java deleted file mode 100644 index 394da30eea..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.trackedentity.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.common.internal.DataStatePropagator; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummaries; -import org.hisp.dhis.android.core.imports.internal.ImportConflict; -import org.hisp.dhis.android.core.imports.internal.TEIImportSummary; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.relationship.Relationship; -import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository; -import org.hisp.dhis.android.core.relationship.RelationshipHelper; -import org.hisp.dhis.android.core.relationship.internal.RelationshipDHISVersionManager; -import org.hisp.dhis.android.core.relationship.internal.RelationshipStore; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -import static org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getState; - -@Reusable -public final class TrackedEntityInstanceImportHandler { - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final EnrollmentImportHandler enrollmentImportHandler; - private final TrackerImportConflictStore trackerImportConflictStore; - private final TrackerImportConflictParser trackerImportConflictParser; - private final RelationshipStore relationshipStore; - private final DataStatePropagator dataStatePropagator; - private final RelationshipDHISVersionManager relationshipDHISVersionManager; - private final RelationshipCollectionRepository relationshipRepository; - - @Inject - TrackedEntityInstanceImportHandler(@NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull EnrollmentImportHandler enrollmentImportHandler, - @NonNull TrackerImportConflictStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser, - @NonNull RelationshipStore relationshipStore, - @NonNull DataStatePropagator dataStatePropagator, - @NonNull RelationshipDHISVersionManager relationshipDHISVersionManager, - @NonNull RelationshipCollectionRepository relationshipRepository) { - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.enrollmentImportHandler = enrollmentImportHandler; - this.trackerImportConflictStore = trackerImportConflictStore; - this.trackerImportConflictParser = trackerImportConflictParser; - this.relationshipStore = relationshipStore; - this.dataStatePropagator = dataStatePropagator; - this.relationshipDHISVersionManager = relationshipDHISVersionManager; - this.relationshipRepository = relationshipRepository; - } - - public void handleTrackedEntityInstanceImportSummaries(List teiImportSummaries) { - if (teiImportSummaries == null) { - return; - } - - for (TEIImportSummary teiImportSummary : teiImportSummaries) { - if (teiImportSummary == null) { - break; - } - - State state = getState(teiImportSummary.status()); - HandleAction handleAction = null; - - if (teiImportSummary.reference() != null) { - handleAction = trackedEntityInstanceStore.setStateOrDelete(teiImportSummary.reference(), state); - - if (state.equals(State.ERROR) || state.equals(State.WARNING)) { - dataStatePropagator.resetUploadingEnrollmentAndEventStates(teiImportSummary.reference()); - setRelationshipsState(teiImportSummary.reference(), State.TO_UPDATE); - } else { - setRelationshipsState(teiImportSummary.reference(), State.SYNCED); - } - - trackerImportConflictStore.deleteTrackedEntityConflicts(teiImportSummary.reference()); - } - - if (handleAction != HandleAction.Delete) { - storeTEIImportConflicts(teiImportSummary); - - if (teiImportSummary.enrollments() != null) { - EnrollmentImportSummaries importEnrollment = teiImportSummary.enrollments(); - - enrollmentImportHandler.handleEnrollmentImportSummary( - importEnrollment.importSummaries(), - teiImportSummary.reference()); - } - } - } - } - - private void storeTEIImportConflicts(TEIImportSummary teiImportSummary) { - List trackerImportConflicts = new ArrayList<>(); - if (teiImportSummary.description() != null) { - trackerImportConflicts.add(getConflictBuilder(teiImportSummary) - .conflict(teiImportSummary.description()) - .displayDescription(teiImportSummary.description()) - .value(teiImportSummary.reference()) - .build()); - } - - if (teiImportSummary.conflicts() != null) { - for (ImportConflict importConflict : teiImportSummary.conflicts()) { - trackerImportConflicts.add(trackerImportConflictParser - .getTrackedEntityInstanceConflict(importConflict, getConflictBuilder(teiImportSummary))); - } - } - - for (TrackerImportConflict trackerImportConflict : trackerImportConflicts) { - trackerImportConflictStore.insert(trackerImportConflict); - } - } - - private void setRelationshipsState(String trackedEntityInstanceUid, State state) { - List dbRelationships = - relationshipRepository.getByItem(RelationshipHelper.teiItem(trackedEntityInstanceUid), true); - - List ownedRelationships = relationshipDHISVersionManager - .getOwnedRelationships(dbRelationships, trackedEntityInstanceUid); - - for (Relationship relationship : ownedRelationships) { - relationshipStore.setStateOrDelete(relationship.uid(), state); - } - } - - private TrackerImportConflict.Builder getConflictBuilder(TEIImportSummary teiImportSummary) { - return TrackerImportConflict.builder() - .trackedEntityInstance(teiImportSummary.reference()) - .tableReference(TrackedEntityInstanceTableInfo.TABLE_INFO.name()) - .status(teiImportSummary.status()) - .created(new Date()); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt new file mode 100644 index 0000000000..a909641b91 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler +import org.hisp.dhis.android.core.imports.TrackerImportConflict +import org.hisp.dhis.android.core.imports.internal.TEIImportSummary +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser +import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore +import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.internal.RelationshipDHISVersionManager +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo +import java.util.* +import javax.inject.Inject + +@Reusable +internal class TrackedEntityInstanceImportHandler @Inject internal constructor( + private val trackedEntityInstanceStore: TrackedEntityInstanceStore, + private val enrollmentImportHandler: EnrollmentImportHandler, + private val trackerImportConflictStore: TrackerImportConflictStore, + private val trackerImportConflictParser: TrackerImportConflictParser, + private val relationshipStore: RelationshipStore, + private val dataStatePropagator: DataStatePropagator, + private val relationshipDHISVersionManager: RelationshipDHISVersionManager, + private val relationshipRepository: RelationshipCollectionRepository +) { + + fun handleTrackedEntityInstanceImportSummaries(teiImportSummaries: List?) { + if (teiImportSummaries == null) { + return + } + + teiImportSummaries.filterNotNull().forEach { teiImportSummary -> + val state = getSyncState(teiImportSummary.status()) + + teiImportSummary.reference()?.let { teiUid -> + val handleAction = trackedEntityInstanceStore.setSyncStateOrDelete(teiUid, state) + + if (state == State.ERROR || state == State.WARNING) { + dataStatePropagator.resetUploadingEnrollmentAndEventStates(teiUid) + setRelationshipsState(teiUid, State.TO_UPDATE) + } else { + setRelationshipsState(teiUid, State.SYNCED) + } + trackerImportConflictStore.deleteTrackedEntityConflicts(teiUid) + + if (handleAction !== HandleAction.Delete) { + storeTEIImportConflicts(teiImportSummary) + + teiImportSummary.enrollments()?.importSummaries().let { + enrollmentImportHandler.handleEnrollmentImportSummary(it, teiUid) + } + } + } + } + } + + private fun storeTEIImportConflicts(teiImportSummary: TEIImportSummary) { + val trackerImportConflicts: MutableList = ArrayList() + if (teiImportSummary.description() != null) { + trackerImportConflicts.add( + getConflictBuilder(teiImportSummary) + .conflict(teiImportSummary.description()) + .displayDescription(teiImportSummary.description()) + .value(teiImportSummary.reference()) + .build() + ) + } + teiImportSummary.conflicts()?.forEach { importConflict -> + trackerImportConflicts.add( + trackerImportConflictParser + .getTrackedEntityInstanceConflict(importConflict, getConflictBuilder(teiImportSummary)) + ) + } + + trackerImportConflicts.forEach { trackerImportConflictStore.insert(it) } + } + + private fun setRelationshipsState(trackedEntityInstanceUid: String?, state: State) { + val dbRelationships = + relationshipRepository.getByItem(RelationshipHelper.teiItem(trackedEntityInstanceUid), true) + val ownedRelationships = relationshipDHISVersionManager + .getOwnedRelationships(dbRelationships, trackedEntityInstanceUid) + for (relationship in ownedRelationships) { + relationshipStore.setSyncStateOrDelete(relationship.uid()!!, state) + } + } + + private fun getConflictBuilder(teiImportSummary: TEIImportSummary): TrackerImportConflict.Builder { + return TrackerImportConflict.builder() + .trackedEntityInstance(teiImportSummary.reference()) + .tableReference(TrackedEntityInstanceTableInfo.TABLE_INFO.name()) + .status(teiImportSummary.status()) + .created(Date()) + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java index e800667f2f..56ae26c19a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.trackedentity.internal; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; import java.util.List; @@ -42,4 +43,6 @@ public interface TrackedEntityInstanceStore extends IdentifiableDeletableDataObj List querySyncedTrackedEntityInstanceUids(); List queryMissingRelationshipsUids(); + + int setState(String uid, State state); } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java index 7ec1b2b4c0..745b5a48a6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.trackedentity.internal; +import android.content.ContentValues; + import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; @@ -35,6 +37,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStoreImpl; import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.DataColumns; +import org.hisp.dhis.android.core.common.IdentifiableColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo; @@ -102,6 +105,17 @@ public List queryMissingRelationshipsUids() { return selectUidsWhere(whereRelationshipsClause); } + @Override + public int setState(String uid, State state) { + ContentValues updates = new ContentValues(); + updates.put(DataColumns.STATE, state.toString()); + String whereClause = new WhereClauseBuilder() + .appendKeyStringValue(IdentifiableColumns.UID, uid) + .build(); + + return updateWhere(updates, whereClause); + } + public static TrackedEntityInstanceStore create(DatabaseAdapter databaseAdapter) { SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl( TrackedEntityInstanceTableInfo.TABLE_INFO.name(), diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt index a28d828f4f..ad4ef00fd9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt @@ -42,7 +42,7 @@ internal class JobReportEnrollmentHandler @Inject internal constructor( ) : JobReportTypeHandler() { override fun handleObject(uid: String, state: State) { - enrollmentStore.setState(uid, state) + enrollmentStore.setSyncState(uid, state) conflictStore.deleteEnrollmentConflicts(uid) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index aedcf41259..f046190a0c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -60,7 +60,7 @@ internal class JobReportEventHandler @Inject internal constructor( } override fun handleObject(uid: String, state: State) { - eventStore.setState(uid, state) + eventStore.setSyncState(uid, state) conflictStore.deleteEventConflicts(uid) handleEventNotes(uid, state) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt index db1c618626..b701d317b5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -42,7 +42,7 @@ internal class JobReportTrackedEntityHandler @Inject internal constructor( ) : JobReportTypeHandler() { override fun handleObject(uid: String, state: State) { - trackedEntityStore.setState(uid, state) + trackedEntityStore.setSyncState(uid, state) conflictStore.deleteTrackedEntityConflicts(uid) } diff --git a/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java index 70a608967e..a4f3beeef1 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java @@ -39,7 +39,6 @@ import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -64,9 +63,6 @@ public class EnrollmentImportHandlerShould { @Mock private EnrollmentStore enrollmentStore; - @Mock - private TrackedEntityInstanceStore trackedEntityInstanceStore; - @Mock private IdentifiableObjectStore noteStore; @@ -98,15 +94,15 @@ public class EnrollmentImportHandlerShould { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - enrollmentImportHandler = new EnrollmentImportHandler(enrollmentStore, trackedEntityInstanceStore, noteStore, + enrollmentImportHandler = new EnrollmentImportHandler(enrollmentStore, noteStore, eventImportHandler, trackerImportConflictStore, trackerImportConflictParser, dataStatePropagator); } @Test public void do_nothing_when_passing_null_arguments() throws Exception { - enrollmentImportHandler.handleEnrollmentImportSummary(null, null); + enrollmentImportHandler.handleEnrollmentImportSummary(null, "tei_uid"); - verify(enrollmentStore, never()).setStateOrDelete(anyString(), any(State.class)); + verify(enrollmentStore, never()).setSyncStateOrDelete(anyString(), any(State.class)); } @Test @@ -116,7 +112,7 @@ public void invoke_set_state_when_enrollment_import_summary_is_success_with_refe enrollmentImportHandler.handleEnrollmentImportSummary(Collections.singletonList(importSummary), "test_tei_uid"); - verify(enrollmentStore, times(1)).setStateOrDelete("test_enrollment_uid", State.SYNCED); + verify(enrollmentStore, times(1)).setSyncStateOrDelete("test_enrollment_uid", State.SYNCED); } @Test @@ -126,7 +122,7 @@ public void invoke_set_state_when_enrollment_import_summary_is_error_with_refer enrollmentImportHandler.handleEnrollmentImportSummary(Collections.singletonList(importSummary), "test_tei_uid"); - verify(enrollmentStore, times(1)).setStateOrDelete("test_enrollment_uid", State.ERROR); + verify(enrollmentStore, times(1)).setSyncStateOrDelete("test_enrollment_uid", State.ERROR); } @Test @@ -141,7 +137,7 @@ public void invoke_set_state_and_handle_event_import_summaries_when_enrollment_i enrollmentImportHandler.handleEnrollmentImportSummary(Collections.singletonList(importSummary), "test_tei_uid"); - verify(enrollmentStore, times(1)).setStateOrDelete("test_enrollment_uid", State.SYNCED); + verify(enrollmentStore, times(1)).setSyncStateOrDelete("test_enrollment_uid", State.SYNCED); verify(eventImportHandler, times(1)).handleEventImportSummaries( eq(eventSummaries), anyString(), anyString() ); diff --git a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java index 7a2f7e42a6..54854265af 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.event.internal; import org.hisp.dhis.android.core.common.State; +import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; import org.hisp.dhis.android.core.imports.ImportStatus; import org.hisp.dhis.android.core.imports.internal.EventImportSummary; @@ -60,12 +61,6 @@ public class EventImportHandlerShould { @Mock private EventStore eventStore; - @Mock - private EnrollmentStore enrollmentStore; - - @Mock - private TrackedEntityInstanceStore trackedEntityInstanceStore; - @Mock private TrackerImportConflictStore trackerImportConflictStore; @@ -75,6 +70,9 @@ public class EventImportHandlerShould { @Mock private TrackerImportConflictParser trackerImportConflictParser; + @Mock + private DataStatePropagator dataStatePropagator; + // object to test private EventImportHandler eventImportHandler; @@ -84,15 +82,15 @@ public void setUp() throws Exception { when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); - eventImportHandler = new EventImportHandler(eventStore, enrollmentStore, trackedEntityInstanceStore, - trackerImportConflictStore, trackerImportConflictParser, jobReportEventHandler); + eventImportHandler = new EventImportHandler(eventStore, trackerImportConflictStore, + trackerImportConflictParser, jobReportEventHandler, dataStatePropagator); } @Test public void do_nothing_when_passing_null_argument() throws Exception { eventImportHandler.handleEventImportSummaries(null, null, null); - verify(eventStore, never()).setStateOrDelete(anyString(), any(State.class)); + verify(eventStore, never()).setSyncStateOrDelete(anyString(), any(State.class)); } @Test @@ -103,7 +101,7 @@ public void invoke_set_state_after_handle_event_import_summaries_with_success_st eventImportHandler.handleEventImportSummaries(Collections.singletonList(importSummary), "test_enrollment_uid", "test_tei_uid"); - verify(eventStore, times(1)).setStateOrDelete("test_event_uid", State.SYNCED); + verify(eventStore, times(1)).setSyncStateOrDelete("test_event_uid", State.SYNCED); } @Test @@ -114,6 +112,6 @@ public void invoke_set_state_after_handle_event_import_summaries_with_error_stat eventImportHandler.handleEventImportSummaries(Collections.singletonList(importSummary), "test_enrollment_uid", "test_tei_uid"); - verify(eventStore, times(1)).setStateOrDelete("test_event_uid", State.ERROR); + verify(eventStore, times(1)).setSyncStateOrDelete("test_event_uid", State.ERROR); } } \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java index dd9e88acb1..49103d0a56 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java @@ -112,7 +112,7 @@ public void setUp() throws Exception { public void do_nothing_when_passing_null_argument() throws Exception { trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries(null); - verify(trackedEntityInstanceStore, never()).setStateOrDelete(anyString(), any(State.class)); + verify(trackedEntityInstanceStore, never()).setSyncStateOrDelete(anyString(), any(State.class)); } @Test @@ -124,7 +124,7 @@ public void setStatus_shouldUpdateTrackedEntityInstanceStatusSuccess() throws Ex Collections.singletonList(importSummary) ); - verify(trackedEntityInstanceStore, times(1)).setStateOrDelete("test_tei_uid", State.SYNCED); + verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.SYNCED); } @Test @@ -136,7 +136,7 @@ public void setStatus_shouldUpdateTrackedEntityInstanceStatusError() throws Exce Collections.singletonList(importSummary) ); - verify(trackedEntityInstanceStore, times(1)).setStateOrDelete("test_tei_uid", State.ERROR); + verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.ERROR); } @Test @@ -151,7 +151,7 @@ public void update_tracker_entity_instance_status_success_status_and_handle_impo Collections.singletonList(importSummary) ); - verify(trackedEntityInstanceStore, times(1)).setStateOrDelete("test_tei_uid", State.SYNCED); + verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.SYNCED); verify(enrollmentImportHandler, times(1)).handleEnrollmentImportSummary( eq(enrollmentSummaries), anyString()); } From ea5e68e95f7695ba49445f3dbcdeb1c67873a397 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 23 Jun 2021 12:36:03 +0200 Subject: [PATCH 090/308] [ANDROSDK-1395] Temp --- .../internal/EnrollmentImportHandler.kt | 41 +++++++++---------- .../core/event/internal/EventImportHandler.kt | 18 +++----- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt index a540e1cc48..496acc043f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt @@ -60,46 +60,51 @@ internal class EnrollmentImportHandler @Inject constructor( fun handleEnrollmentImportSummary( enrollmentImportSummaries: List?, teiUid: String - ) { - if (enrollmentImportSummaries == null) { - return - } - var parentState: State = State.SYNCED + ): State { + var globalState: State = State.SYNCED - enrollmentImportSummaries.filterNotNull().forEach { enrollmentImportSummary -> + enrollmentImportSummaries?.filterNotNull()?.forEach { enrollmentImportSummary -> val syncState = getSyncState(enrollmentImportSummary.status()) enrollmentImportSummary.reference()?.let { enrollmentUid -> val handleAction = enrollmentStore.setSyncStateOrDelete(enrollmentUid, syncState) - if (syncState == State.ERROR || syncState == State.WARNING) { - parentState = if (parentState == State.ERROR) State.ERROR else syncState - dataStatePropagator.resetUploadingEventStates(enrollmentUid) - } trackerImportConflictStore.deleteEnrollmentConflicts(enrollmentUid) if (handleAction !== HandleAction.Delete) { handleNoteImportSummary(enrollmentUid, syncState) storeEnrollmentImportConflicts(enrollmentImportSummary, teiUid) - handleEventImportSummaries(enrollmentImportSummary, teiUid) + + if (syncState == State.ERROR || syncState == State.WARNING) { + globalState = if (globalState == State.ERROR) State.ERROR else syncState + dataStatePropagator.resetUploadingEventStates(enrollmentUid) + } else { + + } + + val eventState = handleEventImportSummaries(enrollmentImportSummary, teiUid) + + if (globalState == State.ERROR || globalState == State.WARNING) { + globalState = if (globalState == State.ERROR) State.ERROR else eventState + } } } } - updateParentState(parentState, teiUid) + return globalState } private fun handleEventImportSummaries( enrollmentImportSummary: EnrollmentImportSummary, teiUid: String - ) { - enrollmentImportSummary.events()?.importSummaries()?.let { importSummaries -> + ): State { + return enrollmentImportSummary.events()?.importSummaries()?.let { importSummaries -> eventImportHandler.handleEventImportSummaries( importSummaries, enrollmentImportSummary.reference()!!, teiUid ) - } + } ?: State.SYNCED } private fun handleNoteImportSummary(enrollmentUid: String, state: State) { @@ -141,12 +146,6 @@ internal class EnrollmentImportHandler @Inject constructor( trackerImportConflicts.forEach { trackerImportConflictStore.insert(it) } } - private fun updateParentState(parentState: State, teiUid: String?) { - if (parentState != State.SYNCED && teiUid != null) { - dataStatePropagator.propagateTrackedEntityInstanceError(teiUid, parentState) - } - } - private fun getConflictBuilder( trackedEntityInstanceUid: String, enrollmentImportSummary: EnrollmentImportSummary diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt index 4d90e68fcd..3e74eac83a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt @@ -31,7 +31,6 @@ import dagger.Reusable import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State -import org.hisp.dhis.android.core.common.internal.DataStatePropagator import org.hisp.dhis.android.core.event.EventTableInfo import org.hisp.dhis.android.core.imports.TrackerImportConflict import org.hisp.dhis.android.core.imports.internal.EventImportSummary @@ -46,16 +45,15 @@ internal class EventImportHandler @Inject constructor( private val eventStore: EventStore, private val trackerImportConflictStore: TrackerImportConflictStore, private val trackerImportConflictParser: TrackerImportConflictParser, - private val jobReportEventHandler: JobReportEventHandler, - private val dataStatePropagator: DataStatePropagator + private val jobReportEventHandler: JobReportEventHandler ) { fun handleEventImportSummaries( eventImportSummaries: List?, enrollmentUid: String?, teiUid: String? - ) { - var parentState: State = State.SYNCED + ): State { + var globalState: State = State.SYNCED eventImportSummaries?.filterNotNull()?.forEach { eventImportSummary -> val state = getSyncState(eventImportSummary.status()) @@ -63,7 +61,7 @@ internal class EventImportHandler @Inject constructor( eventImportSummary.reference()?.let { eventUid -> val handleAction = eventStore.setSyncStateOrDelete(eventUid, state) if (state == State.ERROR || state == State.WARNING) { - parentState = if (parentState == State.ERROR) State.ERROR else state + globalState = if (globalState == State.ERROR) State.ERROR else state } trackerImportConflictStore.deleteEventConflicts(eventUid) @@ -74,7 +72,7 @@ internal class EventImportHandler @Inject constructor( } } - updateParentState(parentState, enrollmentUid) + return globalState } private fun storeEventImportConflicts( @@ -104,12 +102,6 @@ internal class EventImportHandler @Inject constructor( trackerImportConflicts.forEach { trackerImportConflictStore.insert(it) } } - private fun updateParentState(parentState: State, enrollmentUid: String?) { - if (parentState != State.SYNCED && enrollmentUid != null) { - dataStatePropagator.propagateEnrollmentError(enrollmentUid, parentState) - } - } - private fun getConflictBuilder( trackedEntityInstanceUid: String?, enrollmentUid: String?, From 2949e9da2e044f1eaba0c8f88c3de4506db470b3 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:29:04 +0200 Subject: [PATCH 091/308] [androsdk-1383] Add visualization enums --- .../visualization/DataDimensionItemType.kt | 39 ++++++++++++++++ .../core/visualization/DigitGroupSeparator.kt | 34 ++++++++++++++ .../core/visualization/DisplayDensity.kt | 35 ++++++++++++++ .../visualization/HideEmptyItemStrategy.kt | 40 ++++++++++++++++ .../core/visualization/VisualizationType.kt | 46 +++++++++++++++++++ 5 files changed, 194 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt new file mode 100644 index 0000000000..c883f4dd91 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class DataDimensionItemType { + INDICATOR, + DATA_ELEMENT, + DATA_ELEMENT_OPERAND, + REPORTING_RATE, + PROGRAM_INDICATOR, + PROGRAM_DATA_ELEMENT, + PROGRAM_ATTRIBUTE, + VALIDATION_RULE +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt new file mode 100644 index 0000000000..dcd0ab8dd8 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class DigitGroupSeparator { + COMMA, + SPACE, + NONE +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt new file mode 100644 index 0000000000..de46799620 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class DisplayDensity { + COMFORTABLE, + NORMAL, + COMPACT, + NONE +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt new file mode 100644 index 0000000000..c4bc87875d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class HideEmptyItemStrategy { + NONE, + BEFORE_FIRST, + AFTER_LAST, + BEFORE_FIRST_AFTER_LAST, + ALL; + + open fun isHide(): Boolean { + return this == BEFORE_FIRST || this == AFTER_LAST || this == BEFORE_FIRST_AFTER_LAST || this == ALL + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt new file mode 100644 index 0000000000..c91c0e9bc7 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class VisualizationType { + COLUMN, + STACKED_COLUMN, + BAR, + STACKED_BAR, + LINE, + AREA, + PIE, + RADAR, + GAUGE, + YEAR_OVER_YEAR_LINE, + YEAR_OVER_YEAR_COLUMN, + SINGLE_VALUE, + PIVOT_TABLE, + SCATTER, + BUBBLE +} From ae5a1c4de00dfffc2a36097b0da72548ec7e97c8 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:29:27 +0200 Subject: [PATCH 092/308] [androsdk-1383] Add visualization enum column adapters --- .../DigitGroupSeparatorColumnAdapter.kt | 36 +++++++++++++++++++ .../internal/DisplayDensityColumnAdapter.kt | 36 +++++++++++++++++++ .../HideEmptyItemStrategyColumnAdapter.kt | 36 +++++++++++++++++++ .../VisualizationTypeColumnAdapter.kt | 36 +++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt new file mode 100644 index 0000000000..8a284a38c3 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.DigitGroupSeparator + +class DigitGroupSeparatorColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return DigitGroupSeparator::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt new file mode 100644 index 0000000000..defcefe168 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.DisplayDensity + +class DisplayDensityColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return DisplayDensity::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt new file mode 100644 index 0000000000..f48303e1e0 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.HideEmptyItemStrategy + +class HideEmptyItemStrategyColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return HideEmptyItemStrategy::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt new file mode 100644 index 0000000000..58b7e16b5a --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.VisualizationType + +class VisualizationTypeColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return VisualizationType::class.java + } +} From 872735ce701c599f08b4cce78180e4af67dc0e9c Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:29:49 +0200 Subject: [PATCH 093/308] [androsdk-1383] Add CategoryDimension and DataDimensionItem --- .../core/visualization/CategoryDimension.java | 79 ++++++++++++ .../core/visualization/DataDimensionItem.java | 114 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java new file mode 100644 index 0000000000..41aa0be768 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUid; + +import java.util.List; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_CategoryDimension.Builder.class) +public abstract class CategoryDimension implements CoreObject { + + @Nullable + @JsonProperty() + public abstract ObjectWithUid category(); + + @Nullable + @JsonProperty() + public abstract List categoryOptions(); + + public static Builder builder() { + return new $$AutoValue_CategoryDimension.Builder(); + } + + public static CategoryDimension create(Cursor cursor) { + return AutoValue_CategoryDimension.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder { + + public abstract Builder id(Long id); + + public abstract Builder category(ObjectWithUid category); + + public abstract Builder categoryOptions(List categoryOptions); + + public abstract CategoryDimension build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java new file mode 100644 index 0000000000..2cdf523cc6 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUid; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_DataDimensionItem.Builder.class) +public abstract class DataDimensionItem implements CoreObject { + + @Nullable + @JsonProperty() + public abstract DataDimensionItemType dataDimensionItemType(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid indicator(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid dataElement(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid dataElementOperand(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid reportingRate(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid programIndicator(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid programDataElement(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid programAttribute(); + + + public static Builder builder() { + return new $$AutoValue_DataDimensionItem.Builder(); + } + + public static DataDimensionItem create(Cursor cursor) { + return AutoValue_DataDimensionItem.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder { + + public abstract Builder id(Long id); + + public abstract Builder dataDimensionItemType(DataDimensionItemType dataDimensionItemType); + + public abstract Builder indicator(ObjectWithUid indicator); + + public abstract Builder dataElement(ObjectWithUid dataElement); + + public abstract Builder dataElementOperand(ObjectWithUid dataElementOperand); + + public abstract Builder reportingRate(ObjectWithUid reportingRate); + + public abstract Builder programIndicator(ObjectWithUid programIndicator); + + public abstract Builder programDataElement(ObjectWithUid programDataElement); + + public abstract Builder programAttribute(ObjectWithUid programAttribute); + + public abstract DataDimensionItem build(); + } +} \ No newline at end of file From 86de6d39a5b59477858f1a387de374f9fba6c9e6 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:30:05 +0200 Subject: [PATCH 094/308] [androsdk-1383] Extend visualization pojo --- .../core/visualization/Visualization.java | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index e45225fe79..fb17049b68 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -35,10 +35,21 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DigitGroupSeparatorColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DisplayDensityColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.HideEmptyItemStrategyColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.VisualizationTypeColumnAdapter; import org.hisp.dhis.android.core.common.BaseIdentifiableObject; import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUid; +import org.hisp.dhis.android.core.common.RelativePeriod; + +import java.util.HashMap; +import java.util.List; @AutoValue @JsonDeserialize(builder = $$AutoValue_Visualization.Builder.class) @@ -56,6 +67,145 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @JsonProperty() public abstract String displayFormName(); + @Nullable + @JsonProperty() + @ColumnAdapter(VisualizationTypeColumnAdapter.class) + public abstract VisualizationType type(); + + @Nullable + @JsonProperty() + public abstract Boolean hideTitle(); + + @Nullable + @JsonProperty() + public abstract Boolean hideSubtitle(); + + @Nullable + @JsonProperty() + public abstract Boolean hideEmptyColumns(); + + @Nullable + @JsonProperty() + public abstract Boolean hideEmptyRows(); + + @Nullable + @JsonProperty() + @ColumnAdapter(HideEmptyItemStrategyColumnAdapter.class) + public abstract HideEmptyItemStrategy hideEmptyRowItems(); + + @Nullable + @JsonProperty() + public abstract Boolean hideLegend(); + + @Nullable + @JsonProperty() + public abstract Boolean showHierarchy(); + + @Nullable + @JsonProperty() + public abstract Boolean rowTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean rowSubTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean colTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean colSubTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean showDimensionLabels(); + + @Nullable + @JsonProperty() + public abstract Boolean percentStackedValues(); + + @Nullable + @JsonProperty() + public abstract Boolean noSpaceBetweenColumns(); + + @Nullable + @JsonProperty() + public abstract Boolean skipRounding(); + + @Nullable + @JsonProperty() + @ColumnAdapter(DisplayDensityColumnAdapter.class) + public abstract DisplayDensity displayDensity(); + + @Nullable + @JsonProperty() + @ColumnAdapter(DigitGroupSeparatorColumnAdapter.class) + public abstract DigitGroupSeparator digitGroupSeparator(); + + @Nullable + @JsonProperty() + public abstract HashMap relativePeriods(); + + @Nullable + @JsonProperty() + public abstract List categoryDimensions(); + + @Nullable + @JsonProperty() + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List filterDimensions(); + + @Nullable + @JsonProperty() + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List rowDimensions(); + + @Nullable + @JsonProperty() + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List columnDimensions(); + + @Nullable + @JsonProperty() + public abstract List dataDimensionItems(); + + @Nullable + @JsonProperty() + public abstract List organisationUnitLevels(); + + @Nullable + @JsonProperty() + public abstract Boolean userOrganisationUnit(); + + @Nullable + @JsonProperty() + public abstract Boolean userOrganisationUnitChildren(); + + @Nullable + @JsonProperty() + public abstract Boolean userOrganisationUnitGrandChildren(); + + @Nullable + @JsonProperty() + public abstract List organisationUnits(); + + @Nullable + @JsonProperty() + public abstract List columns(); + + @Nullable + @JsonProperty() + public abstract List periods(); + + @Nullable + @JsonProperty() + public abstract List filters(); + + @Nullable + @JsonProperty() + public abstract List rows(); + public static Builder builder() { return new $$AutoValue_Visualization.Builder(); } @@ -78,6 +228,72 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder relativePeriods); + + public abstract Builder categoryDimension(CategoryDimension categoryDimension); + + public abstract Builder filterDimensions(List filterDimensions); + + public abstract Builder rowDimensions(List rowDimensions); + + public abstract Builder columnDimensions(List columnDimensions); + + public abstract Builder dataDimensionItems(List dataDimensionItems); + + public abstract Builder organisationUnitLevels(List organisationUnitLevels); + + public abstract Builder userOrganisationUnit(Boolean userOrganisationUnit); + + public abstract Builder userOrganisationUnitChildren(Boolean userOrganisationUnitChildren); + + public abstract Builder userOrganisationUnitGrandChildren(Boolean userOrganisationUnitGrandChildren); + + public abstract Builder organisationUnits(List organisationUnits); + + public abstract Builder columns(List columns); + + public abstract Builder periods(List periods); + + public abstract Builder filters(List filters); + + public abstract Builder rows(List rows); + public abstract Visualization build(); } } \ No newline at end of file From e99e485c349d3518e7fc8ff1ee786b900c3561b1 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 17:39:55 +0200 Subject: [PATCH 095/308] [androsdk-1383] Add column adapters needed for Visualizations --- .../CategoryDimensionListColumnAdapter.kt | 47 ++++++++++++++ .../internal/IntegerListColumnAdapter.kt | 46 +++++++++++++ .../JSONObjectHashMapColumnAdapter.kt | 65 +++++++++++++++++++ .../ObjectWithUidListColumnAdapter.kt | 47 ++++++++++++++ .../internal/RelativePeriodsColumnAdapter.kt | 47 ++++++++++++++ .../DataDimensionItemTypeColumnAdapter.kt | 36 ++++++++++ ...oreDataDimensionItemListColumnAdapter.java | 37 +++++++++++ 7 files changed, 325 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt new file mode 100644 index 0000000000..5a6053c9fd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.visualization.CategoryDimension + +internal class CategoryDimensionListColumnAdapter : JSONObjectListColumnAdapter() { + override fun getObjectClass(): Class> { + return ArrayList().javaClass + } + + override fun serialize(o: List?): String? = CategoryDimensionListColumnAdapter.serialize(o) + + companion object { + fun serialize(o: List?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt new file mode 100644 index 0000000000..8880c8d478 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory + +internal class IntegerListColumnAdapter : JSONObjectListColumnAdapter() { + override fun getObjectClass(): Class> { + return ArrayList().javaClass + } + + override fun serialize(o: List?): String? = IntegerListColumnAdapter.serialize(o) + + companion object { + fun serialize(o: List?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt new file mode 100644 index 0000000000..7630eb8bec --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import android.content.ContentValues +import android.database.Cursor +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.JsonMappingException +import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory + +internal abstract class JSONObjectHashMapColumnAdapter : ColumnTypeAdapter> { + protected abstract fun getObjectClass(): Class> + + override fun fromCursor(cursor: Cursor, columnName: String): HashMap { + val columnIndex = cursor.getColumnIndex(columnName) + val str = cursor.getString(columnIndex) + return try { + ObjectMapperFactory.objectMapper().readValue(str, getObjectClass()) + } catch (e: JsonProcessingException) { + hashMapOf() + } catch (e: JsonMappingException) { + hashMapOf() + } catch (e: IllegalArgumentException) { + hashMapOf() + } catch (e: IllegalStateException) { + hashMapOf() + } + } + + override fun toContentValues(contentValues: ContentValues, columnName: String, o: HashMap?) { + try { + contentValues.put(columnName, serialize(o)) + } catch (e: JsonProcessingException) { + e.printStackTrace() + } + } + + abstract fun serialize(o: HashMap?): String? +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt new file mode 100644 index 0000000000..da0d49fef9 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.common.ObjectWithUid + +internal class ObjectWithUidListColumnAdapter : JSONObjectListColumnAdapter() { + override fun getObjectClass(): Class> { + return ArrayList().javaClass + } + + override fun serialize(o: List?): String? = ObjectWithUidListColumnAdapter.serialize(o) + + companion object { + fun serialize(o: List?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt new file mode 100644 index 0000000000..e9048ac470 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.common.RelativePeriod + +internal class RelativePeriodsColumnAdapter : JSONObjectHashMapColumnAdapter() { + override fun getObjectClass(): Class> { + return HashMap().javaClass + } + + override fun serialize(o: HashMap?): String? = RelativePeriodsColumnAdapter.serialize(o) + + companion object { + fun serialize(o: HashMap?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt new file mode 100644 index 0000000000..db0f93899e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.DataDimensionItemType + +class DataDimensionItemTypeColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return DataDimensionItemType::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java new file mode 100644 index 0000000000..58c76cfcbe --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.ignore.internal; + +import org.hisp.dhis.android.core.visualization.DataDimensionItem; + +import java.util.List; + +public final class IgnoreDataDimensionItemListColumnAdapter + extends IgnoreColumnAdapter> { +} \ No newline at end of file From 1d78a25dab93057439157c13e220ee4e3c20ed36 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 17:40:31 +0200 Subject: [PATCH 096/308] [androsdk-1383] Add adapters to pojos --- .../core/visualization/CategoryDimension.java | 5 +++++ .../core/visualization/DataDimensionItem.java | 11 +++++++++++ .../core/visualization/Visualization.java | 16 +++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java index 41aa0be768..d3a806144d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java @@ -35,8 +35,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.identifiable.internal.ObjectWithUidColumnAdapter; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; @@ -48,10 +51,12 @@ public abstract class CategoryDimension implements CoreObject { @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid category(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List categoryOptions(); public static Builder builder() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java index 2cdf523cc6..6195a38ccc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java @@ -35,8 +35,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DataDimensionItemTypeColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.identifiable.internal.ObjectWithUidColumnAdapter; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; @@ -46,34 +49,42 @@ public abstract class DataDimensionItem implements CoreObject { @Nullable @JsonProperty() + @ColumnAdapter(DataDimensionItemTypeColumnAdapter.class) public abstract DataDimensionItemType dataDimensionItemType(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid indicator(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid dataElement(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid dataElementOperand(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid reportingRate(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programIndicator(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programDataElement(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programAttribute(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index fb17049b68..f227ee9e1c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -38,11 +38,16 @@ import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.CategoryDimensionListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.IntegerListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.RelativePeriodsColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DigitGroupSeparatorColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DisplayDensityColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.HideEmptyItemStrategyColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.VisualizationTypeColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreDataDimensionItemListColumnAdapter; import org.hisp.dhis.android.core.common.BaseIdentifiableObject; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; @@ -145,10 +150,12 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() + @ColumnAdapter(RelativePeriodsColumnAdapter.class) public abstract HashMap relativePeriods(); @Nullable @JsonProperty() + @ColumnAdapter(CategoryDimensionListColumnAdapter.class) public abstract List categoryDimensions(); @Nullable @@ -168,10 +175,12 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() + @ColumnAdapter(IgnoreDataDimensionItemListColumnAdapter.class) public abstract List dataDimensionItems(); @Nullable @JsonProperty() + @ColumnAdapter(IntegerListColumnAdapter.class) public abstract List organisationUnitLevels(); @Nullable @@ -188,22 +197,27 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List organisationUnits(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List columns(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List periods(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List filters(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List rows(); public static Builder builder() { @@ -266,7 +280,7 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder relativePeriods); - public abstract Builder categoryDimension(CategoryDimension categoryDimension); + public abstract Builder categoryDimensions(List categoryDimensions); public abstract Builder filterDimensions(List filterDimensions); From ef4d083a9646120b1433bd83d9e7e6b4538b6f5f Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 30 Jun 2021 07:54:11 +0200 Subject: [PATCH 097/308] [ANDROSDK-1395] Finish merging develop --- ...PayloadGeneratorMockIntegrationShould.java | 505 ------------------ ...stPayloadGeneratorMockIntegrationShould.kt | 26 +- .../internal/BaseDatabaseOpenHelper.java | 2 +- .../internal/EnrollmentImportHandler.java | 220 -------- .../event/internal/EventImportHandler.java | 173 ------ .../internal/TEIWebResponseHandler.java | 8 +- .../TrackedEntityInstanceImportHandler.java | 199 ------- ...ckedEntityInstanceImportHandlerShould.java | 4 +- 8 files changed, 22 insertions(+), 1115 deletions(-) delete mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java deleted file mode 100644 index 4e49c4d80c..0000000000 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.java +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.trackedentity.internal; - -import com.google.common.collect.Lists; - -import org.hisp.dhis.android.core.arch.call.executors.internal.D2CallExecutor; -import org.hisp.dhis.android.core.arch.helpers.UidsHelper; -import org.hisp.dhis.android.core.common.ObjectWithUid; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.data.relationship.RelationshipSamples; -import org.hisp.dhis.android.core.data.trackedentity.TrackedEntityDataValueSamples; -import org.hisp.dhis.android.core.data.trackedentity.TrackedEntityInstanceSamples; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.EnrollmentInternalAccessor; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStoreImpl; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.internal.EventStoreImpl; -import org.hisp.dhis.android.core.maintenance.D2Error; -import org.hisp.dhis.android.core.maintenance.internal.ForeignKeyCleanerImpl; -import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.note.NoteCreateProjection; -import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; -import org.hisp.dhis.android.core.organisationunit.internal.OrganisationUnitStore; -import org.hisp.dhis.android.core.program.Program; -import org.hisp.dhis.android.core.program.ProgramStage; -import org.hisp.dhis.android.core.program.internal.ProgramStageStore; -import org.hisp.dhis.android.core.relationship.RelationshipConstraintType; -import org.hisp.dhis.android.core.relationship.RelationshipItem; -import org.hisp.dhis.android.core.relationship.RelationshipItemTrackedEntityInstance; -import org.hisp.dhis.android.core.relationship.RelationshipType; -import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStoreImpl; -import org.hisp.dhis.android.core.relationship.internal.RelationshipStoreImpl; -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeStore; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityType; -import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestMetadataEnqueable; -import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; -import org.junit.After; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static com.google.common.truth.Truth.assertThat; - -@RunWith(D2JunitRunner.class) -public class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould extends BaseMockIntegrationTestMetadataEnqueable { - - private static TrackedEntityInstancePostPayloadGenerator payloadGenerator; - private static TrackedEntityInstanceStore teiStore; - - private final String teiId = "teiId"; - private final String enrollment1Id = "enrollment1Id"; - private final String enrollment2Id = "enrollment2Id"; - private final String enrollment3Id = "enrollment3Id"; - private final String event1Id = "event1Id"; - private final String event2Id = "event2Id"; - private final String event3Id = "event3Id"; - - @After - public void tearDown() throws D2Error { - d2.wipeModule().wipeData(); - } - - @BeforeClass - public static void setUpClass() throws Exception { - BaseMockIntegrationTestMetadataEnqueable.setUpClass(); - payloadGenerator = objects.d2DIComponent.trackedEntityInstancePostPayloadGenerator(); - teiStore = TrackedEntityInstanceStoreImpl.create(d2.databaseAdapter()); - } - - @Test - public void build_payload_with_different_enrollments() { - storeTrackedEntityInstance(); - - List> partitions = getPartitions(); - - assertThat(partitions.size()).isEqualTo(1); - assertThat(partitions.get(0).size()).isEqualTo(1); - for (TrackedEntityInstance instance : partitions.get(0)) { - assertThat(getEnrollments(instance).size()).isEqualTo(2); - for (Enrollment enrollment : getEnrollments(instance)) { - assertThat(getEvents(enrollment).size()).isEqualTo(1); - for (Event event : getEvents(enrollment)) { - assertThat(event.trackedEntityDataValues().size()).isEqualTo(1); - } - } - } - } - - private List> getPartitions() { - return payloadGenerator.getTrackedEntityInstancesPartitions(teiStore.queryTrackedEntityInstancesToSync()); - } - - @Test - public void build_payload_with_the_enrollments_events_and_values_set_for_upload() { - storeTrackedEntityInstance(); - - List> partitions = getPartitions(); - - assertThat(partitions.size()).isEqualTo(1); - assertThat(partitions.get(0).size()).isEqualTo(1); - for (TrackedEntityInstance instance : partitions.get(0)) { - assertThat(getEnrollments(instance).size()).isEqualTo(2); - for (Enrollment enrollment : getEnrollments(instance)) { - assertThat(getEvents(enrollment).size()).isEqualTo(1); - for (Event event : getEvents(enrollment)) { - assertThat(event.trackedEntityDataValues().size()).isEqualTo(1); - } - } - } - } - - @Test - public void build_payload_without_events_marked_as_error() { - storeTrackedEntityInstance(); - - EnrollmentStoreImpl.create(databaseAdapter).setSyncState("enrollment3Id", State.TO_POST); - EnrollmentStoreImpl.create(databaseAdapter).setState("enrollment3Id", State.TO_POST); - List> partitions = getPartitions(); - - assertThat(partitions.size()).isEqualTo(1); - assertThat(partitions.get(0).size()).isEqualTo(1); - for (TrackedEntityInstance instance : partitions.get(0)) { - assertThat(getEnrollments(instance).size()).isEqualTo(3); - for (Enrollment enrollment : getEnrollments(instance)) { - if (enrollment.uid().equals("enrollment3Id")) { - assertThat(getEvents(enrollment).size()).isEqualTo(0); - } else { - assertThat(getEvents(enrollment).size()).isEqualTo(1); - } - } - } - } - - @Test - public void handle_import_conflicts_correctly() { - storeTrackedEntityInstance(); - - dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_2.json"); - - d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); - - assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(3); - } - - @Test - public void delete_old_import_conflicts() { - storeTrackedEntityInstance(); - - dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_2.json"); - d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); - assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(3); - - - TrackedEntityInstanceStoreImpl.create(databaseAdapter).setSyncState("teiId", State.TO_POST); - TrackedEntityInstanceStoreImpl.create(databaseAdapter).setState("teiId", State.TO_POST); - EnrollmentStoreImpl.create(databaseAdapter).setSyncState("enrollment1Id", State.TO_POST); - EnrollmentStoreImpl.create(databaseAdapter).setState("enrollment1Id", State.TO_POST); - EnrollmentStoreImpl.create(databaseAdapter).setSyncState("enrollment2Id", State.TO_POST); - EnrollmentStoreImpl.create(databaseAdapter).setState("enrollment2Id", State.TO_POST); - EventStoreImpl.create(databaseAdapter).setSyncState("event1Id", State.TO_POST); - EventStoreImpl.create(databaseAdapter).setSyncState("event2Id", State.TO_POST); - - dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_3.json"); - d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); - assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(1); - } - - @Test - public void handle_tei_deletions() throws D2Error { - storeTrackedEntityInstance(); - - d2.trackedEntityModule().trackedEntityInstances().uid("teiId").blockingDelete(); - - // There is no TEIs to upload, so there is no request to enqueue. - - d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); - - assertThat(d2.trackedEntityModule().trackedEntityInstances().blockingCount()).isEqualTo(0); - assertThat(d2.enrollmentModule().enrollments().blockingCount()).isEqualTo(0); - assertThat(d2.eventModule().events().blockingCount()).isEqualTo(0); - assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(0); - } - - @Test - public void recreate_teis_with_filters_and_relationships() throws Exception { - String tei1 = "tei1"; - String tei2 = "tei2"; - String tei3 = "tei3"; - String tei4 = "tei4"; - String tei5 = "tei5"; - - storeSimpleTrackedEntityInstance(tei1, State.TO_POST); - storeSimpleTrackedEntityInstance(tei2, State.TO_POST); - storeSimpleTrackedEntityInstance(tei3, State.TO_POST); - storeSimpleTrackedEntityInstance(tei4, State.TO_POST); - storeSimpleTrackedEntityInstance(tei5, State.SYNCED); - - storeRelationship("relationship1", tei1, tei2); - storeRelationship("relationship2", tei2, tei3); - storeRelationship("relationship3", tei1, tei5); - storeRelationship("relationship4", tei5, tei4); - - List> partitions = payloadGenerator.getTrackedEntityInstancesPartitions( - d2.trackedEntityModule().trackedEntityInstances().byUid().eq(tei1) - .byState().in(State.uploadableStates()).blockingGet()); - - assertThat(partitions.size()).isEqualTo(1); - assertThat(partitions.get(0).size()).isEqualTo(3); - assertThat(UidsHelper.getUidsList(partitions.get(0)).containsAll(Lists.newArrayList(tei1, tei2, tei3))).isTrue(); - } - - @Test - public void mark_payload_as_uploading() { - storeTrackedEntityInstance(); - - // Ignore result. Just interested in check that target TEIs are marked as UPLOADING - List> partitions = getPartitions(); - - TrackedEntityInstance instance = TrackedEntityInstanceStoreImpl.create(databaseAdapter).selectFirst(); - assertThat(instance.syncState()).isEqualTo(State.UPLOADING); - - List enrollments = EnrollmentStoreImpl.create(databaseAdapter).selectAll(); - for (Enrollment enrollment : enrollments) { - if ("enrollment1Id".equals(enrollment.uid()) || "enrollment2Id".equals(enrollment.uid())) { - assertThat(enrollment.syncState()).isEqualTo(State.UPLOADING); - } else { - assertThat(enrollment.syncState()).isNotEqualTo(State.UPLOADING); - } - } - - List events = EventStoreImpl.create(databaseAdapter).selectAll(); - for (Event event : events) { - if ("event1Id".equals(event.uid()) || "event2Id".equals(event.uid())) { - assertThat(event.state()).isEqualTo(State.UPLOADING); - } else { - assertThat(event.state()).isNotEqualTo(State.UPLOADING); - } - } - } - - @Test - public void restore_payload_states_when_error_500() { - storeTrackedEntityInstance(); - - dhis2MockServer.enqueueMockResponse(500, "Internal Server Error"); - - d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); - - TrackedEntityInstance instance = TrackedEntityInstanceStoreImpl.create(databaseAdapter).selectFirst(); - assertThat(instance.state()).isEqualTo(State.TO_POST); - - List enrollments = EnrollmentStoreImpl.create(databaseAdapter).selectAll(); - for (Enrollment enrollment : enrollments) { - if ("enrollment1Id".equals(enrollment.uid()) || "enrollment2Id".equals(enrollment.uid())) { - assertThat(enrollment.state()).isEqualTo(State.TO_POST); - } - } - - List events = EventStoreImpl.create(databaseAdapter).selectAll(); - for (Event event : events) { - if ("event1Id".equals(event.uid())) { - assertThat(event.state()).isEqualTo(State.TO_UPDATE); - } - if ("event2Id".equals(event.uid())) { - assertThat(event.state()).isEqualTo(State.SYNCED_VIA_SMS); - } - } - } - - @Test - public void build_payload_with_enrollment_notes() throws D2Error { - storeTrackedEntityInstance(); - - d2.noteModule().notes().blockingAdd(NoteCreateProjection.builder() - .enrollment(enrollment1Id) - .noteType(Note.NoteType.ENROLLMENT_NOTE) - .value("This is an enrollment note") - .build()); - - List> partitions = getPartitions(); - - assertThat(partitions.size()).isEqualTo(1); - assertThat(partitions.get(0).size()).isEqualTo(1); - for (TrackedEntityInstance instance : partitions.get(0)) { - for (Enrollment enrollment : getEnrollments(instance)) { - if (enrollment.uid().equals(enrollment1Id)) { - assertThat(enrollment.notes().size()).isEqualTo(1); - } else { - assertThat(enrollment.notes().size()).isEqualTo(0); - } - } - } - } - - @Test - public void build_payload_with_event_notes() throws D2Error { - storeTrackedEntityInstance(); - - d2.noteModule().notes().blockingAdd(NoteCreateProjection.builder() - .event(event1Id) - .noteType(Note.NoteType.EVENT_NOTE) - .value("This is an event note") - .build()); - - List> partitions = getPartitions(); - - assertThat(partitions.size()).isEqualTo(1); - assertThat(partitions.get(0).size()).isEqualTo(1); - for (TrackedEntityInstance instance : partitions.get(0)) { - for (Enrollment enrollment : getEnrollments(instance)) { - if (enrollment.uid().equals(enrollment1Id)) { - for (Event event : getEvents(enrollment)) { - if (event.uid().equals(event1Id)) { - assertThat(event.notes().size()).isEqualTo(1); - } else { - assertThat(enrollment.notes().size()).isEqualTo(0); - } - } - } - } - } - } - - private void storeTrackedEntityInstance() { - OrganisationUnit orgUnit = OrganisationUnitStore.create(databaseAdapter).selectFirst(); - TrackedEntityType teiType = TrackedEntityTypeStore.create(databaseAdapter).selectFirst(); - Program program = d2.programModule().programs().one().blockingGet(); - ProgramStage programStage = ProgramStageStore.create(databaseAdapter).selectFirst(); - - TrackedEntityDataValue dataValue1 = TrackedEntityDataValueSamples.get().toBuilder().event(event1Id).build(); - - Event event1 = Event.builder() - .uid(event1Id) - .enrollment(enrollment1Id) - .organisationUnit(orgUnit.uid()) - .program(program.uid()) - .programStage(programStage.uid()) - .syncState(State.TO_UPDATE) - .trackedEntityDataValues(Collections.singletonList(dataValue1)) - .build(); - - Enrollment enrollment1 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), - Collections.singletonList(event1)) - .uid(enrollment1Id) - .program(program.uid()) - .organisationUnit(orgUnit.uid()) - .state(State.TO_POST) - .syncState(State.TO_POST) - .trackedEntityInstance(teiId) - .build(); - - TrackedEntityDataValue dataValue2 = TrackedEntityDataValueSamples.get().toBuilder().event(event2Id).build(); - - Event event2 = Event.builder() - .uid(event2Id) - .enrollment(enrollment2Id) - .organisationUnit(orgUnit.uid()) - .program(program.uid()) - .programStage(programStage.uid()) - .syncState(State.SYNCED_VIA_SMS) - .trackedEntityDataValues(Collections.singletonList(dataValue2)) - .build(); - - Enrollment enrollment2 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), - Collections.singletonList(event2)) - .uid(enrollment2Id) - .program(program.uid()) - .organisationUnit(orgUnit.uid()) - .state(State.TO_POST) - .syncState(State.TO_POST) - .trackedEntityInstance(teiId) - .build(); - - TrackedEntityDataValue dataValue3 = TrackedEntityDataValueSamples.get().toBuilder().event(event3Id).build(); - - Event event3 = Event.builder() - .uid(event3Id) - .enrollment(enrollment3Id) - .organisationUnit(orgUnit.uid()) - .program(program.uid()) - .programStage(programStage.uid()) - .syncState(State.ERROR) - .trackedEntityDataValues(Collections.singletonList(dataValue3)) - .build(); - - Enrollment enrollment3 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), - Collections.singletonList(event3)) - .uid(enrollment3Id) - .program(program.uid()) - .organisationUnit(orgUnit.uid()) - .state(State.SYNCED) - .syncState(State.SYNCED) - .trackedEntityInstance(teiId) - .build(); - - TrackedEntityInstance tei = TrackedEntityInstanceInternalAccessor.insertEnrollments( - TrackedEntityInstance.builder(), Arrays.asList(enrollment1, enrollment2, enrollment3)) - .uid(teiId) - .trackedEntityType(teiType.uid()) - .organisationUnit(orgUnit.uid()) - .state(State.TO_POST) - .syncState(State.TO_POST) - .build(); - - TrackedEntityInstanceStoreImpl.create(databaseAdapter).insert(tei); - EnrollmentStoreImpl.create(databaseAdapter).insert(enrollment1); - EnrollmentStoreImpl.create(databaseAdapter).insert(enrollment2); - EnrollmentStoreImpl.create(databaseAdapter).insert(enrollment3); - EventStoreImpl.create(databaseAdapter).insert(event1); - EventStoreImpl.create(databaseAdapter).insert(event2); - EventStoreImpl.create(databaseAdapter).insert(event3); - TrackedEntityDataValueStoreImpl.create(databaseAdapter).insert(dataValue1); - TrackedEntityDataValueStoreImpl.create(databaseAdapter).insert(dataValue2); - TrackedEntityDataValueStoreImpl.create(databaseAdapter).insert(dataValue3); - } - - private void storeSimpleTrackedEntityInstance(String teiUid, State state) { - OrganisationUnit orgUnit = OrganisationUnitStore.create(databaseAdapter).selectFirst(); - TrackedEntityType teiType = TrackedEntityTypeStore.create(databaseAdapter).selectFirst(); - - TrackedEntityInstanceStoreImpl.create(databaseAdapter).insert( - TrackedEntityInstanceSamples.get().toBuilder() - .uid(teiUid) - .trackedEntityType(teiType.uid()) - .organisationUnit(orgUnit.uid()) - .state(state) - .syncState(state) - .build()); - } - - private void storeRelationship(String relationshipUid, String fromUid, String toUid) throws D2Error { - - RelationshipType relationshipType = RelationshipTypeStore.create(databaseAdapter).selectFirst(); - final D2CallExecutor executor = D2CallExecutor.create(databaseAdapter); - - executor.executeD2CallTransactionally(() -> { - - RelationshipStoreImpl.create(databaseAdapter).insert( - RelationshipSamples.get230(relationshipUid, fromUid, toUid).toBuilder() - .relationshipType(relationshipType.uid()).build()); - RelationshipItemStoreImpl.create(databaseAdapter).insert( - RelationshipItem.builder() - .relationship(ObjectWithUid.create(relationshipUid)) - .relationshipItemType(RelationshipConstraintType.FROM) - .trackedEntityInstance( - RelationshipItemTrackedEntityInstance.builder().trackedEntityInstance(fromUid).build()) - .build() - ); - RelationshipItemStoreImpl.create(databaseAdapter).insert( - RelationshipItem.builder() - .relationship(ObjectWithUid.create(relationshipUid)) - .relationshipItemType(RelationshipConstraintType.TO) - .trackedEntityInstance( - RelationshipItemTrackedEntityInstance.builder().trackedEntityInstance(toUid).build()) - .build() - ); - - ForeignKeyCleanerImpl.create(databaseAdapter).cleanForeignKeyErrors(); - - return null; - }); - } - - private List getEnrollments(TrackedEntityInstance trackedEntityInstance) { - return TrackedEntityInstanceInternalAccessor.accessEnrollments(trackedEntityInstance); - } - - private List getEvents(Enrollment enrollment) { - return EnrollmentInternalAccessor.accessEvents(enrollment); - } -} \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt index b652e3c351..64c74bc361 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt @@ -172,8 +172,8 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI teiStore.setState("teiId", State.TO_POST) enrollmentStore.setState("enrollment1Id", State.TO_POST) enrollmentStore.setState("enrollment2Id", State.TO_POST) - eventStore.setState("event1Id", State.TO_POST) - eventStore.setState("event2Id", State.TO_POST) + eventStore.setSyncStateOrDelete("event1Id", State.TO_POST) + eventStore.setSyncStateOrDelete("event2Id", State.TO_POST) dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_3.json") @@ -234,23 +234,23 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI val partitions = partitions val instance = teiStore.selectFirst() - assertThat(instance!!.state()).isEqualTo(State.UPLOADING) + assertThat(instance!!.syncState()).isEqualTo(State.UPLOADING) val enrollments = enrollmentStore.selectAll() for (enrollment in enrollments) { if ("enrollment1Id" == enrollment.uid() || "enrollment2Id" == enrollment.uid()) { - assertThat(enrollment.state()).isEqualTo(State.UPLOADING) + assertThat(enrollment.syncState()).isEqualTo(State.UPLOADING) } else { - assertThat(enrollment.state()).isNotEqualTo(State.UPLOADING) + assertThat(enrollment.syncState()).isNotEqualTo(State.UPLOADING) } } val events = eventStore.selectAll() for (event in events) { if (event1Id == event.uid() || event2Id == event.uid()) { - assertThat(event.state()).isEqualTo(State.UPLOADING) + assertThat(event.syncState()).isEqualTo(State.UPLOADING) } else { - assertThat(event.state()).isNotEqualTo(State.UPLOADING) + assertThat(event.syncState()).isNotEqualTo(State.UPLOADING) } } } @@ -345,16 +345,20 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI // Only enrollment1 and event1 are TO_UPDATE enrollmentStore.setState(enrollment2Id, State.SYNCED) - eventStore.setState(event2Id, State.SYNCED) + enrollmentStore.setSyncState(enrollment2Id, State.SYNCED) + eventStore.setSyncState(event2Id, State.SYNCED) dhis2MockServer.enqueueMockResponse("imports/web_response_with_empty_events.json") d2.trackedEntityModule().trackedEntityInstances().blockingUpload() val trackedEntityInstance = teiStore.selectByUid(teiId) assertThat(trackedEntityInstance!!.state()).isEqualTo(State.TO_UPDATE) + assertThat(trackedEntityInstance.syncState()).isEqualTo(State.SYNCED) assertThat(enrollmentStore.selectByUid(enrollment1Id)!!.state()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrollment1Id)!!.syncState()).isEqualTo(State.SYNCED) assertThat(enrollmentStore.selectByUid(enrollment2Id)!!.state()).isEqualTo(State.SYNCED) + assertThat(enrollmentStore.selectByUid(enrollment2Id)!!.syncState()).isEqualTo(State.SYNCED) assertThat(eventStore.selectByUid(event1Id)!!.state()).isEqualTo(State.TO_UPDATE) assertThat(eventStore.selectByUid(event2Id)!!.state()).isEqualTo(State.SYNCED) @@ -374,7 +378,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .organisationUnit(orgUnit!!.uid()) .program(program.uid()) .programStage(programStage!!.uid()) - .state(State.TO_UPDATE) + .syncState(State.TO_UPDATE) .trackedEntityDataValues(listOf(dataValue1)) .build() @@ -393,7 +397,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.SYNCED_VIA_SMS) + .syncState(State.SYNCED_VIA_SMS) .trackedEntityDataValues(listOf(dataValue2)) .build() @@ -413,7 +417,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .organisationUnit(orgUnit.uid()) .program(program.uid()) .programStage(programStage.uid()) - .state(State.ERROR) + .syncState(State.ERROR) .trackedEntityDataValues(listOf(dataValue3)) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index a7adfeb070..5aafddb5ee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 101; + static final int VERSION = 104; private final AssetManager assetManager; private final int targetVersion; diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java deleted file mode 100644 index 04f4340f76..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.enrollment.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; -import org.hisp.dhis.android.core.common.DataColumns; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.common.internal.DataStatePropagator; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.EnrollmentInternalAccessor; -import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.internal.EventImportHandler; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.BaseImportSummaryHelper; -import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary; -import org.hisp.dhis.android.core.imports.internal.EventImportSummaries; -import org.hisp.dhis.android.core.imports.internal.ImportConflict; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.note.Note; -import org.hisp.dhis.android.core.note.NoteTableInfo; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -import static org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getState; - -@Reusable -@SuppressWarnings("PMD.ExcessiveImports") -public class EnrollmentImportHandler { - private final EnrollmentStore enrollmentStore; - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final IdentifiableObjectStore noteStore; - private final EventImportHandler eventImportHandler; - private final TrackerImportConflictStore trackerImportConflictStore; - private final TrackerImportConflictParser trackerImportConflictParser; - private final DataStatePropagator dataStatePropagator; - - @Inject - public EnrollmentImportHandler(@NonNull EnrollmentStore enrollmentStore, - @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull IdentifiableObjectStore noteStore, - @NonNull EventImportHandler eventImportHandler, - @NonNull TrackerImportConflictStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser, - @NonNull DataStatePropagator dataStatePropagator) { - this.enrollmentStore = enrollmentStore; - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.noteStore = noteStore; - this.eventImportHandler = eventImportHandler; - this.trackerImportConflictStore = trackerImportConflictStore; - this.trackerImportConflictParser = trackerImportConflictParser; - this.dataStatePropagator = dataStatePropagator; - } - - public void handleEnrollmentImportSummary(List enrollmentImportSummaries, - List enrollments, - String teiUid) { - State parentState = null; - - if (enrollmentImportSummaries != null) { - for (EnrollmentImportSummary enrollmentImportSummary : enrollmentImportSummaries) { - String enrollmentUid = enrollmentImportSummary == null ? null : enrollmentImportSummary.reference(); - - if (enrollmentUid == null) { - break; - } - - State state = getState(enrollmentImportSummary.status()); - trackerImportConflictStore.deleteEnrollmentConflicts(enrollmentUid); - - HandleAction handleAction = enrollmentStore.setStateOrDelete(enrollmentUid, state); - - if (state.equals(State.ERROR) || state.equals(State.WARNING)) { - parentState = parentState == State.ERROR ? State.ERROR : state; - dataStatePropagator.resetUploadingEventStates(enrollmentUid); - } - - if (handleAction != HandleAction.Delete) { - storeEnrollmentImportConflicts(enrollmentImportSummary, teiUid); - handleNoteImportSummary(enrollmentUid, state); - handleEventImportSummaries(enrollmentImportSummary, enrollments, teiUid); - } - - } - } - - List processedEnrollments = BaseImportSummaryHelper.getReferences(enrollmentImportSummaries); - for (Enrollment enrollment : enrollments) { - if (!processedEnrollments.contains(enrollment.uid())) { - State state = State.TO_UPDATE; - enrollmentStore.setStateOrDelete(enrollment.uid(), state); - parentState = parentState == State.ERROR || parentState == State.WARNING ? parentState : state; - dataStatePropagator.resetUploadingEventStates(enrollment.uid()); - - trackerImportConflictStore.deleteEnrollmentConflicts(enrollment.uid()); - } - } - - updateParentState(parentState, teiUid); - } - - private void handleEventImportSummaries(EnrollmentImportSummary enrollmentImportSummary, - List enrollments, - String teiUid) { - - if (enrollmentImportSummary.events() != null) { - EventImportSummaries eventImportSummaries = enrollmentImportSummary.events(); - - if (eventImportSummaries.importSummaries() != null) { - eventImportHandler.handleEventImportSummaries( - eventImportSummaries.importSummaries(), - getEvents(enrollmentImportSummary.reference(), enrollments), - enrollmentImportSummary.reference(), - teiUid); - } - } - } - - private void handleNoteImportSummary(String enrollmentUid, State state) { - State newNoteState = state.equals(State.SYNCED) ? State.SYNCED : State.TO_POST; - String whereClause = new WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) - .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build(); - List notes = noteStore.selectWhere(whereClause); - for (Note note : notes) { - noteStore.update(note.toBuilder().state(newNoteState).build()); - } - } - - private void storeEnrollmentImportConflicts(EnrollmentImportSummary enrollmentImportSummary, - String teiUid) { - List trackerImportConflicts = new ArrayList<>(); - if (enrollmentImportSummary.description() != null) { - trackerImportConflicts.add(getConflictBuilder(teiUid, enrollmentImportSummary) - .conflict(enrollmentImportSummary.description()) - .displayDescription(enrollmentImportSummary.description()) - .value(enrollmentImportSummary.reference()) - .build()); - } - - if (enrollmentImportSummary.conflicts() != null) { - for (ImportConflict importConflict : enrollmentImportSummary.conflicts()) { - trackerImportConflicts.add(trackerImportConflictParser - .getEnrollmentConflict(importConflict, getConflictBuilder(teiUid, enrollmentImportSummary))); - } - } - - for (TrackerImportConflict trackerImportConflict : trackerImportConflicts) { - trackerImportConflictStore.insert(trackerImportConflict); - } - } - - - private void updateParentState(State parentState, String teiUid) { - if (parentState != null && teiUid != null) { - trackedEntityInstanceStore.setState(teiUid, parentState); - } - } - - private List getEvents(String enrollmentUid, - List enrollments) { - for (Enrollment enrollment : enrollments) { - if (enrollmentUid.equals(enrollment.uid())) { - return EnrollmentInternalAccessor.accessEvents(enrollment); - } - } - return Collections.emptyList(); - } - - private TrackerImportConflict.Builder getConflictBuilder(String trackedEntityInstanceUid, - EnrollmentImportSummary enrollmentImportSummary) { - return TrackerImportConflict.builder() - .trackedEntityInstance(trackedEntityInstanceUid) - .enrollment(enrollmentImportSummary.reference()) - .tableReference(EnrollmentTableInfo.TABLE_INFO.name()) - .status(enrollmentImportSummary.status()) - .created(new Date()); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java deleted file mode 100644 index 1281ac5c4d..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.event.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.EventTableInfo; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.BaseImportSummaryHelper; -import org.hisp.dhis.android.core.imports.internal.EventImportSummary; -import org.hisp.dhis.android.core.imports.internal.ImportConflict; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; -import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEventHandler; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -import static org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getState; - -@Reusable -public class EventImportHandler { - private final EventStore eventStore; - private final EnrollmentStore enrollmentStore; - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final TrackerImportConflictStore trackerImportConflictStore; - private final TrackerImportConflictParser trackerImportConflictParser; - private final JobReportEventHandler jobReportEventHandler; - - @Inject - public EventImportHandler(@NonNull EventStore eventStore, - @NonNull EnrollmentStore enrollmentStore, - @NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull TrackerImportConflictStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser, - JobReportEventHandler jobReportEventHandler) { - this.eventStore = eventStore; - this.enrollmentStore = enrollmentStore; - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.trackerImportConflictStore = trackerImportConflictStore; - this.trackerImportConflictParser = trackerImportConflictParser; - this.jobReportEventHandler = jobReportEventHandler; - } - - public void handleEventImportSummaries(List eventImportSummaries, - List events, - String enrollmentUid, - String teiUid) { - State parentState = null; - - if (eventImportSummaries != null) { - for (EventImportSummary eventImportSummary : eventImportSummaries) { - String eventUid = eventImportSummary == null ? null : eventImportSummary.reference(); - - if (eventUid == null) { - break; - } - - State state = getState(eventImportSummary.status()); - trackerImportConflictStore.deleteEventConflicts(eventUid); - - HandleAction handleAction = eventStore.setStateOrDelete(eventUid, state); - - if (state == State.ERROR || state == State.WARNING) { - parentState = parentState == State.ERROR ? State.ERROR : state; - } - - if (handleAction != HandleAction.Delete) { - jobReportEventHandler.handleEventNotes(eventUid, state); - - storeEventImportConflicts(eventImportSummary, teiUid, enrollmentUid); - } - } - } - - List processedEvents = BaseImportSummaryHelper.getReferences(eventImportSummaries); - for (Event event : events) { - if (!processedEvents.contains(event.uid())) { - State state = State.TO_UPDATE; - eventStore.setStateOrDelete(event.uid(), state); - parentState = parentState == State.ERROR || parentState == State.WARNING ? parentState : state; - - trackerImportConflictStore.deleteEventConflicts(event.uid()); - } - } - - updateParentState(parentState, teiUid, enrollmentUid); - } - - private void storeEventImportConflicts(EventImportSummary importSummary, - String teiUid, - String enrollmentUid) { - List trackerImportConflicts = new ArrayList<>(); - if (importSummary.description() != null) { - trackerImportConflicts.add(getConflictBuilder(teiUid, enrollmentUid, importSummary) - .conflict(importSummary.description()) - .displayDescription(importSummary.description()) - .value(importSummary.reference()) - .build()); - } - - if (importSummary.conflicts() != null) { - for (ImportConflict importConflict : importSummary.conflicts()) { - trackerImportConflicts.add(trackerImportConflictParser - .getEventConflict(importConflict, getConflictBuilder(teiUid, enrollmentUid, importSummary))); - } - - } - - for (TrackerImportConflict trackerImportConflict : trackerImportConflicts) { - trackerImportConflictStore.insert(trackerImportConflict); - } - } - - private void updateParentState(State parentState, String teiUid, String enrollmentUid) { - if (parentState != null) { - if (teiUid != null) { - trackedEntityInstanceStore.setState(teiUid, parentState); - } - if (enrollmentUid != null) { - enrollmentStore.setState(enrollmentUid, parentState); - } - } - } - - private TrackerImportConflict.Builder getConflictBuilder(String trackedEntityInstanceUid, - String enrollmentUid, - EventImportSummary eventImportSummary) { - return TrackerImportConflict.builder() - .trackedEntityInstance(trackedEntityInstanceUid) - .enrollment(enrollmentUid) - .event(eventImportSummary.reference()) - .tableReference(EventTableInfo.TABLE_INFO.name()) - .status(eventImportSummary.status()) - .created(new Date()); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java index 2e7560122b..7b9683ebd1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java @@ -28,15 +28,15 @@ package org.hisp.dhis.android.core.imports.internal; +import androidx.annotation.NonNull; + import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceImportHandler; -import javax.inject.Inject; - -import androidx.annotation.NonNull; - import java.util.List; +import javax.inject.Inject; + import dagger.Reusable; @Reusable diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java deleted file mode 100644 index e59e1314ac..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.trackedentity.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.common.internal.DataStatePropagator; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler; -import org.hisp.dhis.android.core.imports.TrackerImportConflict; -import org.hisp.dhis.android.core.imports.internal.BaseImportSummaryHelper; -import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummaries; -import org.hisp.dhis.android.core.imports.internal.ImportConflict; -import org.hisp.dhis.android.core.imports.internal.TEIImportSummary; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.relationship.Relationship; -import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository; -import org.hisp.dhis.android.core.relationship.RelationshipHelper; -import org.hisp.dhis.android.core.relationship.internal.RelationshipDHISVersionManager; -import org.hisp.dhis.android.core.relationship.internal.RelationshipStore; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; - -import static org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getState; - -@Reusable -@SuppressWarnings("PMD.ExcessiveImports") -public final class TrackedEntityInstanceImportHandler { - private final TrackedEntityInstanceStore trackedEntityInstanceStore; - private final EnrollmentImportHandler enrollmentImportHandler; - private final TrackerImportConflictStore trackerImportConflictStore; - private final TrackerImportConflictParser trackerImportConflictParser; - private final RelationshipStore relationshipStore; - private final DataStatePropagator dataStatePropagator; - private final RelationshipDHISVersionManager relationshipDHISVersionManager; - private final RelationshipCollectionRepository relationshipRepository; - - @Inject - TrackedEntityInstanceImportHandler(@NonNull TrackedEntityInstanceStore trackedEntityInstanceStore, - @NonNull EnrollmentImportHandler enrollmentImportHandler, - @NonNull TrackerImportConflictStore trackerImportConflictStore, - @NonNull TrackerImportConflictParser trackerImportConflictParser, - @NonNull RelationshipStore relationshipStore, - @NonNull DataStatePropagator dataStatePropagator, - @NonNull RelationshipDHISVersionManager relationshipDHISVersionManager, - @NonNull RelationshipCollectionRepository relationshipRepository) { - this.trackedEntityInstanceStore = trackedEntityInstanceStore; - this.enrollmentImportHandler = enrollmentImportHandler; - this.trackerImportConflictStore = trackerImportConflictStore; - this.trackerImportConflictParser = trackerImportConflictParser; - this.relationshipStore = relationshipStore; - this.dataStatePropagator = dataStatePropagator; - this.relationshipDHISVersionManager = relationshipDHISVersionManager; - this.relationshipRepository = relationshipRepository; - } - - public void handleTrackedEntityInstanceImportSummaries(List teiImportSummaries, - List instances) { - if (teiImportSummaries != null) { - for (TEIImportSummary teiImportSummary : teiImportSummaries) { - String teiUid = teiImportSummary == null ? null : teiImportSummary.reference(); - - if (teiUid == null) { - continue; - } - - State state = getState(teiImportSummary.status()); - trackerImportConflictStore.deleteTrackedEntityConflicts(teiUid); - - HandleAction handleAction = trackedEntityInstanceStore.setStateOrDelete(teiUid, state); - - if (state.equals(State.ERROR) || state.equals(State.WARNING)) { - dataStatePropagator.resetUploadingEnrollmentAndEventStates(teiUid); - setRelationshipsState(teiUid, State.TO_UPDATE); - } else { - setRelationshipsState(teiUid, State.SYNCED); - } - - if (handleAction != HandleAction.Delete) { - storeTEIImportConflicts(teiImportSummary); - if (teiImportSummary.enrollments() != null) { - EnrollmentImportSummaries importEnrollment = teiImportSummary.enrollments(); - - enrollmentImportHandler.handleEnrollmentImportSummary( - importEnrollment.importSummaries(), - getEnrollments(teiUid, instances), - teiUid); - } - } - } - } - - processIgnoredTEIs(teiImportSummaries, instances); - } - - private void storeTEIImportConflicts(TEIImportSummary teiImportSummary) { - List trackerImportConflicts = new ArrayList<>(); - if (teiImportSummary.description() != null) { - trackerImportConflicts.add(getConflictBuilder(teiImportSummary) - .conflict(teiImportSummary.description()) - .displayDescription(teiImportSummary.description()) - .value(teiImportSummary.reference()) - .build()); - } - - if (teiImportSummary.conflicts() != null) { - for (ImportConflict importConflict : teiImportSummary.conflicts()) { - trackerImportConflicts.add(trackerImportConflictParser - .getTrackedEntityInstanceConflict(importConflict, getConflictBuilder(teiImportSummary))); - } - } - - for (TrackerImportConflict trackerImportConflict : trackerImportConflicts) { - trackerImportConflictStore.insert(trackerImportConflict); - } - } - - private void setRelationshipsState(String trackedEntityInstanceUid, State state) { - List dbRelationships = - relationshipRepository.getByItem(RelationshipHelper.teiItem(trackedEntityInstanceUid), true); - - List ownedRelationships = relationshipDHISVersionManager - .getOwnedRelationships(dbRelationships, trackedEntityInstanceUid); - - for (Relationship relationship : ownedRelationships) { - relationshipStore.setStateOrDelete(relationship.uid(), state); - } - } - - private void processIgnoredTEIs(List teiImportSummaries, - List instances) { - - List processedTEIs = BaseImportSummaryHelper.getReferences(teiImportSummaries); - for (TrackedEntityInstance instance : instances) { - if (!processedTEIs.contains(instance.uid())) { - trackedEntityInstanceStore.setStateOrDelete(instance.uid(), State.TO_UPDATE); - dataStatePropagator.resetUploadingEnrollmentAndEventStates(instance.uid()); - setRelationshipsState(instance.uid(), State.TO_UPDATE); - } - } - } - - private List getEnrollments(String trackedEntityInstanceUid, - List instances) { - for (TrackedEntityInstance instance : instances) { - if (trackedEntityInstanceUid.equals(instance.uid())) { - return TrackedEntityInstanceInternalAccessor.accessEnrollments(instance); - } - } - return Collections.emptyList(); - } - - private TrackerImportConflict.Builder getConflictBuilder(TEIImportSummary teiImportSummary) { - return TrackerImportConflict.builder() - .trackedEntityInstance(teiImportSummary.reference()) - .tableReference(TrackedEntityInstanceTableInfo.TABLE_INFO.name()) - .status(teiImportSummary.status()) - .created(new Date()); - } -} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java index 66c87a0a9a..f00a5ab092 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java @@ -177,7 +177,7 @@ public void mark_as_to_update_tracked_entity_instances_not_present_in_the_respon Collections.singletonList(importSummary), instances ); - verify(trackedEntityInstanceStore, times(1)).setStateOrDelete("test_tei_uid", State.SYNCED); - verify(trackedEntityInstanceStore, times(1)).setStateOrDelete("missing_tei_uid", State.TO_UPDATE); + verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.SYNCED); + verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("missing_tei_uid", State.TO_UPDATE); } } \ No newline at end of file From 0a12467553b049cef150793c8ab9ae6fe1a73628 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 30 Jun 2021 08:53:53 +0200 Subject: [PATCH 098/308] [ANDROSDK-1395] Rename state to aggregatedSyncState --- ...stPayloadGeneratorMockIntegrationShould.kt | 2 +- ...ectionRepositoryMockIntegrationShould.java | 12 +++++-- ...ectionRepositoryMockIntegrationShould.java | 14 ++++++-- core/src/main/assets/migrations/104.sql | 14 +++++--- core/src/main/assets/snapshots/104.sql | 4 +-- .../internal/IgnoreStateColumnAdapter.java | 34 +++++++++++++++++++ .../dhis/android/core/common/DataColumns.java | 2 +- .../android/core/enrollment/Enrollment.java | 26 +++++++++++--- .../EnrollmentCollectionRepository.java | 10 +++++- .../core/enrollment/EnrollmentTableInfo.java | 2 +- .../internal/EnrollmentStoreImpl.java | 6 ++-- .../trackedentity/TrackedEntityInstance.java | 26 +++++++++++--- ...kedEntityInstanceCollectionRepository.java | 12 +++++-- .../TrackedEntityInstanceTableInfo.java | 2 +- .../TrackedEntityAttributeValueStoreImpl.java | 6 +++- .../TrackedEntityInstanceStoreImpl.java | 11 +++--- .../TrackedEntityInstanceLocalQueryHelper.kt | 4 +-- ...dEntityInstanceLocalQueryHelperShould.java | 4 +-- 18 files changed, 152 insertions(+), 39 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreStateColumnAdapter.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt index 64c74bc361..cadcf06415 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt @@ -218,7 +218,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI val partitions = payloadGenerator.getTrackedEntityInstancesPartitions( d2.trackedEntityModule().trackedEntityInstances().byUid().eq(tei1) - .byState().`in`(*State.uploadableStates()).blockingGet() + .byAggregatedSyncState().`in`(*State.uploadableStates()).blockingGet() ) assertThat(partitions.size).isEqualTo(1) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java index 7d8ddf0d4a..c15e8cc617 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/enrollment/EnrollmentCollectionRepositoryMockIntegrationShould.java @@ -179,9 +179,17 @@ public void filter_by_tracked_entity_instance() { } @Test - public void filter_by_state() { + public void filter_by_aggregated_sync_state() { List enrollments = d2.enrollmentModule().enrollments() - .byState().eq(State.SYNCED) + .byAggregatedSyncState().eq(State.SYNCED) + .blockingGet(); + assertThat(enrollments.size()).isEqualTo(2); + } + + @Test + public void filter_by_sync_state() { + List enrollments = d2.enrollmentModule().enrollments() + .bySyncState().eq(State.SYNCED) .blockingGet(); assertThat(enrollments.size()).isEqualTo(2); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java index 43abad1b09..5cd330dd10 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java @@ -148,16 +148,26 @@ public void filter_by_geometry_coordinates() { } @Test - public void filter_by_state() { + public void filter_by_aggregated_sync_state() { List trackedEntityInstances = d2.trackedEntityModule().trackedEntityInstances() - .byState().eq(State.SYNCED) + .byAggregatedSyncState().eq(State.SYNCED) .blockingGet(); // TODO set to assertThat(trackedEntityInstances.size()).isEqualTo(2); after moving write tests to another db assertThat(trackedEntityInstances.size()).isEqualTo(1); } + @Test + public void filter_by_sync_state() { + List trackedEntityInstances = + d2.trackedEntityModule().trackedEntityInstances() + .bySyncState().eq(State.SYNCED) + .blockingGet(); + + assertThat(trackedEntityInstances.size()).isEqualTo(2); + } + @Test public void filter_by_deleted() { List trackedEntityInstances = diff --git a/core/src/main/assets/migrations/104.sql b/core/src/main/assets/migrations/104.sql index 88e53d4911..2b90b5118d 100644 --- a/core/src/main/assets/migrations/104.sql +++ b/core/src/main/assets/migrations/104.sql @@ -26,11 +26,15 @@ CREATE TABLE FileResource (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT N INSERT INTO FileResource (_id, uid, name, created, lastUpdated, contentType, contentLength, path, syncState) SELECT _id, uid, name, created, lastUpdated, contentType, contentLength, path, state FROM FileResource_Old; DROP TABLE FileResource_Old; -ALTER TABLE TrackedEntityInstance ADD COLUMN syncState TEXT; -UPDATE TrackedEntityInstance SET syncState = state; - -ALTER TABLE Enrollment ADD COLUMN syncState TEXT; -UPDATE Enrollment SET syncState = state; +ALTER TABLE TrackedEntityInstance RENAME TO TrackedEntityInstance_Old; +CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, syncState TEXT, aggregatedSyncState TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +INSERT INTO TrackedEntityInstance (_id, uid, created, lastUpdated, createdAtClient, lastUpdatedAtClient, organisationUnit, trackedEntityType, geometryType, geometryCoordinates, syncState, aggregatedSyncState, deleted) SELECT _id, uid, created, lastUpdated, createdAtClient, lastUpdatedAtClient, organisationUnit, trackedEntityType, geometryType, geometryCoordinates, state, state, deleted FROM TrackedEntityInstance_Old; +DROP TABLE TrackedEntityInstance_Old; + +ALTER TABLE Enrollment RENAME TO Enrollment_Old; +CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, syncState TEXT, aggregatedSyncState TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +INSERT INTO Enrollment (_id, uid, created, lastUpdated, createdAtClient, lastUpdatedAtClient, organisationUnit, program, enrollmentDate, incidentDate, followup, status, trackedEntityInstance, syncState, aggregatedSyncState, geometryType, geometryCoordinates, deleted, completedDate) SELECT _id, uid, created, lastUpdated, createdAtClient, lastUpdatedAtClient, organisationUnit, program, enrollmentDate, incidentDate, followup, status, trackedEntityInstance, state, state, geometryType, geometryCoordinates, deleted, completedDate FROM Enrollment_Old; +DROP TABLE Enrollment_Old; ALTER TABLE Event RENAME TO Event_Old; CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/assets/snapshots/104.sql b/core/src/main/assets/snapshots/104.sql index 2d5427fc42..a2dc05807f 100644 --- a/core/src/main/assets/snapshots/104.sql +++ b/core/src/main/assets/snapshots/104.sql @@ -68,8 +68,8 @@ CREATE TABLE UserOrganisationUnit (_id INTEGER PRIMARY KEY AUTOINCREMENT, user T CREATE TABLE RelationshipType (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, fromToName TEXT, toFromName TEXT, bidirectional INTEGER, accessDataWrite INTEGER ); CREATE TABLE ProgramStage (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, executionDateLabel TEXT, allowGenerateNextVisit INTEGER, validCompleteOnly INTEGER, reportDateToUse TEXT, openAfterEnrollment INTEGER, repeatable INTEGER, formType TEXT, displayGenerateEventBox INTEGER, generatedByEnrollmentDate INTEGER, autoGenerateEvent INTEGER, sortOrder INTEGER, hideDueDate INTEGER, blockEntryForm INTEGER, minDaysFromStart INTEGER, standardInterval INTEGER, program TEXT NOT NULL, periodType TEXT, accessDataWrite INTEGER, remindCompleted INTEGER, description TEXT, displayDescription TEXT, featureType TEXT, color TEXT, icon TEXT, enableUserAssignment INTEGER, dueDateLabel TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Program (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, version INTEGER, onlyEnrollOnce INTEGER, enrollmentDateLabel TEXT, displayIncidentDate INTEGER, incidentDateLabel TEXT, registration INTEGER, selectEnrollmentDatesInFuture INTEGER, dataEntryMethod INTEGER, ignoreOverdueEvents INTEGER, selectIncidentDatesInFuture INTEGER, useFirstStageDuringRegistration INTEGER, displayFrontPageList INTEGER, programType TEXT, relatedProgram TEXT, trackedEntityType TEXT, categoryCombo TEXT, accessDataWrite INTEGER, expiryDays INTEGER, completeEventsExpiryDays INTEGER, expiryPeriodType TEXT, minAttributesRequiredToSearch INTEGER, maxTeiCountToReturn INTEGER, featureType TEXT, accessLevel TEXT, color TEXT, icon TEXT, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryCombo) REFERENCES CategoryCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, state TEXT, deleted INTEGER, syncState TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, state TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, syncState TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, syncState TEXT, aggregatedSyncState TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, syncState TEXT, aggregatedSyncState TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, period TEXT NOT NULL, organisationUnit TEXT NOT NULL, categoryOptionCombo TEXT NOT NULL, attributeOptionCombo TEXT NOT NULL, value TEXT, storedBy TEXT, created TEXT, lastUpdated TEXT, comment TEXT, followUp INTEGER, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId), FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo)); CREATE TABLE TrackedEntityDataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, event TEXT NOT NULL, dataElement TEXT NOT NULL, storedBy TEXT, value TEXT, created TEXT, lastUpdated TEXT, providedElsewhere INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreStateColumnAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreStateColumnAdapter.java new file mode 100644 index 0000000000..87e345038d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreStateColumnAdapter.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.ignore.internal; + +import org.hisp.dhis.android.core.common.State; + +public final class IgnoreStateColumnAdapter extends IgnoreColumnAdapter { +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java b/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java index 897e5a851b..bf705725e4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/DataColumns.java @@ -29,6 +29,6 @@ package org.hisp.dhis.android.core.common; public class DataColumns extends CoreColumns { - public static final String STATE = "state"; + public static final String AGGREGATED_SYNC_STATE = "aggregatedSyncState"; public static final String SYNC_STATE = "syncState"; } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java index 3e5a26a72b..c6feabff3b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java @@ -48,6 +48,7 @@ import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreEventListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNoteListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreRelationshipListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreStateColumnAdapter; import org.hisp.dhis.android.core.arch.helpers.CoordinateHelper; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; import org.hisp.dhis.android.core.common.Coordinates; @@ -157,11 +158,20 @@ public abstract class Enrollment extends BaseDeletableDataObject implements Obje @ColumnAdapter(IgnoreRelationshipListColumnAdapter.class) abstract List relationships(); - @Override @Nullable - @ColumnName(DataColumns.STATE) + @ColumnName(DataColumns.AGGREGATED_SYNC_STATE) @ColumnAdapter(StateColumnAdapter.class) - public abstract State state(); + public abstract State aggregatedSyncState(); + + /** + * @deprecated Use {@link #aggregatedSyncState()} instead. + */ + @Deprecated + @Nullable + @ColumnAdapter(IgnoreStateColumnAdapter.class) + public State state() { + return aggregatedSyncState(); + } public static Builder builder() { return new $$AutoValue_Enrollment.Builder(); @@ -220,7 +230,15 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder relationships); - public abstract Builder state(State state); + public abstract Builder aggregatedSyncState(State aggregatedSyncState); + + /** + * @deprecated Use {@link #aggregatedSyncState(State)} instead. + */ + @Deprecated + public Builder state(State state) { + return aggregatedSyncState(state); + } abstract Enrollment autoBuild(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java index d5e03c5f0e..f43da29e09 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java @@ -134,8 +134,16 @@ public StringFilterConnector byGeometryCoordinat return cf.string(EnrollmentTableInfo.Columns.GEOMETRY_COORDINATES); } + public EnumFilterConnector byAggregatedSyncState() { + return cf.enumC(DataColumns.AGGREGATED_SYNC_STATE); + } + + /** + * Use {@link #byAggregatedSyncState()} instead. + */ + @Deprecated public EnumFilterConnector byState() { - return cf.enumC(DataColumns.STATE); + return byAggregatedSyncState(); } public EnumFilterConnector bySyncState() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java index 5d3e2b4c20..c70634ebd5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentTableInfo.java @@ -86,7 +86,7 @@ public String[] all() { GEOMETRY_TYPE, GEOMETRY_COORDINATES, SYNC_STATE, - STATE, + AGGREGATED_SYNC_STATE, DELETED ); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java index b046554fb6..997c0ee0f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java @@ -85,7 +85,7 @@ private EnrollmentStoreImpl(DatabaseAdapter databaseAdapter, @Override public Map> queryEnrollmentsToPost() { String enrollmentsToPostQuery = new WhereClauseBuilder() - .appendInKeyStringValues(DataColumns.STATE, + .appendInKeyStringValues(DataColumns.AGGREGATED_SYNC_STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())).build(); List enrollmentList = selectWhere(enrollmentsToPostQuery); @@ -101,7 +101,7 @@ public Map> queryEnrollmentsToPost() { @Override public List queryMissingRelationshipsUids() { String whereRelationshipsClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.RELATIONSHIP) + .appendKeyStringValue(DataColumns.AGGREGATED_SYNC_STATE, State.RELATIONSHIP) .appendIsNullValue(EventTableInfo.Columns.ORGANISATION_UNIT) .build(); @@ -111,7 +111,7 @@ public List queryMissingRelationshipsUids() { @Override public int setState(String uid, State state) { ContentValues updates = new ContentValues(); - updates.put(DataColumns.STATE, state.toString()); + updates.put(DataColumns.AGGREGATED_SYNC_STATE, state.toString()); String whereClause = new WhereClauseBuilder() .appendKeyStringValue(IdentifiableColumns.UID, uid) .build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java index 089ed71811..ebb9ffc770 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java @@ -45,6 +45,7 @@ import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreEnrollmentListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreRelationship229CompatibleListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreStateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreStringColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreTrackedEntityAttributeValueListColumnAdapter; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; @@ -125,11 +126,20 @@ public abstract class TrackedEntityInstance extends BaseDeletableDataObject impl @ColumnAdapter(IgnoreEnrollmentListColumnAdapter.class) abstract List enrollments(); - @Override @Nullable - @ColumnName(DataColumns.STATE) + @ColumnName(DataColumns.AGGREGATED_SYNC_STATE) @ColumnAdapter(StateColumnAdapter.class) - public abstract State state(); + public abstract State aggregatedSyncState(); + + /** + * @deprecated Use {@link #aggregatedSyncState()} instead. + */ + @Deprecated + @Nullable + @ColumnAdapter(IgnoreStateColumnAdapter.class) + public State state() { + return aggregatedSyncState(); + } public static Builder builder() { return new $$AutoValue_TrackedEntityInstance.Builder(); @@ -174,7 +184,15 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder trackedEntityAttributeValues); - public abstract Builder state(State state); + public abstract Builder aggregatedSyncState(State state); + + /** + * @deprecated Use {@link #aggregatedSyncState(State)} instead. + */ + @Deprecated + public Builder state(State state) { + return aggregatedSyncState(state); + } abstract Builder relationships(List relationships); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java index b46b98761d..35485b51e7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java @@ -89,7 +89,7 @@ public Observable upload() { return Observable.concat( jobQueryCall.queryPendingJobs(), Observable.fromCallable(() -> - byState().in(State.uploadableStates()).blockingGetWithoutChildren() + byAggregatedSyncState().in(State.uploadableStates()).blockingGetWithoutChildren() ).flatMap(postCall::uploadTrackedEntityInstances) ); } @@ -141,14 +141,22 @@ public StringFilterConnector byGeomet return cf.string(Columns.GEOMETRY_COORDINATES); } + /** + * @deprecated Use {@link #byAggregatedSyncState()} instead. + */ + @Deprecated public EnumFilterConnector byState() { - return cf.enumC(Columns.STATE); + return byAggregatedSyncState(); } public EnumFilterConnector bySyncState() { return cf.enumC(Columns.SYNC_STATE); } + public EnumFilterConnector byAggregatedSyncState() { + return cf.enumC(Columns.AGGREGATED_SYNC_STATE); + } + public BooleanFilterConnector byDeleted() { return cf.bool(Columns.DELETED); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java index a25637a034..b5ecd4d2a0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceTableInfo.java @@ -74,7 +74,7 @@ public String[] all() { GEOMETRY_TYPE, GEOMETRY_COORDINATES, SYNC_STATE, - STATE, + AGGREGATED_SYNC_STATE, DELETED ); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityAttributeValueStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityAttributeValueStoreImpl.java index b878e91eb3..389d43842a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityAttributeValueStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityAttributeValueStoreImpl.java @@ -39,6 +39,7 @@ import org.hisp.dhis.android.core.arch.db.stores.projections.internal.SingleParentChildProjection; import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue; import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValueTableInfo; @@ -103,7 +104,10 @@ public Map> queryTrackedEntityAttribut private String teiInUploadableState() { String states = CollectionsHelper.commaAndSpaceSeparatedArrayValues( CollectionsHelper.withSingleQuotationMarksArray(EnumHelper.asStringList(State.uploadableStates()))); - return "(TrackedEntityInstance.state IN (" + states + "))"; + return "(" + TrackedEntityAttributeValueTableInfo.Columns.TRACKED_ENTITY_INSTANCE + + "." + + DataColumns.AGGREGATED_SYNC_STATE + + " IN (" + states + "))"; } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java index 745b5a48a6..ec649296eb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java @@ -70,8 +70,9 @@ public TrackedEntityInstanceStoreImpl(DatabaseAdapter databaseAdapter, @Override public List queryTrackedEntityInstancesToSync() { + List uploadableStatesString = EnumHelper.asStringList(State.uploadableStates()); String whereToSyncClause = new WhereClauseBuilder() - .appendInKeyStringValues(DataColumns.STATE, EnumHelper.asStringList(State.uploadableStates())) + .appendInKeyStringValues(DataColumns.AGGREGATED_SYNC_STATE, uploadableStatesString) .build(); return selectWhere(whereToSyncClause); @@ -80,7 +81,7 @@ public List queryTrackedEntityInstancesToSync() { @Override public List queryTrackedEntityInstancesToPost() { String whereToPostClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.TO_POST.name()) + .appendKeyStringValue(DataColumns.AGGREGATED_SYNC_STATE, State.TO_POST.name()) .build(); return selectWhere(whereToPostClause); @@ -89,7 +90,7 @@ public List queryTrackedEntityInstancesToPost() { @Override public List querySyncedTrackedEntityInstanceUids() { String whereSyncedClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.SYNCED) + .appendKeyStringValue(DataColumns.AGGREGATED_SYNC_STATE, State.SYNCED) .build(); return selectUidsWhere(whereSyncedClause); @@ -98,7 +99,7 @@ public List querySyncedTrackedEntityInstanceUids() { @Override public List queryMissingRelationshipsUids() { String whereRelationshipsClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.RELATIONSHIP) + .appendKeyStringValue(DataColumns.AGGREGATED_SYNC_STATE, State.RELATIONSHIP) .appendIsNullValue(TrackedEntityInstanceTableInfo.Columns.ORGANISATION_UNIT) .build(); @@ -108,7 +109,7 @@ public List queryMissingRelationshipsUids() { @Override public int setState(String uid, State state) { ContentValues updates = new ContentValues(); - updates.put(DataColumns.STATE, state.toString()); + updates.put(DataColumns.AGGREGATED_SYNC_STATE, state.toString()); String whereClause = new WhereClauseBuilder() .appendKeyStringValue(IdentifiableColumns.UID, uid) .build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt index fd8e4773e7..00d3f2b02e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelper.kt @@ -126,9 +126,9 @@ internal class TrackedEntityInstanceLocalQueryHelper @Inject constructor( } if (scope.states() == null) { - where.appendNotKeyStringValue(dot(teiAlias, DataColumns.STATE), State.RELATIONSHIP.name) + where.appendNotKeyStringValue(dot(teiAlias, DataColumns.AGGREGATED_SYNC_STATE), State.RELATIONSHIP.name) } else { - where.appendInKeyEnumValues(dot(teiAlias, DataColumns.STATE), scope.states()) + where.appendInKeyEnumValues(dot(teiAlias, DataColumns.AGGREGATED_SYNC_STATE), scope.states()) } if (!scope.includeDeleted()) { diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelperShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelperShould.java index 4ba92ce1f0..61986b19eb 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelperShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/search/TrackedEntityInstanceLocalQueryHelperShould.java @@ -113,7 +113,7 @@ public void build_sql_query_with_states() { .build(); String sqlQuery = localQueryHelper.getSqlQuery(scope, Collections.emptySet(), 50); - assertThat(sqlQuery).contains("state IN ('SYNCED', 'TO_POST', 'TO_UPDATE')"); + assertThat(sqlQuery).contains("aggregatedSyncState IN ('SYNCED', 'TO_POST', 'TO_UPDATE')"); } @Test @@ -123,7 +123,7 @@ public void build_sql_without_relationships_by_default() { .build(); String sqlQuery = localQueryHelper.getSqlQuery(scope, Collections.emptySet(), 50); - assertThat(sqlQuery).contains("state != 'RELATIONSHIP'"); + assertThat(sqlQuery).contains("aggregatedSyncState != 'RELATIONSHIP'"); } @Test From 66d32adb87b69a304bf50443b7b56d2fa382550e Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 30 Jun 2021 11:40:25 +0200 Subject: [PATCH 099/308] [ANDROSDK-1395] Adapt tests; improve lastUpdated logic --- .../DataStatePropagatorIntegrationShould.java | 34 ++--- ...stPayloadGeneratorMockIntegrationShould.kt | 22 +-- ...ectionRepositoryMockIntegrationShould.java | 2 +- .../internal/DeletableStoreWithState.kt | 1 + ...dentifiableDeletableDataObjectStoreImpl.kt | 5 + .../android/core/common/BaseDataObject.java | 4 + .../dhis/android/core/common/DataObject.java | 2 + .../common/internal/DataStatePropagator.kt | 5 +- .../internal/DataStatePropagatorImpl.kt | 132 ++++++++++------ .../EnrollmentCollectionRepository.java | 5 + .../EnrollmentObjectRepository.java | 4 +- .../internal/EnrollmentHandler.java | 4 +- .../internal/EnrollmentImportHandler.kt | 19 +-- .../EnrollmentProjectionTransformer.java | 2 +- ...nrollmentStore.java => EnrollmentStore.kt} | 20 ++- .../internal/EnrollmentStoreImpl.java | 142 ------------------ .../internal/EnrollmentStoreImpl.kt | 125 +++++++++++++++ .../core/event/EventCollectionRepository.java | 5 + .../core/event/internal/EventImportHandler.kt | 17 +-- ...TrackedEntityInstanceObjectRepository.java | 4 +- ...porterTrackedEntityPostPayloadGenerator.kt | 4 +- ...edEntityInstanceProjectionTransformer.java | 2 +- .../internal/TrackedEntityInstanceStore.java | 2 +- .../TrackedEntityInstanceStoreImpl.java | 4 +- .../internal/EventImportHandlerShould.java | 5 +- 25 files changed, 307 insertions(+), 264 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/{EnrollmentStore.java => EnrollmentStore.kt} (75%) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java index d9cce95215..1dad2ac689 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java @@ -172,7 +172,7 @@ public void do_not_propagate_last_updated_if_previous_is_newer() throws D2Error, public void propagate_last_updated_if_previous_is_null() throws D2Error { String teiUid = createTEIWithLastUpdated(null); - propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()); + d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); assertThat(trackedEntityInstanceStore.selectByUid(teiUid).lastUpdated()).isNotNull(); trackedEntityInstanceStore.delete(teiUid); @@ -232,9 +232,9 @@ private void assertThatSetTeiToUpdateWhenEnrollmentPropagation(State state) thro private void assertThatDoNotSetTeiToUpdateWhenEnrollmentPropagation(State state) throws D2Error { String teiUid = createTEIWithState(state); - propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()); + d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(state); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); trackedEntityInstanceStore.delete(teiUid); } @@ -242,12 +242,12 @@ private void assertThatSetTeiToUpdateWhenEventPropagation(State state) throws D2 String teiUid = createTEIWithState(state); String enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - enrollmentStore.setState(enrolmentUid, state); + enrollmentStore.setAggregatedSyncState(enrolmentUid, state); propagator.propagateEventUpdate(Event.builder().uid("uid").enrollment(enrolmentUid).build()); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrolmentUid).state()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -255,10 +255,10 @@ private void assertThatDoNotSetTeiToUpdateWhenEventPropagation(State state) thro String teiUid = createTEIWithState(state); String enrolmentUid = createEnrollmentWithState(state, teiUid); - propagator.propagateEventUpdate(Event.builder().uid("uid").enrollment(enrolmentUid).build()); + d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(state); - assertThat(enrollmentStore.selectByUid(enrolmentUid).state()).isEqualTo(state); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); + assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); trackedEntityInstanceStore.delete(teiUid); } @@ -269,9 +269,9 @@ private void assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrolmentUid).state()).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.selectByUid(eventUid).state()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -282,21 +282,21 @@ private void assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation( propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(state); - assertThat(enrollmentStore.selectByUid(enrolmentUid).state()).isEqualTo(state); - assertThat(eventStore.selectByUid(eventUid).state()).isEqualTo(state); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); + assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); + assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(state); trackedEntityInstanceStore.delete(teiUid); } private String createTEIWithState(State state) throws D2Error { String teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()); - trackedEntityInstanceStore.setState(teiUid, state); + trackedEntityInstanceStore.setAggregatedSyncState(teiUid, state); return teiUid; } private String createEnrollmentWithState(State state, String teiUid) throws D2Error { String enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - enrollmentStore.setState(enrolmentUid, state); + enrollmentStore.setAggregatedSyncState(enrolmentUid, state); return enrolmentUid; } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt index cadcf06415..e705d65f06 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt @@ -130,7 +130,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI fun build_payload_without_events_marked_as_error() { storeTrackedEntityInstance() - enrollmentStore.setState(enrollment3Id, State.TO_POST) + enrollmentStore.setAggregatedSyncState(enrollment3Id, State.TO_POST) val partitions = partitions assertThat(partitions.size).isEqualTo(1) @@ -169,9 +169,9 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(3) - teiStore.setState("teiId", State.TO_POST) - enrollmentStore.setState("enrollment1Id", State.TO_POST) - enrollmentStore.setState("enrollment2Id", State.TO_POST) + teiStore.setAggregatedSyncState("teiId", State.TO_POST) + enrollmentStore.setAggregatedSyncState("enrollment1Id", State.TO_POST) + enrollmentStore.setAggregatedSyncState("enrollment2Id", State.TO_POST) eventStore.setSyncStateOrDelete("event1Id", State.TO_POST) eventStore.setSyncStateOrDelete("event2Id", State.TO_POST) @@ -344,7 +344,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI storeTrackedEntityInstance() // Only enrollment1 and event1 are TO_UPDATE - enrollmentStore.setState(enrollment2Id, State.SYNCED) + enrollmentStore.setAggregatedSyncState(enrollment2Id, State.SYNCED) enrollmentStore.setSyncState(enrollment2Id, State.SYNCED) eventStore.setSyncState(event2Id, State.SYNCED) @@ -386,7 +386,8 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .uid(enrollment1Id) .program(program.uid()) .organisationUnit(orgUnit.uid()) - .state(State.TO_POST) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .trackedEntityInstance(teiId) .build() val dataValue2 = TrackedEntityDataValueSamples.get().toBuilder().event(event2Id).build() @@ -405,7 +406,8 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .uid(enrollment2Id) .program(program.uid()) .organisationUnit(orgUnit.uid()) - .state(State.TO_POST) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .trackedEntityInstance(teiId) .build() @@ -425,7 +427,8 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .uid(enrollment3Id) .program(program.uid()) .organisationUnit(orgUnit.uid()) - .state(State.SYNCED) + .syncState(State.TO_POST) + .aggregatedSyncState(State.SYNCED) .trackedEntityInstance(teiId) .build() @@ -435,7 +438,8 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .uid(teiId) .trackedEntityType(teiType!!.uid()) .organisationUnit(orgUnit.uid()) - .state(State.TO_POST) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .build() teiStore.insert(tei) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java index 5cd330dd10..ebe4dcf10a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/trackedentity/TrackedEntityCollectionRepositoryMockIntegrationShould.java @@ -165,7 +165,7 @@ public void filter_by_sync_state() { .bySyncState().eq(State.SYNCED) .blockingGet(); - assertThat(trackedEntityInstances.size()).isEqualTo(2); + assertThat(trackedEntityInstances.size()).isEqualTo(1); } @Test diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt index 51acd83338..e443ff6ef2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/DeletableStoreWithState.kt @@ -33,4 +33,5 @@ import org.hisp.dhis.android.core.common.State internal interface DeletableStoreWithState : StoreWithState { fun setSyncStateOrDelete(uid: String, state: State): HandleAction fun setDeleted(uid: String): Int + fun selectSyncStateWhere(where: String): List } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt index 2ffaa46fc5..e5d6fef7f8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableDeletableDataObjectStoreImpl.kt @@ -116,4 +116,9 @@ internal open class IdentifiableDeletableDataObjectStoreImpl( setDeletedStatement!!.clearBindings() return updatedRow } + + override fun selectSyncStateWhere(where: String): List { + val statesStr = selectStringColumnsWhereClause(DataColumns.SYNC_STATE, where) + return statesStr.map { State.valueOf(it) } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java b/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java index 299810b74d..2eb1e8930a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java @@ -38,6 +38,10 @@ public abstract class BaseDataObject extends BaseObject implements DataObject { + /** + * @deprecated Use {@link #syncState()} instead. + */ + @Deprecated @Override @Nullable public State state() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java b/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java index 4b59f588ca..ec2aa87a6e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/DataObject.java @@ -29,6 +29,8 @@ package org.hisp.dhis.android.core.common; public interface DataObject extends CoreObject { + @Deprecated State state(); + State syncState(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index d6262d302b..6362830ce8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -27,7 +27,6 @@ */ package org.hisp.dhis.android.core.common.internal -import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.note.Note @@ -53,7 +52,7 @@ interface DataStatePropagator { fun resetUploadingEventStates(enrollmentUid: String?) - fun propagateEnrollmentError(enrollmentUid: String?, state: State?) + fun refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid: String) - fun propagateTrackedEntityInstanceError(trackedEntityInstanceUid: String?, state: State?) + fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 0e90efc256..2599d4457d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -53,33 +53,37 @@ internal class DataStatePropagatorImpl @Inject internal constructor( ) : DataStatePropagator { override fun propagateEnrollmentUpdate(enrollment: Enrollment?) { - if (enrollment != null) { - setTeiState(enrollment.trackedEntityInstance(), getStateForUpdate) + enrollment?.let { + refreshTrackedEntityInstanceAggregatedSyncState(it.trackedEntityInstance()!!) + refreshTrackedEntityInstanceLastUpdated(it.trackedEntityInstance()!!) } } override fun propagateEventUpdate(event: Event?) { - if (event?.enrollment() != null) { - val enrollment = setEnrollmentState(event.enrollment(), getStateForUpdate) + event?.enrollment()?.let { enrollmentUid -> + refreshEnrollmentAggregatedSyncState(enrollmentUid) + refreshEnrollmentLastUpdated(enrollmentUid) + val enrollment = enrollmentStore.selectByUid(enrollmentUid) propagateEnrollmentUpdate(enrollment) } } override fun propagateTrackedEntityDataValueUpdate(dataValue: TrackedEntityDataValue?) { - val event = setEventState(dataValue!!.event(), getStateForUpdate) + val event = setEventSyncState(dataValue!!.event(), getStateForUpdate) propagateEventUpdate(event) } override fun propagateTrackedEntityAttributeUpdate(trackedEntityAttributeValue: TrackedEntityAttributeValue?) { - setTeiState(trackedEntityAttributeValue!!.trackedEntityInstance(), getStateForUpdate) + setTeiSyncState(trackedEntityAttributeValue!!.trackedEntityInstance(), getStateForUpdate) } override fun propagateNoteCreation(note: Note?) { if (note!!.noteType() == Note.NoteType.ENROLLMENT_NOTE) { - val enrollment = setEnrollmentState(note.enrollment(), getStateForUpdate) + setEnrollmentSyncState(note.enrollment()!!, getStateForUpdate) + val enrollment = enrollmentStore.selectByUid(note.enrollment()!!) propagateEnrollmentUpdate(enrollment) } else if (note.noteType() == Note.NoteType.EVENT_NOTE) { - val event = setEventState(note.event(), getStateForUpdate) + val event = setEventSyncState(note.event(), getStateForUpdate) propagateEventUpdate(event) } } @@ -87,53 +91,42 @@ internal class DataStatePropagatorImpl @Inject internal constructor( override fun propagateRelationshipUpdate(item: RelationshipItem?) { if (item != null) { if (item.hasTrackedEntityInstance()) { - setTeiState(item.trackedEntityInstance()!!.trackedEntityInstance(), getStateForUpdate) + setTeiSyncState(item.trackedEntityInstance()!!.trackedEntityInstance(), getStateForUpdate) } else if (item.hasEnrollment()) { - val enrollment = setEnrollmentState(item.enrollment()!!.enrollment(), getStateForUpdate) + setEnrollmentSyncState(item.enrollment()!!.enrollment(), getStateForUpdate) + val enrollment = enrollmentStore.selectByUid(item.enrollment()!!.enrollment()) propagateEnrollmentUpdate(enrollment) } else if (item.hasEvent()) { - val event = setEventState(item.event()!!.event(), getStateForUpdate) + val event = setEventSyncState(item.event()!!.event(), getStateForUpdate) propagateEventUpdate(event) } } } - private fun setTeiState(trackedEntityInstanceUid: String?, getState: (State?) -> State): TrackedEntityInstance? { - var instance = trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid!!) + private fun setTeiSyncState(trackedEntityInstanceUid: String?, getState: (State?) -> State) { + val instance = trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid!!) if (instance != null) { - val now = Date() - val updatedTEI = instance.toBuilder() - .state(getState(instance.state())) - .lastUpdated(getMaxDate(instance.lastUpdated(), now)) - .lastUpdatedAtClient(getMaxDate(instance.lastUpdatedAtClient(), now)) - .build() - trackedEntityInstanceStore.update(updatedTEI) - instance = updatedTEI + trackedEntityInstanceStore.setSyncState(trackedEntityInstanceUid, getState(instance.syncState())) + refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid) + refreshTrackedEntityInstanceLastUpdated(trackedEntityInstanceUid) } - return instance } - private fun setEnrollmentState(enrollmentUid: String?, getState: (State?) -> State): Enrollment? { - var enrollment = enrollmentStore.selectByUid(enrollmentUid!!) + private fun setEnrollmentSyncState(enrollmentUid: String, getState: (State?) -> State) { + val enrollment = enrollmentStore.selectByUid(enrollmentUid) if (enrollment != null) { - val now = Date() - val updatedEnrollment = enrollment.toBuilder() - .state(getState(enrollment.state())) - .lastUpdated(getMaxDate(enrollment.lastUpdated(), now)) - .lastUpdatedAtClient(getMaxDate(enrollment.lastUpdatedAtClient(), now)) - .build() - enrollmentStore.update(updatedEnrollment) - enrollment = updatedEnrollment + enrollmentStore.setSyncState(enrollmentUid, getState(enrollment.aggregatedSyncState())) + refreshEnrollmentAggregatedSyncState(enrollmentUid) + refreshEnrollmentLastUpdated(enrollmentUid) } - return enrollment } - private fun setEventState(eventUid: String?, getState: (State?) -> State): Event? { + private fun setEventSyncState(eventUid: String?, getState: (State?) -> State): Event? { var event = eventStore.selectByUid(eventUid!!) if (event != null) { val now = Date() val updatedEvent = event.toBuilder() - .syncState(getState(event.state())) + .syncState(getState(event.syncState())) .lastUpdated(getMaxDate(event.lastUpdated(), now)) .lastUpdatedAtClient(getMaxDate(event.lastUpdatedAtClient(), now)) .build() @@ -143,6 +136,28 @@ internal class DataStatePropagatorImpl @Inject internal constructor( return event } + private fun refreshEnrollmentLastUpdated(enrollmentUid: String) { + enrollmentStore.selectByUid(enrollmentUid)?.let { enrollment -> + val now = Date() + val updatedEnrollment = enrollment.toBuilder() + .lastUpdated(getMaxDate(enrollment.lastUpdated(), now)) + .lastUpdatedAtClient(getMaxDate(enrollment.lastUpdatedAtClient(), now)) + .build() + enrollmentStore.update(updatedEnrollment) + } + } + + private fun refreshTrackedEntityInstanceLastUpdated(trackedEntityInstanceUid: String) { + trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid)?.let { instance -> + val now = Date() + val updatedInstance = instance.toBuilder() + .lastUpdated(getMaxDate(instance.lastUpdated(), now)) + .lastUpdatedAtClient(getMaxDate(instance.lastUpdatedAtClient(), now)) + .build() + trackedEntityInstanceStore.update(updatedInstance) + } + } + override fun resetUploadingEnrollmentAndEventStates(trackedEntityInstanceUid: String?) { if (trackedEntityInstanceUid == null) { return @@ -174,15 +189,6 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } } - override fun propagateEnrollmentError(enrollmentUid: String?, state: State?) { - val enrollment = setEnrollmentState(enrollmentUid) { state!! } - propagateTrackedEntityInstanceError(enrollment?.trackedEntityInstance(), state) - } - - override fun propagateTrackedEntityInstanceError(trackedEntityInstanceUid: String?, state: State?) { - setTeiState(trackedEntityInstanceUid) { state!! } - } - private fun getMaxDate(existing: Date?, today: Date?): Date? { return if (existing == null) { today @@ -200,4 +206,42 @@ internal class DataStatePropagatorImpl @Inject internal constructor( State.TO_UPDATE } } + + override fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) { + enrollmentStore.selectByUid(enrollmentUid)?.let { enrollment -> + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EventTableInfo.Columns.ENROLLMENT, enrollmentUid) + .build() + val eventStates = eventStore.selectSyncStateWhere(whereClause) + + val enrollmentAggregatedSyncState = getAggregatedSyncState(eventStates + enrollment.syncState()!!) + enrollmentStore.setAggregatedSyncState(enrollmentUid, enrollmentAggregatedSyncState) + } + } + + override fun refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid: String) { + trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid)?.let { trackedEntityInstance -> + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, trackedEntityInstanceUid) + .build() + val enrollmentStates = enrollmentStore.selectAggregatedSyncStateWhere(whereClause) + + val teiAggregatedSyncState = getAggregatedSyncState(enrollmentStates + trackedEntityInstance.syncState()!!) + trackedEntityInstanceStore.setAggregatedSyncState(trackedEntityInstanceUid, teiAggregatedSyncState) + } + } + + private fun getAggregatedSyncState(states: List): State { + return when { + states.contains(State.RELATIONSHIP) -> State.RELATIONSHIP + states.contains(State.ERROR) -> State.ERROR + states.contains(State.WARNING) -> State.WARNING + states.contains(State.UPLOADING) || + states.contains(State.SENT_VIA_SMS) || + states.contains(State.SYNCED_VIA_SMS) || + states.contains(State.TO_POST) || + states.contains(State.TO_UPDATE) -> State.TO_UPDATE + else -> State.SYNCED + } + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java index f43da29e09..cdcd2f2efb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentCollectionRepository.java @@ -72,6 +72,11 @@ public final class EnrollmentCollectionRepository extends ReadWriteWithUidCollec this.dataStatePropagator = dataStatePropagator; } + @Override + protected void propagateState(Enrollment enrollment) { + dataStatePropagator.propagateEnrollmentUpdate(enrollment); + } + @Override public EnrollmentObjectRepository uid(String uid) { RepositoryScope updatedScope = RepositoryScopeHelper.withUidFilterItem(scope, uid); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java index f116a8609d..10752ebbb1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentObjectRepository.java @@ -90,12 +90,12 @@ public Unit setGeometry(Geometry geometry) throws D2Error { private Enrollment.Builder updateBuilder() { Enrollment enrollment = blockingGetWithoutChildren(); Date updateDate = new Date(); - State state = enrollment.state(); + State state = enrollment.aggregatedSyncState(); state = state == State.TO_POST ? state : State.TO_UPDATE; return enrollment.toBuilder() - .state(state) .syncState(state) + .aggregatedSyncState(state) .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java index a26bd8446c..bab0d18072 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java @@ -90,12 +90,12 @@ final class EnrollmentHandler extends IdentifiableDataHandlerImpl { @Override protected Enrollment addRelationshipState(Enrollment o) { - return o.toBuilder().state(State.RELATIONSHIP).syncState(State.RELATIONSHIP).build(); + return o.toBuilder().aggregatedSyncState(State.RELATIONSHIP).syncState(State.RELATIONSHIP).build(); } @Override protected Enrollment addSyncedState(Enrollment o) { - return o.toBuilder().state(State.SYNCED).syncState(State.SYNCED).build(); + return o.toBuilder().aggregatedSyncState(State.SYNCED).syncState(State.SYNCED).build(); } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt index 1025e386b0..be31709f58 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt @@ -65,8 +65,7 @@ internal class EnrollmentImportHandler @Inject constructor( enrollmentImportSummaries: List?, enrollments: List, teiUid: String - ): State { - var globalState: State = State.SYNCED + ) { enrollmentImportSummaries?.filterNotNull()?.forEach { enrollmentImportSummary -> enrollmentImportSummary.reference()?.let { enrollmentUid -> @@ -77,7 +76,6 @@ internal class EnrollmentImportHandler @Inject constructor( val handleAction = enrollmentStore.setSyncStateOrDelete(enrollmentUid, syncState) if (syncState == State.ERROR || syncState == State.WARNING) { - globalState = if (globalState == State.ERROR) State.ERROR else syncState dataStatePropagator.resetUploadingEventStates(enrollmentUid) } @@ -85,11 +83,7 @@ internal class EnrollmentImportHandler @Inject constructor( handleNoteImportSummary(enrollmentUid, syncState) storeEnrollmentImportConflicts(enrollmentImportSummary, teiUid) - val eventState = handleEventImportSummaries(enrollmentImportSummary, enrollments, teiUid) - - if (globalState == State.ERROR || globalState == State.WARNING) { - globalState = if (globalState == State.ERROR) State.ERROR else eventState - } + handleEventImportSummaries(enrollmentImportSummary, enrollments, teiUid) } } } @@ -100,19 +94,18 @@ internal class EnrollmentImportHandler @Inject constructor( val state = State.TO_UPDATE trackerImportConflictStore.deleteEnrollmentConflicts(enrollment.uid()) enrollmentStore.setSyncStateOrDelete(enrollment.uid(), state) - globalState = if (globalState == State.ERROR || globalState == State.WARNING) globalState else state dataStatePropagator.resetUploadingEventStates(enrollment.uid()) } - return globalState + dataStatePropagator.refreshTrackedEntityInstanceAggregatedSyncState(teiUid) } private fun handleEventImportSummaries( enrollmentImportSummary: EnrollmentImportSummary, enrollments: List, teiUid: String - ): State { - return enrollmentImportSummary.events()?.importSummaries()?.let { importSummaries -> + ) { + enrollmentImportSummary.events()?.importSummaries()?.let { importSummaries -> val enrollmentUid = enrollmentImportSummary.reference()!! eventImportHandler.handleEventImportSummaries( importSummaries, @@ -120,7 +113,7 @@ internal class EnrollmentImportHandler @Inject constructor( enrollmentUid, teiUid ) - } ?: State.SYNCED + } } private fun handleNoteImportSummary(enrollmentUid: String, state: State) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java index 59b263be15..5b480a9586 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentProjectionTransformer.java @@ -46,7 +46,7 @@ public Enrollment transform(EnrollmentCreateProjection projection) { return Enrollment.builder() .uid(generatedUid) - .state(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .syncState(State.TO_POST) .created(creationDate) .lastUpdated(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt similarity index 75% rename from core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java rename to core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt index 4cb7d33a9d..6493d61078 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt @@ -25,21 +25,19 @@ * (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.enrollment.internal -package org.hisp.dhis.android.core.enrollment.internal; +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.Enrollment -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.Enrollment; +internal interface EnrollmentStore : IdentifiableDeletableDataObjectStore { -import java.util.List; -import java.util.Map; + fun queryEnrollmentsToPost(): Map> -public interface EnrollmentStore extends IdentifiableDeletableDataObjectStore { + fun queryMissingRelationshipsUids(): List - Map> queryEnrollmentsToPost(); + fun setAggregatedSyncState(uid: String, state: State): Int - List queryMissingRelationshipsUids(); - - int setState(String uid, State state); + fun selectAggregatedSyncStateWhere(whereClause: String): List } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java deleted file mode 100644 index 997c0ee0f1..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.enrollment.internal; - -import android.content.ContentValues; -import android.database.Cursor; - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStoreImpl; -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; -import org.hisp.dhis.android.core.common.DataColumns; -import org.hisp.dhis.android.core.common.IdentifiableColumns; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; -import org.hisp.dhis.android.core.event.EventTableInfo; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import kotlin.jvm.functions.Function1; - -public final class EnrollmentStoreImpl - extends IdentifiableDeletableDataObjectStoreImpl implements EnrollmentStore { - - private static final StatementBinder BINDER = (o, w) -> { - w.bind(1, o.uid()); - w.bind(2, o.created()); - w.bind(3, o.lastUpdated()); - w.bind(4, o.createdAtClient()); - w.bind(5, o.lastUpdatedAtClient()); - w.bind(6, o.organisationUnit()); - w.bind(7, o.program()); - w.bind(8, o.enrollmentDate()); - w.bind(9, o.incidentDate()); - w.bind(10, o.completedDate()); - w.bind(11, o.followUp()); - w.bind(12, o.status()); - w.bind(13, o.trackedEntityInstance()); - w.bind(14, o.geometry() == null ? null : o.geometry().type()); - w.bind(15, o.geometry() == null ? null : o.geometry().coordinates()); - w.bind(16, o.syncState()); - w.bind(17, o.state()); - w.bind(18, o.deleted()); - }; - - private EnrollmentStoreImpl(DatabaseAdapter databaseAdapter, - SQLStatementBuilderImpl builder, - StatementBinder binder, - Function1 objectFactory) { - super(databaseAdapter, builder, binder, objectFactory); - } - - @Override - public Map> queryEnrollmentsToPost() { - String enrollmentsToPostQuery = new WhereClauseBuilder() - .appendInKeyStringValues(DataColumns.AGGREGATED_SYNC_STATE, - EnumHelper.asStringList(State.uploadableStatesIncludingError())).build(); - - List enrollmentList = selectWhere(enrollmentsToPostQuery); - - Map> enrollmentMap = new HashMap<>(); - for (Enrollment enrollment : enrollmentList) { - addEnrollmentToMap(enrollmentMap, enrollment); - } - - return enrollmentMap; - } - - @Override - public List queryMissingRelationshipsUids() { - String whereRelationshipsClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.AGGREGATED_SYNC_STATE, State.RELATIONSHIP) - .appendIsNullValue(EventTableInfo.Columns.ORGANISATION_UNIT) - .build(); - - return selectUidsWhere(whereRelationshipsClause); - } - - @Override - public int setState(String uid, State state) { - ContentValues updates = new ContentValues(); - updates.put(DataColumns.AGGREGATED_SYNC_STATE, state.toString()); - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(IdentifiableColumns.UID, uid) - .build(); - - return updateWhere(updates, whereClause); - } - - private void addEnrollmentToMap(Map> enrollmentMap, Enrollment enrollment) { - if (enrollmentMap.get(enrollment.trackedEntityInstance()) == null) { - enrollmentMap.put(enrollment.trackedEntityInstance(), new ArrayList<>()); - } - - enrollmentMap.get(enrollment.trackedEntityInstance()).add(enrollment); - } - - public static EnrollmentStore create(DatabaseAdapter databaseAdapter) { - SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl( - EnrollmentTableInfo.TABLE_INFO.name(), - EnrollmentTableInfo.TABLE_INFO.columns()); - - return new EnrollmentStoreImpl( - databaseAdapter, - statementBuilder, - BINDER, - Enrollment::create - ); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt new file mode 100644 index 0000000000..f06f565ab6 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004-2021, 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.core.enrollment.internal + +import android.content.ContentValues +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +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.internal.IdentifiableDeletableDataObjectStoreImpl +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper +import org.hisp.dhis.android.core.common.DataColumns +import org.hisp.dhis.android.core.common.IdentifiableColumns +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo +import org.hisp.dhis.android.core.event.EventTableInfo + +internal class EnrollmentStoreImpl private constructor( + databaseAdapter: DatabaseAdapter, + builder: SQLStatementBuilderImpl, + binder: StatementBinder, + objectFactory: Function1 +) : IdentifiableDeletableDataObjectStoreImpl(databaseAdapter, builder, binder, objectFactory), + EnrollmentStore { + + override fun queryEnrollmentsToPost(): Map> { + val enrollmentsToPostQuery = WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.AGGREGATED_SYNC_STATE, + EnumHelper.asStringList(*State.uploadableStatesIncludingError()) + ).build() + val enrollmentList: List = selectWhere(enrollmentsToPostQuery) + + return enrollmentList.groupBy { it.trackedEntityInstance()!! } + } + + override fun queryMissingRelationshipsUids(): List { + val whereRelationshipsClause = WhereClauseBuilder() + .appendKeyStringValue(DataColumns.AGGREGATED_SYNC_STATE, State.RELATIONSHIP) + .appendIsNullValue(EventTableInfo.Columns.ORGANISATION_UNIT) + .build() + + return selectUidsWhere(whereRelationshipsClause) + } + + override fun setAggregatedSyncState(uid: String, state: State): Int { + val updates = ContentValues() + updates.put(DataColumns.AGGREGATED_SYNC_STATE, state.toString()) + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(IdentifiableColumns.UID, uid) + .build() + + return updateWhere(updates, whereClause) + } + + override fun selectAggregatedSyncStateWhere(whereClause: String): List { + val statesStr = selectStringColumnsWhereClause(DataColumns.AGGREGATED_SYNC_STATE, whereClause) + + return statesStr.map { State.valueOf(it) } + } + + companion object { + private val BINDER = StatementBinder { o: Enrollment, w: StatementWrapper -> + w.bind(1, o.uid()) + w.bind(2, o.created()) + w.bind(3, o.lastUpdated()) + w.bind(4, o.createdAtClient()) + w.bind(5, o.lastUpdatedAtClient()) + w.bind(6, o.organisationUnit()) + w.bind(7, o.program()) + w.bind(8, o.enrollmentDate()) + w.bind(9, o.incidentDate()) + w.bind(10, o.completedDate()) + w.bind(11, o.followUp()) + w.bind(12, o.status()) + w.bind(13, o.trackedEntityInstance()) + w.bind(14, if (o.geometry() == null) null else o.geometry()!!.type()) + w.bind(15, if (o.geometry() == null) null else o.geometry()!!.coordinates()) + w.bind(16, o.syncState()) + w.bind(17, o.aggregatedSyncState()) + w.bind(18, o.deleted()) + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): EnrollmentStore { + val statementBuilder = SQLStatementBuilderImpl( + EnrollmentTableInfo.TABLE_INFO.name(), + EnrollmentTableInfo.TABLE_INFO.columns() + ) + return EnrollmentStoreImpl( + databaseAdapter, + statementBuilder, + BINDER + ) { cursor: Cursor? -> Enrollment.create(cursor) } + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java index 005089eb21..22359cd2e6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java @@ -108,6 +108,11 @@ public void blockingUpload() { upload().blockingSubscribe(); } + @Override + protected void propagateState(Event event) { + dataStatePropagator.propagateEventUpdate(event); + } + @Override public EventObjectRepository uid(String uid) { RepositoryScope updatedScope = RepositoryScopeHelper.withUidFilterItem(scope, uid); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt index 0b8ebcb271..f79acfd5e3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt @@ -31,6 +31,7 @@ import dagger.Reusable import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.EventTableInfo import org.hisp.dhis.android.core.imports.TrackerImportConflict @@ -47,7 +48,8 @@ internal class EventImportHandler @Inject constructor( private val eventStore: EventStore, private val trackerImportConflictStore: TrackerImportConflictStore, private val trackerImportConflictParser: TrackerImportConflictParser, - private val jobReportEventHandler: JobReportEventHandler + private val jobReportEventHandler: JobReportEventHandler, + private val dataStatePropagator: DataStatePropagator ) { fun handleEventImportSummaries( @@ -55,9 +57,7 @@ internal class EventImportHandler @Inject constructor( events: List, enrollmentUid: String?, teiUid: String? - ): State { - var globalState: State = State.SYNCED - + ) { eventImportSummaries?.filterNotNull()?.forEach { eventImportSummary -> eventImportSummary.reference()?.let { eventUid -> @@ -66,10 +66,6 @@ internal class EventImportHandler @Inject constructor( val handleAction = eventStore.setSyncStateOrDelete(eventUid, state) - if (state == State.ERROR || state == State.WARNING) { - globalState = if (globalState == State.ERROR) State.ERROR else state - } - if (handleAction !== HandleAction.Delete) { jobReportEventHandler.handleEventNotes(eventUid, state) storeEventImportConflicts(eventImportSummary, teiUid, enrollmentUid) @@ -82,10 +78,11 @@ internal class EventImportHandler @Inject constructor( val state = State.TO_UPDATE trackerImportConflictStore.deleteEventConflicts(event.uid()) eventStore.setSyncStateOrDelete(event.uid(), state) - globalState = if (globalState == State.ERROR || globalState == State.WARNING) globalState else state } - return globalState + enrollmentUid?.let { + dataStatePropagator.refreshEnrollmentAggregatedSyncState(it) + } } private fun storeEventImportConflicts( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java index 850dd5a707..167677072a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java @@ -65,7 +65,7 @@ public Unit setGeometry(Geometry geometry) throws D2Error { private TrackedEntityInstance.Builder updateBuilder() throws D2Error { TrackedEntityInstance trackedEntityInstance = blockingGetWithoutChildren(); - State state = trackedEntityInstance.state(); + State state = trackedEntityInstance.aggregatedSyncState(); if (state == State.RELATIONSHIP) { throw D2Error .builder() @@ -78,8 +78,8 @@ private TrackedEntityInstance.Builder updateBuilder() throws D2Error { state = state == State.TO_POST ? state : State.TO_UPDATE; return trackedEntityInstance.toBuilder() - .state(state) .syncState(state) + .aggregatedSyncState(state) .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index d2bbd80b55..45bf761979 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Transformer @@ -44,6 +43,7 @@ import org.hisp.dhis.android.core.note.NewTrackerImporterNote import org.hisp.dhis.android.core.note.NewTrackerImporterNoteTransformer import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.trackedentity.* +import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject internal constructor( @@ -104,7 +104,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter } private fun transformMap( - map: MutableMap>, + map: Map>, transformer: Transformer ): Map> { return map.mapValues { diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java index e7c825bb7e..4ca05b7d1e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceProjectionTransformer.java @@ -46,7 +46,7 @@ public TrackedEntityInstance transform(TrackedEntityInstanceCreateProjection pro return TrackedEntityInstance.builder() .uid(generatedUid) - .state(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .syncState(State.TO_POST) .created(creationDate) .lastUpdated(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java index 56ae26c19a..41698677f3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStore.java @@ -44,5 +44,5 @@ public interface TrackedEntityInstanceStore extends IdentifiableDeletableDataObj List queryMissingRelationshipsUids(); - int setState(String uid, State state); + int setAggregatedSyncState(String uid, State state); } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java index ec649296eb..e5ac7c2955 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreImpl.java @@ -59,7 +59,7 @@ public final class TrackedEntityInstanceStoreImpl w.bind(8, o.geometry() == null ? null : o.geometry().type()); w.bind(9, o.geometry() == null ? null : o.geometry().coordinates()); w.bind(10, o.syncState()); - w.bind(11, o.state()); + w.bind(11, o.aggregatedSyncState()); w.bind(12, o.deleted()); }; @@ -107,7 +107,7 @@ public List queryMissingRelationshipsUids() { } @Override - public int setState(String uid, State state) { + public int setAggregatedSyncState(String uid, State state) { ContentValues updates = new ContentValues(); updates.put(DataColumns.AGGREGATED_SYNC_STATE, state.toString()); String whereClause = new WhereClauseBuilder() diff --git a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java index eda2c7b556..7a04abe56c 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/event/internal/EventImportHandlerShould.java @@ -70,6 +70,9 @@ public class EventImportHandlerShould { @Mock private JobReportEventHandler jobReportEventHandler; + @Mock + private DataStatePropagator dataStatePropagator; + @Mock private TrackerImportConflictParser trackerImportConflictParser; @@ -88,7 +91,7 @@ public void setUp() throws Exception { when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); eventImportHandler = new EventImportHandler(eventStore, trackerImportConflictStore, - trackerImportConflictParser, jobReportEventHandler); + trackerImportConflictParser, jobReportEventHandler, dataStatePropagator); } @Test From 0d16d809ae29faff259002b574acac2089939a3f Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 30 Jun 2021 11:57:47 +0200 Subject: [PATCH 100/308] [ANDROSDK-1395] Add missing deprecated method --- .../DataStatePropagatorIntegrationShould.java | 32 +++++++++++++------ .../android/core/common/BaseDataObject.java | 10 ++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java index 1dad2ac689..331a60293c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java @@ -117,7 +117,7 @@ public void do_not_set_parent_state_to_update_if_has_to_post_state() throws D2Er public void do_not_fail_with_events_without_registration() throws D2Error { String eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(null)); - assertThat(eventStore.selectByUid(eventUid).state()).isEqualTo(State.TO_POST); + assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_POST); eventStore.delete(eventUid); } @@ -185,7 +185,8 @@ public void propagate_tei_relationship_update() throws D2Error { propagator.propagateRelationshipUpdate(fromItem); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -198,8 +199,10 @@ public void propagate_enrollment_relationship_update() throws D2Error { propagator.propagateRelationshipUpdate(fromItem); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrollmentUid).state()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(State.SYNCED); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.selectByUid(enrollmentUid).syncState()).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.selectByUid(enrollmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -213,9 +216,11 @@ public void propagate_event_relationship_update() throws D2Error { propagator.propagateRelationshipUpdate(fromItem); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrollmentUid).state()).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.selectByUid(eventUid).state()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(State.SYNCED); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.selectByUid(enrollmentUid).syncState()).isEqualTo(State.SYNCED); + assertThat(enrollmentStore.selectByUid(enrollmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -223,9 +228,10 @@ public void propagate_event_relationship_update() throws D2Error { private void assertThatSetTeiToUpdateWhenEnrollmentPropagation(State state) throws D2Error { String teiUid = createTEIWithState(state); - propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()); + d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).state()).isEqualTo(State.TO_UPDATE); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -258,7 +264,9 @@ private void assertThatDoNotSetTeiToUpdateWhenEventPropagation(State state) thro d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)); assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); + assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); } @@ -269,7 +277,9 @@ private void assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); + assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_UPDATE); trackedEntityInstanceStore.delete(teiUid); @@ -283,19 +293,23 @@ private void assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation( propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()); assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); + assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); + assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(state); trackedEntityInstanceStore.delete(teiUid); } private String createTEIWithState(State state) throws D2Error { String teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()); + trackedEntityInstanceStore.setSyncState(teiUid, state); trackedEntityInstanceStore.setAggregatedSyncState(teiUid, state); return teiUid; } private String createEnrollmentWithState(State state, String teiUid) throws D2Error { String enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); + enrollmentStore.setSyncState(enrolmentUid, state); enrollmentStore.setAggregatedSyncState(enrolmentUid, state); return enrolmentUid; } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java b/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java index 2eb1e8930a..41a1163a28 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/BaseDataObject.java @@ -35,6 +35,7 @@ import com.gabrielittner.auto.value.cursor.ColumnName; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreStateColumnAdapter; public abstract class BaseDataObject extends BaseObject implements DataObject { @@ -44,6 +45,7 @@ public abstract class BaseDataObject extends BaseObject implements DataObject { @Deprecated @Override @Nullable + @ColumnAdapter(IgnoreStateColumnAdapter.class) public State state() { return syncState(); } @@ -57,5 +59,13 @@ public State state() { @JsonPOJOBuilder(withPrefix = "") protected static abstract class Builder extends BaseObject.Builder { public abstract T syncState(@Nullable State syncState); + + /** + * @deprecated Use {@link #syncState(State)} instead. + */ + @Deprecated + public T state(State state) { + return syncState(state); + } } } From 0062a7f6b60246b89fd2935b2b50b89cd82c1cbc Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 30 Jun 2021 13:33:00 +0200 Subject: [PATCH 101/308] [androsdk-1383] Update visualization pojo and adapters --- .../android/core/common/RelativePeriod.kt | 89 ++++++++++--------- .../core/visualization/Visualization.java | 33 ++----- 2 files changed, 52 insertions(+), 70 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt b/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt index 85abdf8ced..71a994008b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt @@ -27,6 +27,7 @@ */ package org.hisp.dhis.android.core.common +import com.fasterxml.jackson.annotation.JsonAlias import org.hisp.dhis.android.core.period.PeriodType @Suppress("MagicNumber") @@ -37,47 +38,49 @@ enum class RelativePeriod constructor( internal val periodsThisYear: Boolean = false, internal val periodsLastYear: Boolean = false ) { - TODAY(PeriodType.Daily, 0, 1), - YESTERDAY(PeriodType.Daily, -1, 0), - LAST_3_DAYS(PeriodType.Daily, -3, 0), - LAST_7_DAYS(PeriodType.Daily, -7, 0), - LAST_14_DAYS(PeriodType.Daily, -14, 0), - LAST_30_DAYS(PeriodType.Daily, -30, 0), - LAST_60_DAYS(PeriodType.Daily, -60, 0), - LAST_90_DAYS(PeriodType.Daily, -90, 0), - LAST_180_DAYS(PeriodType.Daily, -180, 0), - THIS_MONTH(PeriodType.Monthly, 0, 1), - LAST_MONTH(PeriodType.Monthly, -1, 0), - THIS_BIMONTH(PeriodType.BiMonthly, 0, 1), - LAST_BIMONTH(PeriodType.BiMonthly, -1, 0), - THIS_QUARTER(PeriodType.Quarterly, 0, 1), - LAST_QUARTER(PeriodType.Quarterly, -1, 0), - THIS_SIX_MONTH(PeriodType.SixMonthly, 0, 1), - LAST_SIX_MONTH(PeriodType.SixMonthly, -1, 0), - WEEKS_THIS_YEAR(PeriodType.Weekly, null, null, true, false), - MONTHS_THIS_YEAR(PeriodType.Monthly, null, null, true, false), - BIMONTHS_THIS_YEAR(PeriodType.BiMonthly, null, null, true, false), - QUARTERS_THIS_YEAR(PeriodType.Quarterly, null, null, true, false), - THIS_YEAR(PeriodType.Yearly, 0, 1), - MONTHS_LAST_YEAR(PeriodType.Monthly, null, null, false, true), - QUARTERS_LAST_YEAR(PeriodType.Quarterly, null, null, false, true), - LAST_YEAR(PeriodType.Yearly, -1, 0), - LAST_5_YEARS(PeriodType.Yearly, -5, 0), - LAST_12_MONTHS(PeriodType.Monthly, -12, 0), - LAST_6_MONTHS(PeriodType.Monthly, -6, 0), - LAST_3_MONTHS(PeriodType.Monthly, -3, 0), - LAST_6_BIMONTHS(PeriodType.BiMonthly, -6, 0), - LAST_4_QUARTERS(PeriodType.Quarterly, -4, 0), - LAST_2_SIXMONTHS(PeriodType.SixMonthly, -2, 0), - THIS_FINANCIAL_YEAR(PeriodType.FinancialApril, 0, 1), - LAST_FINANCIAL_YEAR(PeriodType.FinancialApril, -1, 0), - LAST_5_FINANCIAL_YEARS(PeriodType.FinancialApril, -5, 0), - THIS_WEEK(PeriodType.Weekly, 0, 1), - LAST_WEEK(PeriodType.Weekly, -1, 0), - THIS_BIWEEK(PeriodType.BiWeekly, 0, 1), - LAST_BIWEEK(PeriodType.BiWeekly, -1, 0), - LAST_4_WEEKS(PeriodType.Weekly, -4, 0), - LAST_4_BIWEEKS(PeriodType.BiWeekly, -4, 0), - LAST_12_WEEKS(PeriodType.Weekly, -12, 0), - LAST_52_WEEKS(PeriodType.Weekly, -52, 0) + @JsonAlias("today", "thisDay") TODAY(PeriodType.Daily, 0, 1), + @JsonAlias("yesterday") YESTERDAY(PeriodType.Daily, -1, 0), + @JsonAlias("last3Days") LAST_3_DAYS(PeriodType.Daily, -3, 0), + @JsonAlias("last7Days") LAST_7_DAYS(PeriodType.Daily, -7, 0), + @JsonAlias("last14Days") LAST_14_DAYS(PeriodType.Daily, -14, 0), + @JsonAlias("last30Days") LAST_30_DAYS(PeriodType.Daily, -30, 0), + @JsonAlias("last60Days") LAST_60_DAYS(PeriodType.Daily, -60, 0), + @JsonAlias("last90Days") LAST_90_DAYS(PeriodType.Daily, -90, 0), + @JsonAlias("last180Days") LAST_180_DAYS(PeriodType.Daily, -180, 0), + @JsonAlias("thisMonth") THIS_MONTH(PeriodType.Monthly, 0, 1), + @JsonAlias("lastMonth") LAST_MONTH(PeriodType.Monthly, -1, 0), + @JsonAlias("thisBimonth") THIS_BIMONTH(PeriodType.BiMonthly, 0, 1), + @JsonAlias("lastBimonth") LAST_BIMONTH(PeriodType.BiMonthly, -1, 0), + @JsonAlias("thisQuarter") THIS_QUARTER(PeriodType.Quarterly, 0, 1), + @JsonAlias("lastQuarter") LAST_QUARTER(PeriodType.Quarterly, -1, 0), + @JsonAlias("thisSixMonth") THIS_SIX_MONTH(PeriodType.SixMonthly, 0, 1), + @JsonAlias("lastSixMonth") LAST_SIX_MONTH(PeriodType.SixMonthly, -1, 0), + @JsonAlias("weeksThisYear") WEEKS_THIS_YEAR(PeriodType.Weekly, null, null, true, false), + @JsonAlias("monthsThisYear") MONTHS_THIS_YEAR(PeriodType.Monthly, null, null, true, false), + @JsonAlias("biMonthsThisYear") BIMONTHS_THIS_YEAR(PeriodType.BiMonthly, null, null, true, false), + @JsonAlias("quartersThisYear") QUARTERS_THIS_YEAR(PeriodType.Quarterly, null, null, true, false), + @JsonAlias("thisYear") THIS_YEAR(PeriodType.Yearly, 0, 1), + @JsonAlias("monthsLastYear") MONTHS_LAST_YEAR(PeriodType.Monthly, null, null, false, true), + @JsonAlias("quartersLastYear") QUARTERS_LAST_YEAR(PeriodType.Quarterly, null, null, false, true), + @JsonAlias("lastYear") LAST_YEAR(PeriodType.Yearly, -1, 0), + @JsonAlias("last5Years") LAST_5_YEARS(PeriodType.Yearly, -5, 0), + @JsonAlias("last10Years") LAST_10_YEARS(PeriodType.Yearly, -10, 0), + @JsonAlias("last12Months") LAST_12_MONTHS(PeriodType.Monthly, -12, 0), + @JsonAlias("last6Months") LAST_6_MONTHS(PeriodType.Monthly, -6, 0), + @JsonAlias("last3Months") LAST_3_MONTHS(PeriodType.Monthly, -3, 0), + @JsonAlias("last6BiMonths") LAST_6_BIMONTHS(PeriodType.BiMonthly, -6, 0), + @JsonAlias("last4Quarters") LAST_4_QUARTERS(PeriodType.Quarterly, -4, 0), + @JsonAlias("last2SixMonths") LAST_2_SIXMONTHS(PeriodType.SixMonthly, -2, 0), + @JsonAlias("thisFinancialYear") THIS_FINANCIAL_YEAR(PeriodType.FinancialApril, 0, 1), + @JsonAlias("lastFinancialYear") LAST_FINANCIAL_YEAR(PeriodType.FinancialApril, -1, 0), + @JsonAlias("last5FinancialYears") LAST_5_FINANCIAL_YEARS(PeriodType.FinancialApril, -5, 0), + @JsonAlias("last10FinancialYears") LAST_10_FINANCIAL_YEARS(PeriodType.FinancialApril, -10, 0), + @JsonAlias("thisWeek") THIS_WEEK(PeriodType.Weekly, 0, 1), + @JsonAlias("lastWeek") LAST_WEEK(PeriodType.Weekly, -1, 0), + @JsonAlias("thisBiWeek") THIS_BIWEEK(PeriodType.BiWeekly, 0, 1), + @JsonAlias("lastBiWeek") LAST_BIWEEK(PeriodType.BiWeekly, -1, 0), + @JsonAlias("last4Weeks") LAST_4_WEEKS(PeriodType.Weekly, -4, 0), + @JsonAlias("last4BiWeeks") LAST_4_BIWEEKS(PeriodType.BiWeekly, -4, 0), + @JsonAlias("last12Weeks") LAST_12_WEEKS(PeriodType.Weekly, -12, 0), + @JsonAlias("last52Weeks") LAST_52_WEEKS(PeriodType.Weekly, -52, 0) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index f227ee9e1c..e21b6eb467 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -38,7 +38,6 @@ import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; -import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.CategoryDimensionListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.IntegerListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.RelativePeriodsColumnAdapter; @@ -47,6 +46,7 @@ import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DisplayDensityColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.HideEmptyItemStrategyColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.VisualizationTypeColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreCategoryDimensionListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreDataDimensionItemListColumnAdapter; import org.hisp.dhis.android.core.common.BaseIdentifiableObject; import org.hisp.dhis.android.core.common.CoreObject; @@ -151,12 +151,12 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(RelativePeriodsColumnAdapter.class) - public abstract HashMap relativePeriods(); + public abstract HashMap relativePeriods(); // Cell, but delete false @Nullable @JsonProperty() - @ColumnAdapter(CategoryDimensionListColumnAdapter.class) - public abstract List categoryDimensions(); + @ColumnAdapter(IgnoreCategoryDimensionListColumnAdapter.class) + public abstract List categoryDimensions(); // Table with visualization, category and coptino @Nullable @JsonProperty() @@ -176,7 +176,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(IgnoreDataDimensionItemListColumnAdapter.class) - public abstract List dataDimensionItems(); + public abstract List dataDimensionItems(); // Table with visualization id, type and uids with FK. @Nullable @JsonProperty() @@ -198,28 +198,13 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List organisationUnits(); - - @Nullable - @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List columns(); + public abstract List organisationUnits(); // Cell @Nullable @JsonProperty() @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List periods(); - @Nullable - @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List filters(); - - @Nullable - @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List rows(); - public static Builder builder() { return new $$AutoValue_Visualization.Builder(); } @@ -300,14 +285,8 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder organisationUnits); - public abstract Builder columns(List columns); - public abstract Builder periods(List periods); - public abstract Builder filters(List filters); - - public abstract Builder rows(List rows); - public abstract Visualization build(); } } \ No newline at end of file From 65b0962b8326053773efa23c8291f63455934e4d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 30 Jun 2021 13:33:15 +0200 Subject: [PATCH 102/308] [androsdk-1383] Add some tests --- ...reCategoryDimensionListColumnAdapter.java} | 22 ++----- .../visualization/VisualizationSamples.java | 58 +++++++++++++++++++ .../visualization/visualization.json | 20 ++++--- .../visualization/VisualizationShould.java | 54 +++++++++++++++++ 4 files changed, 130 insertions(+), 24 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/{custom/internal/CategoryDimensionListColumnAdapter.kt => ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java} (69%) create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java create mode 100644 core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java similarity index 69% rename from core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt rename to core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java index 5a6053c9fd..cc9ea128ac 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java @@ -25,23 +25,13 @@ * (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.arch.db.adapters.custom.internal -import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory -import org.hisp.dhis.android.core.visualization.CategoryDimension +package org.hisp.dhis.android.core.arch.db.adapters.ignore.internal; -internal class CategoryDimensionListColumnAdapter : JSONObjectListColumnAdapter() { - override fun getObjectClass(): Class> { - return ArrayList().javaClass - } +import org.hisp.dhis.android.core.visualization.CategoryDimension; - override fun serialize(o: List?): String? = CategoryDimensionListColumnAdapter.serialize(o) +import java.util.List; - companion object { - fun serialize(o: List?): String? { - return o?.let { - ObjectMapperFactory.objectMapper().writeValueAsString(it) - } - } - } -} +public final class IgnoreCategoryDimensionListColumnAdapter + extends IgnoreColumnAdapter> { +} \ No newline at end of file diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java new file mode 100644 index 0000000000..f6056bbee9 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.visualization; + +import org.hisp.dhis.android.core.common.BaseIdentifiableObject; +import org.hisp.dhis.android.core.visualization.Visualization; + +import java.text.ParseException; +import java.util.Date; + +import static org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.fillIdentifiableProperties; + +public class VisualizationSamples { + + public static Visualization get() { + Visualization.Builder builder = Visualization.builder(); + + fillIdentifiableProperties(builder); + return builder + .id(1L) + .build(); + } + + private static Date getDate(String dateStr) { + try { + return BaseIdentifiableObject.DATE_FORMAT.parse(dateStr); + } catch (ParseException e) { + e.printStackTrace(); + return null; + } + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/visualization/visualization.json b/core/src/sharedTest/resources/visualization/visualization.json index 3b59a760fb..b29fc47348 100644 --- a/core/src/sharedTest/resources/visualization/visualization.json +++ b/core/src/sharedTest/resources/visualization/visualization.json @@ -26,6 +26,7 @@ "displayDensity": "NORMAL", "digitGroupSeparator": "COMMA", "relativePeriods": { + "today": true, "thisYear": false, "quartersLastYear": false, "last30Days": false, @@ -193,26 +194,29 @@ "id": "vWbkYPRmKyS" } ], - "columns": [ + "periods": [ { - "id": "dx" + "id": "202102" }, { - "id": "fMZEcRHuamy" + "id": "202103" }, { - "id": "fkAkrdC7eJF" + "id": "2021S2" } ], - "periods": [ + + + + "columns": [ { - "id": "202102" + "id": "dx" }, { - "id": "202103" + "id": "fMZEcRHuamy" }, { - "id": "2021S2" + "id": "fkAkrdC7eJF" } ], "filters": [ diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java new file mode 100644 index 0000000000..80167be179 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import org.hisp.dhis.android.core.common.BaseObjectShould; +import org.hisp.dhis.android.core.common.ObjectShould; +import org.hisp.dhis.android.core.data.visualization.VisualizationSamples; +import org.junit.Test; + +import java.io.IOException; +import java.text.ParseException; + +import static com.google.common.truth.Truth.assertThat; + +public class VisualizationShould extends BaseObjectShould implements ObjectShould { + + public VisualizationShould() { + super("visualization/visualization.json"); + } + + @Override + @Test + public void map_from_json_string() throws IOException, ParseException { + Visualization jsonVisualization = objectMapper.readValue(jsonStream, Visualization.class); + Visualization expectedVisualization = VisualizationSamples.get().toBuilder().id(null).build(); + assertThat(jsonVisualization).isEqualTo(expectedVisualization); + } +} \ No newline at end of file From d8101d24833a389d0786d657717484e4a4ab11f1 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 1 Jul 2021 12:57:44 +0200 Subject: [PATCH 103/308] [androsdk-1383] Improve relative periods column adapter --- .../db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt | 2 +- .../org/hisp/dhis/android/core/visualization/Visualization.java | 2 +- core/src/sharedTest/resources/visualization/visualization.json | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt index e9048ac470..781caf7c52 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -40,7 +40,7 @@ internal class RelativePeriodsColumnAdapter : JSONObjectHashMapColumnAdapter?): String? { return o?.let { - ObjectMapperFactory.objectMapper().writeValueAsString(it) + ObjectMapperFactory.objectMapper().writeValueAsString(it.filter { it.value }) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index e21b6eb467..182862db57 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -151,7 +151,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(RelativePeriodsColumnAdapter.class) - public abstract HashMap relativePeriods(); // Cell, but delete false + public abstract HashMap relativePeriods(); @Nullable @JsonProperty() diff --git a/core/src/sharedTest/resources/visualization/visualization.json b/core/src/sharedTest/resources/visualization/visualization.json index b29fc47348..f57476a51f 100644 --- a/core/src/sharedTest/resources/visualization/visualization.json +++ b/core/src/sharedTest/resources/visualization/visualization.json @@ -26,7 +26,6 @@ "displayDensity": "NORMAL", "digitGroupSeparator": "COMMA", "relativePeriods": { - "today": true, "thisYear": false, "quartersLastYear": false, "last30Days": false, From 40f0967f6202e52353543cf65867ff36c84d50f4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 1 Jul 2021 12:57:58 +0200 Subject: [PATCH 104/308] [androsdk-1383] Add visualization table info --- .../visualization/VisualizationTableInfo.kt | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt new file mode 100644 index 0000000000..4e1c8fdc66 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns +import org.hisp.dhis.android.core.common.IdentifiableColumns + +object VisualizationTableInfo { + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "Visualization" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : IdentifiableColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + DESCRIPTION, + DISPLAY_DESCRIPTION, + DISPLAY_FORM_NAME, + TYPE, + HIDE_TITLE, + HIDE_SUBTITLE, + HIDE_EMPTY_COLUMNS, + HIDE_EMPTY_ROWS, + HIDE_EMPTY_ROW_ITEMS, + HIDE_LEGEND, + SHOW_HIERARCHY, + ROW_TOTALS, + ROW_SUB_TOTALS, + COL_TOTALS, + COL_SUB_TOTALS, + SHOW_DIMENSION_LABELS, + PERCENT_STACKED_VALUES, + NO_SPACE_BETWEEN_COLUMNS, + SKIP_ROUNDING, + DISPLAY_DENSITY, + DIGIT_GROUP_SEPARATOR, + RELATIVE_PERIODS, + FILTER_DIMENSIONS, + ROW_DIMENSIONS, + COLUMN_DIMENSIONS, + ORGANISATION_UNIT_LEVELS, + USER_ORGANISATION_UNIT, + USER_ORGANISATION_UNIT_CHILDREN, + USER_ORGANISATION_UNIT_GRAND_CHILDREN, + ORGANISATION_UNITS, + PERIODS + ) + } + + companion object { + const val DESCRIPTION = "description" + const val DISPLAY_DESCRIPTION = "displayDescription" + const val DISPLAY_FORM_NAME = "displayFormName" + const val TYPE = "type" + const val HIDE_TITLE = "hideTitle" + const val HIDE_SUBTITLE = "hideSubtitle" + const val HIDE_EMPTY_COLUMNS = "hideEmptyColumns" + const val HIDE_EMPTY_ROWS = "hideEmptyRows" + const val HIDE_EMPTY_ROW_ITEMS = "hideEmptyRowItems" + const val HIDE_LEGEND = "hideLegend" + const val SHOW_HIERARCHY = "showHierarchy" + const val ROW_TOTALS = "rowTotals" + const val ROW_SUB_TOTALS = "rowSubTotals" + const val COL_TOTALS = "colTotals" + const val COL_SUB_TOTALS = "colSubTotals" + const val SHOW_DIMENSION_LABELS = "showDimensionLabels" + const val PERCENT_STACKED_VALUES = "percentStackedValues" + const val NO_SPACE_BETWEEN_COLUMNS = "noSpaceBetweenColumns" + const val SKIP_ROUNDING = "skipRounding" + const val DISPLAY_DENSITY = "displayDensity" + const val DIGIT_GROUP_SEPARATOR = "digitGroupSeparator" + const val RELATIVE_PERIODS = "relativePeriods" + const val FILTER_DIMENSIONS = "filterDimensions" + const val ROW_DIMENSIONS = "rowDimensions" + const val COLUMN_DIMENSIONS = "columnDimensions" + const val ORGANISATION_UNIT_LEVELS = "organisationUnitLevels" + const val USER_ORGANISATION_UNIT = "userOrganisationUnit" + const val USER_ORGANISATION_UNIT_CHILDREN = "userOrganisationUnitChildren" + const val USER_ORGANISATION_UNIT_GRAND_CHILDREN = "userOrganisationUnitGrandChildren" + const val ORGANISATION_UNITS = "organisationUnits" + const val PERIODS = "periods" + } + } +} From dd1b41fd07090da8df3004f12e94b56e5a4902e4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 1 Jul 2021 13:26:00 +0200 Subject: [PATCH 105/308] [androsdk-1383] Add visualization store --- .../core/visualization/VisualizationStore.kt | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt new file mode 100644 index 0000000000..11fa9953ac --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory + +@Suppress("MagicNumber") +internal object VisualizationStore { + private val BINDER = object : IdentifiableStatementBinder() { + override fun bindToStatement(o: Visualization, w: StatementWrapper) { + super.bindToStatement(o, w) + w.bind(7, o.description()) + w.bind(8, o.displayDescription()) + w.bind(9, o.displayFormName()) + w.bind(10, o.type()) + w.bind(11, o.hideTitle()) + w.bind(12, o.hideSubtitle()) + w.bind(13, o.hideEmptyColumns()) + w.bind(14, o.hideEmptyRows()) + w.bind(15, o.hideEmptyRowItems()) + w.bind(16, o.hideLegend()) + w.bind(17, o.showHierarchy()) + w.bind(18, o.rowTotals()) + w.bind(19, o.rowSubTotals()) + w.bind(10, o.colTotals()) + w.bind(21, o.colSubTotals()) + w.bind(22, o.showDimensionLabels()) + w.bind(23, o.percentStackedValues()) + w.bind(24, o.noSpaceBetweenColumns()) + w.bind(25, o.skipRounding()) + w.bind(26, o.displayDensity()) + w.bind(27, o.digitGroupSeparator()) + w.bind(28, o.relativePeriods()) + w.bind(29, o.filterDimensions()) + w.bind(20, o.rowDimensions()) + w.bind(31, o.columnDimensions()) + w.bind(32, o.organisationUnitLevels()) + w.bind(33, o.userOrganisationUnit()) + w.bind(34, o.userOrganisationUnitChildren()) + w.bind(35, o.userOrganisationUnitGrandChildren()) + w.bind(36, o.organisationUnits()) + w.bind(37, o.periods())) + } + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return StoreFactory.objectWithUidStore( + databaseAdapter, VisualizationTableInfo.TABLE_INFO, BINDER + ) { cursor: Cursor -> Visualization.create(cursor) } + } +} From b0fae5b20fdd276202a5ef6f11ef985b2193e1e5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 1 Jul 2021 14:16:25 +0200 Subject: [PATCH 106/308] [ANDROSDK-1395] Ktlint, checkstyle --- .../DataStatePropagatorIntegrationShould.java | 344 --------------- .../DataStatePropagatorIntegrationShould.kt | 390 ++++++++++++++++++ .../{EnumHelper.java => EnumHelper.kt} | 21 +- .../core/common/{State.java => State.kt} | 44 +- .../common/internal/DataStatePropagator.kt | 2 +- .../internal/DataStatePropagatorImpl.kt | 16 +- ...SetInstanceSummarySQLStatementBuilder.java | 1 - .../android/core/enrollment/Enrollment.java | 1 + .../internal/EnrollmentImportHandler.kt | 8 +- .../enrollment/internal/EnrollmentStore.kt | 2 +- .../internal/EnrollmentStoreImpl.kt | 4 +- .../core/event/internal/EventImportHandler.kt | 6 +- ...porterTrackedEntityPostPayloadGenerator.kt | 2 +- .../TrackedEntityInstanceImportHandler.kt | 25 +- 14 files changed, 459 insertions(+), 407 deletions(-) delete mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt rename core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/{EnumHelper.java => EnumHelper.kt} (79%) rename core/src/main/java/org/hisp/dhis/android/core/common/{State.java => State.kt} (76%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java deleted file mode 100644 index 331a60293c..0000000000 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.common.internal; - -import androidx.test.runner.AndroidJUnit4; - -import org.hisp.dhis.android.core.common.BaseIdentifiableObject; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.EnrollmentCreateProjection; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStoreImpl; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.EventCreateProjection; -import org.hisp.dhis.android.core.event.internal.EventStore; -import org.hisp.dhis.android.core.event.internal.EventStoreImpl; -import org.hisp.dhis.android.core.maintenance.D2Error; -import org.hisp.dhis.android.core.relationship.RelationshipHelper; -import org.hisp.dhis.android.core.relationship.RelationshipItem; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceCreateProjection; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStoreImpl; -import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.IOException; -import java.text.ParseException; -import java.util.Date; - -import static com.google.common.truth.Truth.assertThat; - -@RunWith(AndroidJUnit4.class) -public class DataStatePropagatorIntegrationShould extends BaseMockIntegrationTestFullDispatcher { - - private DataStatePropagator propagator; - private TrackedEntityInstanceStore trackedEntityInstanceStore; - private EnrollmentStore enrollmentStore; - private EventStore eventStore; - - @Before - public void setUp() throws IOException { - this.trackedEntityInstanceStore = TrackedEntityInstanceStoreImpl.create(d2.databaseAdapter()); - this.enrollmentStore = EnrollmentStoreImpl.create(d2.databaseAdapter()); - this.eventStore = EventStoreImpl.create(d2.databaseAdapter()); - this.propagator = new DataStatePropagatorImpl( - trackedEntityInstanceStore, - enrollmentStore, - eventStore); - } - - @Test - public void set_parent_state_to_update_if_has_synced_state() throws D2Error { - assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.SYNCED); - assertThatSetTeiToUpdateWhenEventPropagation(State.SYNCED); - assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.SYNCED); - } - - @Test - public void set_parent_state_to_update_if_has_to_update_state() throws D2Error { - assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.TO_UPDATE); - assertThatSetTeiToUpdateWhenEventPropagation(State.TO_UPDATE); - assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.TO_UPDATE); - } - - @Test - public void set_parent_state_to_update_if_has_error_state() throws D2Error { - assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.ERROR); - assertThatSetTeiToUpdateWhenEventPropagation(State.ERROR); - assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.ERROR); - } - - @Test - public void set_parent_state_to_update_if_has_warning_state() throws D2Error { - assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.WARNING); - assertThatSetTeiToUpdateWhenEventPropagation(State.WARNING); - assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.WARNING); - } - - @Test - public void do_not_set_parent_state_to_update_if_has_to_post_state() throws D2Error { - assertThatDoNotSetTeiToUpdateWhenEnrollmentPropagation(State.TO_POST); - assertThatDoNotSetTeiToUpdateWhenEventPropagation(State.TO_POST); - assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.TO_POST); - } - - @Test - public void do_not_fail_with_events_without_registration() throws D2Error { - String eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(null)); - - assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_POST); - eventStore.delete(eventUid); - } - - @Test - public void reset_enrollment_and_event_states_if_uploading() throws D2Error { - String teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()); - String enrolmentUid1 = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - String enrolmentUid2 = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - - String eventUid1 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid1)); - String eventUid2 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid1)); - String eventUid3 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid2)); - - enrollmentStore.setSyncState(enrolmentUid1, State.UPLOADING); - eventStore.setSyncState(eventUid1, State.UPLOADING); - - propagator.resetUploadingEnrollmentAndEventStates(teiUid); - - assertThat(enrollmentStore.getSyncState(enrolmentUid1)).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.getSyncState(enrolmentUid2)).isEqualTo(State.TO_POST); - - assertThat(eventStore.getSyncState(eventUid1)).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.getSyncState(eventUid2)).isEqualTo(State.TO_POST); - assertThat(eventStore.getSyncState(eventUid3)).isEqualTo(State.TO_POST); - - trackedEntityInstanceStore.delete(teiUid); - } - - @Test - public void propagate_last_updated_if_previous_is_older() throws D2Error, ParseException { - Date oldDate = BaseIdentifiableObject.DATE_FORMAT.parse("1990-09-20T08:36:46.552"); - String teiUid = createTEIWithLastUpdated(oldDate); - - propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).lastUpdated()).isGreaterThan(oldDate); - trackedEntityInstanceStore.delete(teiUid); - } - - @Test - public void do_not_propagate_last_updated_if_previous_is_newer() throws D2Error, ParseException { - Date newerDate = BaseIdentifiableObject.DATE_FORMAT.parse("2990-09-20T08:36:46.552"); - String teiUid = createTEIWithLastUpdated(newerDate); - - propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).lastUpdated()).isEqualTo(newerDate); - trackedEntityInstanceStore.delete(teiUid); - } - - @Test - public void propagate_last_updated_if_previous_is_null() throws D2Error { - String teiUid = createTEIWithLastUpdated(null); - - d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).lastUpdated()).isNotNull(); - trackedEntityInstanceStore.delete(teiUid); - } - - @Test - public void propagate_tei_relationship_update() throws D2Error { - String teiUid = createTEIWithState(State.SYNCED); - RelationshipItem fromItem = RelationshipHelper.teiItem(teiUid); - - propagator.propagateRelationshipUpdate(fromItem); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(State.TO_UPDATE); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - - trackedEntityInstanceStore.delete(teiUid); - } - - @Test - public void propagate_enrollment_relationship_update() throws D2Error { - String teiUid = createTEIWithState(State.SYNCED); - String enrollmentUid = createEnrollmentWithState(State.SYNCED, teiUid); - RelationshipItem fromItem = RelationshipHelper.enrollmentItem(enrollmentUid); - - propagator.propagateRelationshipUpdate(fromItem); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(State.SYNCED); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrollmentUid).syncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrollmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - - trackedEntityInstanceStore.delete(teiUid); - } - - @Test - public void propagate_event_relationship_update() throws D2Error { - String teiUid = createTEIWithState(State.SYNCED); - String enrollmentUid = createEnrollmentWithState(State.SYNCED, teiUid); - String eventUid = createEventWithState(State.SYNCED, enrollmentUid); - RelationshipItem fromItem = RelationshipHelper.eventItem(eventUid); - - propagator.propagateRelationshipUpdate(fromItem); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(State.SYNCED); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrollmentUid).syncState()).isEqualTo(State.SYNCED); - assertThat(enrollmentStore.selectByUid(enrollmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_UPDATE); - - trackedEntityInstanceStore.delete(teiUid); - } - - private void assertThatSetTeiToUpdateWhenEnrollmentPropagation(State state) throws D2Error { - String teiUid = createTEIWithState(state); - - d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - trackedEntityInstanceStore.delete(teiUid); - } - - private void assertThatDoNotSetTeiToUpdateWhenEnrollmentPropagation(State state) throws D2Error { - String teiUid = createTEIWithState(state); - - d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); - trackedEntityInstanceStore.delete(teiUid); - } - - private void assertThatSetTeiToUpdateWhenEventPropagation(State state) throws D2Error { - String teiUid = createTEIWithState(state); - - String enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - enrollmentStore.setAggregatedSyncState(enrolmentUid, state); - - propagator.propagateEventUpdate(Event.builder().uid("uid").enrollment(enrolmentUid).build()); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - trackedEntityInstanceStore.delete(teiUid); - } - - private void assertThatDoNotSetTeiToUpdateWhenEventPropagation(State state) throws D2Error { - String teiUid = createTEIWithState(state); - String enrolmentUid = createEnrollmentWithState(state, teiUid); - - d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); - assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - trackedEntityInstanceStore.delete(teiUid); - } - - private void assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State state) throws D2Error { - String teiUid = createTEIWithState(state); - String enrolmentUid = createEnrollmentWithState(state, teiUid); - String eventUid = createEventWithState(state, enrolmentUid); - - propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); - assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(State.TO_UPDATE); - trackedEntityInstanceStore.delete(teiUid); - } - - private void assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State state) throws D2Error { - String teiUid = createTEIWithState(state); - String enrolmentUid = createEnrollmentWithState(state, teiUid); - String eventUid = createEventWithState(state, enrolmentUid); - - propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()); - - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).syncState()).isEqualTo(state); - assertThat(trackedEntityInstanceStore.selectByUid(teiUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(enrollmentStore.selectByUid(enrolmentUid).syncState()).isEqualTo(state); - assertThat(enrollmentStore.selectByUid(enrolmentUid).aggregatedSyncState()).isEqualTo(State.TO_UPDATE); - assertThat(eventStore.selectByUid(eventUid).syncState()).isEqualTo(state); - trackedEntityInstanceStore.delete(teiUid); - } - - private String createTEIWithState(State state) throws D2Error { - String teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()); - trackedEntityInstanceStore.setSyncState(teiUid, state); - trackedEntityInstanceStore.setAggregatedSyncState(teiUid, state); - return teiUid; - } - - private String createEnrollmentWithState(State state, String teiUid) throws D2Error { - String enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)); - enrollmentStore.setSyncState(enrolmentUid, state); - enrollmentStore.setAggregatedSyncState(enrolmentUid, state); - return enrolmentUid; - } - - private String createEventWithState(State state, String enrolmentUid) throws D2Error { - String eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)); - eventStore.setSyncState(eventUid, state); - return eventUid; - } - - private String createTEIWithLastUpdated(Date lastUpdated) throws D2Error { - String teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()); - - TrackedEntityInstance existingTEI = trackedEntityInstanceStore.selectByUid(teiUid); - trackedEntityInstanceStore.update(existingTEI.toBuilder().lastUpdated(lastUpdated).build()); - - return teiUid; - } - - private TrackedEntityInstanceCreateProjection sampleTEIProjection() { - return TrackedEntityInstanceCreateProjection.create("DiszpKrYNg8", "nEenWmSyUEp"); - } - - private EnrollmentCreateProjection sampleEnrollmentProjection(String teiUid) { - return EnrollmentCreateProjection.create("DiszpKrYNg8", "lxAQ7Zs9VYR", teiUid); - } - - private EventCreateProjection sampleEventProjection(String enrollmentUid) { - return EventCreateProjection.create(enrollmentUid, "lxAQ7Zs9VYR", "dBwrot7S420", - "DiszpKrYNg8", "bRowv6yZOF2"); - } -} \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt new file mode 100644 index 0000000000..7c130239b3 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2004-2021, 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.core.common.internal + +import androidx.test.runner.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import java.io.IOException +import java.text.ParseException +import java.util.* +import org.hisp.dhis.android.core.common.BaseIdentifiableObject +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.enrollment.EnrollmentCreateProjection +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStoreImpl.Companion.create +import org.hisp.dhis.android.core.event.EventCreateProjection +import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.event.internal.EventStoreImpl +import org.hisp.dhis.android.core.maintenance.D2Error +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceCreateProjection +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStoreImpl +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatcher() { + private lateinit var propagator: DataStatePropagator + private lateinit var trackedEntityInstanceStore: TrackedEntityInstanceStore + private lateinit var enrollmentStore: EnrollmentStore + private lateinit var eventStore: EventStore + + @Before + @Throws(IOException::class) + fun setUp() { + trackedEntityInstanceStore = TrackedEntityInstanceStoreImpl.create(d2.databaseAdapter()) + enrollmentStore = create(d2.databaseAdapter()) + eventStore = EventStoreImpl.create(d2.databaseAdapter()) + propagator = DataStatePropagatorImpl(trackedEntityInstanceStore, enrollmentStore, eventStore) + } + + @Test + @Throws(D2Error::class) + fun set_parent_state_to_update_if_has_synced_state() { + assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.SYNCED) + assertThatSetTeiToUpdateWhenEventPropagation(State.SYNCED) + assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.SYNCED) + } + + @Test + @Throws(D2Error::class) + fun set_parent_state_to_update_if_has_to_update_state() { + assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.TO_UPDATE) + assertThatSetTeiToUpdateWhenEventPropagation(State.TO_UPDATE) + assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.TO_UPDATE) + } + + @Test + @Throws(D2Error::class) + fun set_parent_state_to_update_if_has_to_post_state() { + assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.TO_POST) + assertThatSetTeiToUpdateWhenEventPropagation(State.TO_POST) + assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.TO_POST) + } + + @Test + @Throws(D2Error::class) + fun set_parent_state_to_update_if_has_to_update_synced_via_sms() { + assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.SYNCED_VIA_SMS) + assertThatSetTeiToUpdateWhenEventPropagation(State.SYNCED_VIA_SMS) + assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.SYNCED_VIA_SMS) + } + + @Test + @Throws(D2Error::class) + fun set_parent_state_to_update_if_has_to_update_sent_via_sms() { + assertThatSetTeiToUpdateWhenEnrollmentPropagation(State.SENT_VIA_SMS) + assertThatSetTeiToUpdateWhenEventPropagation(State.SENT_VIA_SMS) + assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.SENT_VIA_SMS) + } + + @Test + @Throws(D2Error::class) + fun do_not_set_parent_state_to_update_if_has_error_state() { + assertThatDoNotSetTeiToUpdateWhenEnrollmentPropagation(State.ERROR) + assertThatDoNotSetTeiToUpdateWhenEventPropagation(State.ERROR) + assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.ERROR) + } + + @Test + @Throws(D2Error::class) + fun do_not_set_parent_state_to_update_if_has_warning_state() { + assertThatDoNotSetTeiToUpdateWhenEnrollmentPropagation(State.WARNING) + assertThatDoNotSetTeiToUpdateWhenEventPropagation(State.WARNING) + assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation(State.WARNING) + } + + @Test + @Throws(D2Error::class) + fun do_not_fail_with_events_without_registration() { + val eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(null)) + + assertThat(eventStore.selectByUid(eventUid)!!.syncState()).isEqualTo(State.TO_POST) + + eventStore.delete(eventUid) + } + + @Test + @Throws(D2Error::class) + fun reset_enrollment_and_event_states_if_uploading() { + val teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()) + val enrolmentUid1 = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + val enrolmentUid2 = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + val eventUid1 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid1)) + val eventUid2 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid1)) + val eventUid3 = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid2)) + + enrollmentStore.setSyncState(enrolmentUid1, State.UPLOADING) + eventStore.setSyncState(eventUid1, State.UPLOADING) + propagator.resetUploadingEnrollmentAndEventStates(teiUid) + + assertThat(enrollmentStore.getSyncState(enrolmentUid1)).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.getSyncState(enrolmentUid2)).isEqualTo(State.TO_POST) + + assertThat(eventStore.getSyncState(eventUid1)).isEqualTo(State.TO_UPDATE) + assertThat(eventStore.getSyncState(eventUid2)).isEqualTo(State.TO_POST) + assertThat(eventStore.getSyncState(eventUid3)).isEqualTo(State.TO_POST) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Test + @Throws(D2Error::class, ParseException::class) + fun propagate_last_updated_if_previous_is_older() { + val oldDate = BaseIdentifiableObject.DATE_FORMAT.parse("1990-09-20T08:36:46.552") + val teiUid = createTEIWithLastUpdated(oldDate) + + propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.lastUpdated()).isGreaterThan(oldDate) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Test + @Throws(D2Error::class, ParseException::class) + fun do_not_propagate_last_updated_if_previous_is_newer() { + val newerDate = BaseIdentifiableObject.DATE_FORMAT.parse("2990-09-20T08:36:46.552") + val teiUid = createTEIWithLastUpdated(newerDate) + + propagator.propagateEnrollmentUpdate(Enrollment.builder().uid("uid").trackedEntityInstance(teiUid).build()) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.lastUpdated()).isEqualTo(newerDate) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Test + @Throws(D2Error::class) + fun propagate_last_updated_if_previous_is_null() { + val teiUid = createTEIWithLastUpdated(null) + d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.lastUpdated()).isNotNull() + + trackedEntityInstanceStore.delete(teiUid) + } + + @Test + @Throws(D2Error::class) + fun propagate_tei_relationship_update() { + val teiUid = createTEIWithState(State.SYNCED) + val fromItem = RelationshipHelper.teiItem(teiUid) + + propagator.propagateRelationshipUpdate(fromItem) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.TO_UPDATE) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Test + @Throws(D2Error::class) + fun propagate_enrollment_relationship_update() { + val teiUid = createTEIWithState(State.SYNCED) + val enrollmentUid = createEnrollmentWithState(State.SYNCED, teiUid) + val fromItem = RelationshipHelper.enrollmentItem(enrollmentUid) + + propagator.propagateRelationshipUpdate(fromItem) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.SYNCED) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.syncState()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Test + @Throws(D2Error::class) + fun propagate_event_relationship_update() { + val teiUid = createTEIWithState(State.SYNCED) + val enrollmentUid = createEnrollmentWithState(State.SYNCED, teiUid) + val eventUid = createEventWithState(State.SYNCED, enrollmentUid) + val fromItem = RelationshipHelper.eventItem(eventUid) + + propagator.propagateRelationshipUpdate(fromItem) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.SYNCED) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.syncState()).isEqualTo(State.SYNCED) + assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + assertThat(eventStore.selectByUid(eventUid)!!.syncState()).isEqualTo(State.TO_UPDATE) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun assertThatSetTeiToUpdateWhenEnrollmentPropagation(state: State) { + val teiUid = createTEIWithState(state) + d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(state) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun assertThatDoNotSetTeiToUpdateWhenEnrollmentPropagation(state: State) { + val teiUid = createTEIWithState(state) + d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(state) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(state) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun assertThatSetTeiToUpdateWhenEventPropagation(state: State) { + val teiUid = createTEIWithState(state) + val enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + + enrollmentStore.setSyncState(enrolmentUid, state) + enrollmentStore.setAggregatedSyncState(enrolmentUid, state) + + d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(state) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.syncState()).isEqualTo(state) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun assertThatDoNotSetTeiToUpdateWhenEventPropagation(state: State) { + val teiUid = createTEIWithState(state) + val enrolmentUid = createEnrollmentWithState(state, teiUid) + + d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(state) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(state) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.syncState()).isEqualTo(state) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.aggregatedSyncState()).isEqualTo(state) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun assertThatSetTeiToUpdateWhenTrackedEntityDataValuePropagation(state: State) { + val teiUid = createTEIWithState(state) + val enrolmentUid = createEnrollmentWithState(state, teiUid) + val eventUid = createEventWithState(state, enrolmentUid) + + propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(state) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.syncState()).isEqualTo(state) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) + assertThat(eventStore.selectByUid(eventUid)!!.syncState()).isIn(listOf(State.TO_POST, State.TO_UPDATE)) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun assertThatDoNotSetTeiToUpdateWhenTrackedEntityDataValuePropagation(state: State) { + val teiUid = createTEIWithState(state) + val enrolmentUid = createEnrollmentWithState(state, teiUid) + val eventUid = createEventWithState(state, enrolmentUid) + + propagator.propagateTrackedEntityDataValueUpdate(TrackedEntityDataValue.builder().event(eventUid).build()) + + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(state) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(state) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.syncState()).isEqualTo(state) + assertThat(enrollmentStore.selectByUid(enrolmentUid)!!.aggregatedSyncState()).isEqualTo(state) + assertThat(eventStore.selectByUid(eventUid)!!.syncState()).isIn(listOf(State.TO_POST, State.TO_UPDATE)) + + trackedEntityInstanceStore.delete(teiUid) + } + + @Throws(D2Error::class) + private fun createTEIWithState(state: State): String { + val teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()) + + trackedEntityInstanceStore.setSyncState(teiUid, state) + trackedEntityInstanceStore.setAggregatedSyncState(teiUid, state) + + return teiUid + } + + @Throws(D2Error::class) + private fun createEnrollmentWithState(state: State, teiUid: String): String { + val enrolmentUid = d2.enrollmentModule().enrollments().blockingAdd(sampleEnrollmentProjection(teiUid)) + + enrollmentStore.setSyncState(enrolmentUid, state) + enrollmentStore.setAggregatedSyncState(enrolmentUid, state) + + return enrolmentUid + } + + @Throws(D2Error::class) + private fun createEventWithState(state: State, enrolmentUid: String): String { + val eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)) + + eventStore.setSyncState(eventUid, state) + + return eventUid + } + + @Throws(D2Error::class) + private fun createTEIWithLastUpdated(lastUpdated: Date?): String { + val teiUid = d2.trackedEntityModule().trackedEntityInstances().blockingAdd(sampleTEIProjection()) + val existingTEI = trackedEntityInstanceStore.selectByUid(teiUid) + + trackedEntityInstanceStore.update(existingTEI!!.toBuilder().lastUpdated(lastUpdated).build()) + + return teiUid + } + + private fun sampleTEIProjection(): TrackedEntityInstanceCreateProjection { + return TrackedEntityInstanceCreateProjection.create("DiszpKrYNg8", "nEenWmSyUEp") + } + + private fun sampleEnrollmentProjection(teiUid: String): EnrollmentCreateProjection { + return EnrollmentCreateProjection.create("DiszpKrYNg8", "lxAQ7Zs9VYR", teiUid) + } + + private fun sampleEventProjection(enrollmentUid: String?): EventCreateProjection { + return EventCreateProjection.create( + enrollmentUid, "lxAQ7Zs9VYR", "dBwrot7S420", + "DiszpKrYNg8", "bRowv6yZOF2" + ) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/EnumHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/EnumHelper.kt similarity index 79% rename from core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/EnumHelper.java rename to core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/EnumHelper.kt index 3854c2a2a3..e91d04860c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/EnumHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/EnumHelper.kt @@ -25,22 +25,17 @@ * (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.arch.helpers.internal -package org.hisp.dhis.android.core.arch.helpers.internal; +internal object EnumHelper { -import java.util.ArrayList; -import java.util.List; - -public final class EnumHelper { - - public static List asStringList(Enum... enums) { - List enumsStr = new ArrayList<>(enums.length); - for (Enum e: enums) { - enumsStr.add(e.name()); - } - return enumsStr; + @JvmStatic + fun asStringList(enums: Collection>): List { + return enums.map { it.name } } - private EnumHelper() { + @JvmStatic + fun asStringList(vararg enums: Enum<*>): List { + return asStringList(enums.toList()) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/State.java b/core/src/main/java/org/hisp/dhis/android/core/common/State.kt similarity index 76% rename from core/src/main/java/org/hisp/dhis/android/core/common/State.java rename to core/src/main/java/org/hisp/dhis/android/core/common/State.kt index 2df0f123d7..d6b43c531d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/State.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/State.kt @@ -25,33 +25,32 @@ * (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.common -package org.hisp.dhis.android.core.common; - -public enum State { - /** Data created locally that does not exist in the server yet. */ +enum class State { + /** Data created locally that does not exist in the server yet. */ TO_POST, - /** Data modified locally that exists in the server. */ + /** Data modified locally that exists in the server. */ TO_UPDATE, - /** Data that received an error from the server after the last upload. */ + /** Data that received an error from the server after the last upload. */ ERROR, - /** The element is synced with the server. There are no local changes for this value. */ + /** The element is synced with the server. There are no local changes for this value. */ SYNCED, - /** Data that received a warning from the server after the last upload. */ + /** Data that received a warning from the server after the last upload. */ WARNING, /** Data is being uploaded. If it is modified before receiving any server response, its state is back to - * TO_UPDATE. When the server response arrives, its state does not change to SYNCED, - * but it remains in TO_UPDATE to indicate that there are local changes. + * **TO_UPDATE**. When the server response arrives, its state does not change to **SYNCED**, + * but it remains in **TO_UPDATE** to indicate that there are local changes. */ UPLOADING, /** This TrackedEntityInstance has been downloaded with the sole purpose of fulfilling a relationship to another - * TEI. This RELATIONSHIP TEI only has basic information (uid, type, etc) and the list of + * TEI. This **RELATIONSHIP** TEI only has basic information (uid, type, etc) and the list of * TrackedEntityAttributes to be able to print meaningful information about the relationship. Other data such * enrollments, events or relationships is not downloaded for this TEI. * Also, this TEI cannot be modified or uploaded to the server. @@ -64,18 +63,19 @@ public enum State { */ SENT_VIA_SMS, - /** Data is sent by sms and there is a successful response from the server. */ + /** Data is sent by sms and there is a successful response from the server. */ SYNCED_VIA_SMS; - public static State[] uploadableStates() { - return new State[] { - TO_POST, TO_UPDATE, SENT_VIA_SMS, SYNCED_VIA_SMS, UPLOADING - }; - } + companion object { + + @JvmStatic + fun uploadableStates(): Array { + return arrayOf(TO_POST, TO_UPDATE, SENT_VIA_SMS, SYNCED_VIA_SMS, UPLOADING) + } - public static State[] uploadableStatesIncludingError() { - return new State[] { - TO_POST, TO_UPDATE, SENT_VIA_SMS, SYNCED_VIA_SMS, UPLOADING, ERROR, WARNING - }; + @JvmStatic + fun uploadableStatesIncludingError(): Array { + return arrayOf(TO_POST, TO_UPDATE, SENT_VIA_SMS, SYNCED_VIA_SMS, UPLOADING, ERROR, WARNING) + } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index 6362830ce8..4766719b72 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -55,4 +55,4 @@ interface DataStatePropagator { fun refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid: String) fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 2599d4457d..e911bbf0b4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.common.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment @@ -40,12 +42,10 @@ import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore -import java.util.* -import javax.inject.Inject @Reusable +@Suppress("TooManyFunctions") internal class DataStatePropagatorImpl @Inject internal constructor( private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentStore: EnrollmentStore, @@ -237,11 +237,11 @@ internal class DataStatePropagatorImpl @Inject internal constructor( states.contains(State.ERROR) -> State.ERROR states.contains(State.WARNING) -> State.WARNING states.contains(State.UPLOADING) || - states.contains(State.SENT_VIA_SMS) || - states.contains(State.SYNCED_VIA_SMS) || - states.contains(State.TO_POST) || - states.contains(State.TO_UPDATE) -> State.TO_UPDATE + states.contains(State.SENT_VIA_SMS) || + states.contains(State.SYNCED_VIA_SMS) || + states.contains(State.TO_POST) || + states.contains(State.TO_UPDATE) -> State.TO_UPDATE else -> State.SYNCED } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java index ddebf516cc..c12522a81e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/internal/DataSetInstanceSummarySQLStatementBuilder.java @@ -29,7 +29,6 @@ package org.hisp.dhis.android.core.dataset.internal; import org.hisp.dhis.android.core.arch.db.sqlorder.internal.SQLOrderType; -import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.DeletableDataColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.dataset.DataSetTableInfo; diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java index c6feabff3b..6e4d4fdd97 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java @@ -65,6 +65,7 @@ import java.util.List; @AutoValue +@SuppressWarnings("PMD.ExcessiveImports") @JsonDeserialize(builder = AutoValue_Enrollment.Builder.class) public abstract class Enrollment extends BaseDeletableDataObject implements ObjectWithUidInterface { diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt index be31709f58..c77f33ebe9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.enrollment.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState @@ -48,8 +50,6 @@ import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.note.NoteTableInfo -import java.util.* -import javax.inject.Inject @Reusable internal class EnrollmentImportHandler @Inject constructor( @@ -120,7 +120,7 @@ internal class EnrollmentImportHandler @Inject constructor( val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST val whereClause = WhereClauseBuilder() .appendInKeyStringValues( - DataColumns.SYNC_STATE, EnumHelper.asStringList(*State.uploadableStatesIncludingError()) + DataColumns.SYNC_STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError().toList()) ) .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build() val notes = noteStore.selectWhere(whereClause) @@ -175,4 +175,4 @@ internal class EnrollmentImportHandler @Inject constructor( .status(enrollmentImportSummary.status()) .created(Date()) } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt index 6493d61078..f09b01b412 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt @@ -40,4 +40,4 @@ internal interface EnrollmentStore : IdentifiableDeletableDataObjectStore -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt index f06f565ab6..0fb6846f5b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt @@ -55,7 +55,7 @@ internal class EnrollmentStoreImpl private constructor( val enrollmentsToPostQuery = WhereClauseBuilder() .appendInKeyStringValues( DataColumns.AGGREGATED_SYNC_STATE, - EnumHelper.asStringList(*State.uploadableStatesIncludingError()) + EnumHelper.asStringList(State.uploadableStatesIncludingError().toList()) ).build() val enrollmentList: List = selectWhere(enrollmentsToPostQuery) @@ -122,4 +122,4 @@ internal class EnrollmentStoreImpl private constructor( ) { cursor: Cursor? -> Enrollment.create(cursor) } } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt index f79acfd5e3..e4a2fa56ea 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.event.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State @@ -40,8 +42,6 @@ import org.hisp.dhis.android.core.imports.internal.EventImportSummary import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEventHandler -import java.util.* -import javax.inject.Inject @Reusable internal class EventImportHandler @Inject constructor( @@ -125,4 +125,4 @@ internal class EventImportHandler @Inject constructor( .status(eventImportSummary.status()) .created(Date()) } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index 45bf761979..e9fcbbd5f6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Transformer @@ -43,7 +44,6 @@ import org.hisp.dhis.android.core.note.NewTrackerImporterNote import org.hisp.dhis.android.core.note.NewTrackerImporterNoteTransformer import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.trackedentity.* -import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt index a440819f7f..3339f21d2e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State @@ -46,8 +48,6 @@ import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo -import java.util.* -import javax.inject.Inject @Reusable internal class TrackedEntityInstanceImportHandler @Inject internal constructor( @@ -83,10 +83,7 @@ internal class TrackedEntityInstanceImportHandler @Inject internal constructor( if (handleAction !== HandleAction.Delete) { storeTEIImportConflicts(teiImportSummary) - teiImportSummary.enrollments()?.importSummaries().let { - enrollmentImportHandler.handleEnrollmentImportSummary(it, - getEnrollments(teiUid, instances), teiUid) - } + handleEnrollmentImportSummaries(teiImportSummary, instances) } } } @@ -94,6 +91,20 @@ internal class TrackedEntityInstanceImportHandler @Inject internal constructor( processIgnoredTEIs(teiImportSummaries, instances) } + private fun handleEnrollmentImportSummaries( + teiImportSummary: TEIImportSummary, + instances: List + ) { + teiImportSummary.enrollments()?.importSummaries().let { importSummaries -> + val teiUid = teiImportSummary.reference()!! + enrollmentImportHandler.handleEnrollmentImportSummary( + importSummaries, + getEnrollments(teiUid, instances), + teiUid + ) + } + } + private fun storeTEIImportConflicts(teiImportSummary: TEIImportSummary) { val trackerImportConflicts: MutableList = ArrayList() if (teiImportSummary.description() != null) { @@ -154,4 +165,4 @@ internal class TrackedEntityInstanceImportHandler @Inject internal constructor( .status(teiImportSummary.status()) .created(Date()) } -} \ No newline at end of file +} From 51d9d5e224339c84ee6aaddb7df480a057d968d3 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 2 Jul 2021 12:42:50 +0200 Subject: [PATCH 107/308] [ANDROSDK-1395] Remove uses of deprecated methods --- .../EnrollmentStoreIntegrationShould.java | 6 +++-- ...FileResourceCallRealIntegrationShould.java | 2 +- ...EntityDataValueStoreIntegrationShould.java | 3 ++- ...tityInstanceCallMockIntegrationShould.java | 5 ++-- ...InstancePostCallRealIntegrationShould.java | 6 ++--- ...stPayloadGeneratorMockIntegrationShould.kt | 25 ++++++++++--------- ...dEntityInstanceStoreIntegrationShould.java | 6 +++-- ...ObjectRepositoryMockIntegrationShould.java | 2 +- ...ObjectRepositoryMockIntegrationShould.java | 14 +++++------ .../arch/helpers/internal/DataStateHelper.kt | 2 +- ...dWriteWithUidDataObjectRepositoryImpl.java | 10 ++++---- ...eadWriteWithValueObjectRepositoryImpl.java | 8 +++--- ...tCompleteRegistrationObjectRepository.java | 5 ++-- .../datavalue/DataValueObjectRepository.java | 4 +-- .../core/event/EventObjectRepository.java | 2 +- .../RelationshipOrphanCleanerImpl.java | 2 +- .../internal/StatePersistorHelper.kt | 2 +- .../TrackedEntityInstanceHandler.java | 6 ++--- .../data/enrollment/EnrollmentSamples.java | 3 ++- .../TrackedEntityInstanceSamples.java | 3 ++- .../RelationshipDHISVersionManagerShould.java | 4 +-- .../TrackedEntityInstanceHandlerShould.java | 4 +-- 22 files changed, 66 insertions(+), 58 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreIntegrationShould.java index 693e963927..40bb44f7bf 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreIntegrationShould.java @@ -60,7 +60,8 @@ protected Enrollment buildObjectToUpdate() { @Override protected Enrollment buildObjectWithToDeleteState() { return EnrollmentSamples.get().toBuilder() - .state(State.TO_UPDATE) + .syncState(State.TO_UPDATE) + .aggregatedSyncState(State.TO_UPDATE) .deleted(true) .build(); } @@ -68,7 +69,8 @@ protected Enrollment buildObjectWithToDeleteState() { @Override protected Enrollment buildObjectWithSyncedState() { return EnrollmentSamples.get().toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) + .aggregatedSyncState(State.SYNCED) .build(); } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallRealIntegrationShould.java index d45c8ff02c..0b23cb5b25 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/fileresource/internal/FileResourceCallRealIntegrationShould.java @@ -110,7 +110,7 @@ public void write_tracked_entity_attribute_related_files_and_upload() throws Exc TrackedEntityInstance trackedEntityInstance2 = d2.trackedEntityModule().trackedEntityInstances().blockingGet().get(0); - assertThat(trackedEntityInstance2.state()).isEqualTo(State.SYNCED); + assertThat(trackedEntityInstance2.syncState()).isEqualTo(State.SYNCED); } //@Test diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java index 5844c15ac9..89aaa6d03c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreIntegrationShould.java @@ -155,7 +155,8 @@ public void select_tracker_data_values() { EnrollmentStore enrollmentStore = EnrollmentStoreImpl.create(TestDatabaseAdapterFactory.get()); Enrollment enrollment = Enrollment.builder().uid("enrollment").organisationUnit("organisation_unit") - .program("program").trackedEntityInstance("tei_uid").state(State.TO_POST).build(); + .program("program").trackedEntityInstance("tei_uid") + .aggregatedSyncState(State.TO_POST).syncState(State.TO_POST).build(); enrollmentStore.insert(enrollment); EventStore eventStore = EventStoreImpl.create(TestDatabaseAdapterFactory.get()); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java index 9e9bfb0a5f..df1bb7cfbf 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceCallMockIntegrationShould.java @@ -210,7 +210,7 @@ private TrackedEntityInstance getDownloadedTei(String teiUid) { List downloadedEnrollmentsWithoutIdAndDeleteFalse = new ArrayList<>(); for (Enrollment enrollment : downloadedEnrollments) { downloadedEnrollmentsWithoutIdAndDeleteFalse.add( - enrollment.toBuilder().id(null).deleted(false).state(null).notes(new ArrayList<>()).build()); + enrollment.toBuilder().id(null).deleted(false).notes(new ArrayList<>()).build()); } EventStore eventStore = EventStoreImpl.create(databaseAdapter); @@ -219,7 +219,7 @@ private TrackedEntityInstance getDownloadedTei(String teiUid) { List downloadedEventsWithoutValuesAndDeleteFalse = new ArrayList<>(); for (Event event : downloadedEventsWithoutValues) { downloadedEventsWithoutValuesAndDeleteFalse.add( - event.toBuilder().id(null).deleted(false).syncState(null).build()); + event.toBuilder().id(null).deleted(false).build()); } List dataValueList = TrackedEntityDataValueStoreImpl.create(databaseAdapter).selectAll(); @@ -282,7 +282,6 @@ private TrackedEntityInstance createTei(TrackedEntityInstance downloadedTei, downloadedTei.toBuilder(), relationships), downloadedEnrollments) .id(null) - .state(null) .deleted(false) .trackedEntityAttributeValues(attValuesWithoutIdAndTEI) .build(); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java index 4facca0205..7db558c6c6 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java @@ -505,8 +505,8 @@ private void insertATei(String uid, TrackedEntityInstance tei, Geometry geometry TrackedEntityInstance trackedEntityInstance = tei.toBuilder() .uid(uid) .geometry(geometry) - .state(State.TO_POST) .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .build(); trackedEntityInstanceStore.insert(trackedEntityInstance); @@ -526,8 +526,8 @@ private void createDummyDataToPost(String orgUnitUid, String programUid, String .organisationUnit(orgUnitUid) .trackedEntityType(trackedEntityUid) .geometry(geometry) - .state(State.TO_POST) .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .build(); trackedEntityInstanceStore.insert(trackedEntityInstance); @@ -537,7 +537,7 @@ private void createDummyDataToPost(String orgUnitUid, String programUid, String .program(programUid).incidentDate(refDate).completedDate(refDate).enrollmentDate(refDate) .followUp(Boolean.FALSE).status(EnrollmentStatus.ACTIVE).trackedEntityInstance(trackedEntityInstanceUid) .geometry(Geometry.builder().type(FeatureType.POINT).coordinates("[10.33, 12.231]").build()) - .state(State.TO_POST).syncState(State.TO_POST).build(); + .syncState(State.TO_POST).aggregatedSyncState(State.TO_POST).build(); enrollmentStore.insert(enrollment); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt index e705d65f06..1397915057 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt @@ -263,22 +263,22 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI d2.trackedEntityModule().trackedEntityInstances().blockingUpload() val instance = teiStore.selectFirst() - assertThat(instance!!.state()).isEqualTo(State.TO_POST) + assertThat(instance!!.syncState()).isEqualTo(State.TO_POST) val enrollments = enrollmentStore.selectAll() for (enrollment in enrollments) { if (enrollment1Id == enrollment.uid() || enrollment2Id == enrollment.uid()) { - assertThat(enrollment.state()).isEqualTo(State.TO_POST) + assertThat(enrollment.syncState()).isEqualTo(State.TO_POST) } } val events = eventStore.selectAll() for (event in events) { if (event1Id == event.uid()) { - assertThat(event.state()).isEqualTo(State.TO_UPDATE) + assertThat(event.syncState()).isEqualTo(State.TO_UPDATE) } if (event2Id == event.uid()) { - assertThat(event.state()).isEqualTo(State.SYNCED_VIA_SMS) + assertThat(event.syncState()).isEqualTo(State.SYNCED_VIA_SMS) } } } @@ -352,16 +352,16 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI d2.trackedEntityModule().trackedEntityInstances().blockingUpload() val trackedEntityInstance = teiStore.selectByUid(teiId) - assertThat(trackedEntityInstance!!.state()).isEqualTo(State.TO_UPDATE) - assertThat(trackedEntityInstance.syncState()).isEqualTo(State.SYNCED) + assertThat(trackedEntityInstance!!.syncState()).isEqualTo(State.SYNCED) + assertThat(trackedEntityInstance.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) - assertThat(enrollmentStore.selectByUid(enrollment1Id)!!.state()).isEqualTo(State.TO_UPDATE) assertThat(enrollmentStore.selectByUid(enrollment1Id)!!.syncState()).isEqualTo(State.SYNCED) - assertThat(enrollmentStore.selectByUid(enrollment2Id)!!.state()).isEqualTo(State.SYNCED) + assertThat(enrollmentStore.selectByUid(enrollment1Id)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) assertThat(enrollmentStore.selectByUid(enrollment2Id)!!.syncState()).isEqualTo(State.SYNCED) + assertThat(enrollmentStore.selectByUid(enrollment2Id)!!.aggregatedSyncState()).isEqualTo(State.SYNCED) - assertThat(eventStore.selectByUid(event1Id)!!.state()).isEqualTo(State.TO_UPDATE) - assertThat(eventStore.selectByUid(event2Id)!!.state()).isEqualTo(State.SYNCED) + assertThat(eventStore.selectByUid(event1Id)!!.syncState()).isEqualTo(State.TO_UPDATE) + assertThat(eventStore.selectByUid(event2Id)!!.syncState()).isEqualTo(State.SYNCED) } private fun storeTrackedEntityInstance() { @@ -462,7 +462,8 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .uid(teiUid) .trackedEntityType(teiType!!.uid()) .organisationUnit(orgUnit!!.uid()) - .state(state) + .syncState(state) + .aggregatedSyncState(state) .build() ) } @@ -518,7 +519,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI @JvmStatic @Throws(Exception::class) fun setUp() { - BaseMockIntegrationTestMetadataEnqueable.setUpClass() + setUpClass() payloadGenerator = objects.d2DIComponent.trackedEntityInstancePostPayloadGenerator() teiStore = TrackedEntityInstanceStoreImpl.create(databaseAdapter) teiDataValueStore = TrackedEntityDataValueStoreImpl.create(databaseAdapter) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreIntegrationShould.java index 9021ead822..e886b0d2b2 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceStoreIntegrationShould.java @@ -61,7 +61,8 @@ protected TrackedEntityInstance buildObjectToUpdate() { @Override protected TrackedEntityInstance buildObjectWithToDeleteState() { return TrackedEntityInstanceSamples.get().toBuilder() - .state(State.TO_UPDATE) + .syncState(State.TO_UPDATE) + .aggregatedSyncState(State.TO_UPDATE) .deleted(true) .build(); } @@ -69,7 +70,8 @@ protected TrackedEntityInstance buildObjectWithToDeleteState() { @Override protected TrackedEntityInstance buildObjectWithSyncedState() { return TrackedEntityInstanceSamples.get().toBuilder() - .state(State.SYNCED) + .syncState(State.SYNCED) + .aggregatedSyncState(State.SYNCED) .build(); } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java index aa0b8fb1d2..5ef36bec2a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/dataset/DataSetCompleteRegistrationObjectRepositoryMockIntegrationShould.java @@ -57,7 +57,7 @@ public void delete() { DataSetCompleteRegistration dataSetCompleteRegistration = objectRepository().blockingGet(); assertThat(dataSetCompleteRegistration.deleted()).isTrue(); - assertThat(dataSetCompleteRegistration.state()).isEqualTo(State.TO_UPDATE); + assertThat(dataSetCompleteRegistration.syncState()).isEqualTo(State.TO_UPDATE); } @Test diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java index 6f971f4b29..929ca2508f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java @@ -84,7 +84,7 @@ public void delete_value_if_state_to_post() throws D2Error { repository.blockingSet("value"); assertThat(repository.blockingExists()).isEqualTo(Boolean.TRUE); - assertThat(repository.blockingGet().state()).isEqualTo(State.TO_POST); + assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_POST); repository.blockingDelete(); assertThat(repository.blockingExists()).isEqualTo(Boolean.FALSE); } @@ -96,11 +96,11 @@ public void set_state_to_delete_if_state_is_not_to_post() throws D2Error { repository.blockingSet("value"); DataValueStore.create(databaseAdapter).setState(repository.blockingGet(), State.ERROR); assertThat(repository.blockingExists()).isEqualTo(Boolean.TRUE); - assertThat(repository.blockingGet().state()).isEqualTo(State.ERROR); + assertThat(repository.blockingGet().syncState()).isEqualTo(State.ERROR); repository.blockingDelete(); assertThat(repository.blockingExists()).isEqualTo(Boolean.TRUE); - assertThat(repository.blockingGet().deleted()).isEqualTo(Boolean.TRUE); - assertThat(repository.blockingGet().state()).isEqualTo(State.TO_UPDATE); + assertThat(repository.blockingGet().syncState()).isEqualTo(Boolean.TRUE); + assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); } @Test @@ -111,12 +111,12 @@ public void set_not_deleted_when_updating_deleted_value() throws D2Error { DataValueStore.create(databaseAdapter).setState(repository.blockingGet(), State.TO_UPDATE); repository.blockingDelete(); - assertThat(repository.blockingGet().state()).isEqualTo(State.TO_UPDATE); + assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); assertThat(repository.blockingGet().deleted()).isEqualTo(Boolean.TRUE); repository.blockingSet("new_value"); - assertThat(repository.blockingGet().state()).isEqualTo(State.TO_UPDATE); - assertThat(repository.blockingGet().deleted()).isEqualTo(Boolean.FALSE); + assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); + assertThat(repository.blockingGet().syncState()).isEqualTo(Boolean.FALSE); } @Test diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/DataStateHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/DataStateHelper.kt index 0f1d56b38e..0187a9d02c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/DataStateHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/helpers/internal/DataStateHelper.kt @@ -40,6 +40,6 @@ object DataStateHelper { @JvmStatic fun forcedOrOwn(o: DataObject, forcedState: State?): State { - return forcedState ?: o.state() + return forcedState ?: o.syncState() } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java index 7a81425ab6..0ad285333d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithUidDataObjectRepositoryImpl.java @@ -64,7 +64,7 @@ public ReadWriteWithUidDataObjectRepositoryImpl(IdentifiableDeletableDataObjectS } /** - * Removes the object in scope in an asynchronous way. Field {@link DataObject#state()} is marked as + * Removes the object in scope in an asynchronous way. Field {@link DataObject#syncState()} is marked as * {@link State#TO_UPDATE} and {@link DeletableDataObject#deleted()} as true. In the next upload, it will be deleted * in the server. It returns a {@code Completable} that completes as soon as the object is deleted in the database. * The {@code Completable} fails if the object doesn't exist. @@ -76,7 +76,7 @@ public Completable delete() { } /** - * Removes the object in scope in a synchronous way. Field {@link DataObject#state()} is marked as + * Removes the object in scope in a synchronous way. Field {@link DataObject#syncState()} is marked as * {@link State#TO_UPDATE} and {@link DeletableDataObject#deleted()} as true. In the next upload, it will be deleted * in the server. It blocks the thread and finishes as soon as the object is deleted in the database. * It throws an exception if the object doesn't exist. @@ -97,7 +97,7 @@ public void blockingDelete() throws D2Error { .errorDescription("Tried to delete non existing object") .build(); } else { - if (object.state() == State.TO_POST) { + if (object.syncState() == State.TO_POST) { store.delete(object.uid()); } else { store.setDeleted(object.uid()); @@ -108,7 +108,7 @@ public void blockingDelete() throws D2Error { } /** - * Removes the object in scope in a synchronous way. Field {@link DataObject#state()} is marked as + * Removes the object in scope in a synchronous way. Field {@link DataObject#syncState()} is marked as * {@link State#TO_POST} and {@link DeletableDataObject#deleted()} as true. Unlike {@link #delete()}, * it doesn't throw an exception if the object doesn't exist. * It returns a {@code Completable} that completes as soon as the object is deleted in the database. @@ -120,7 +120,7 @@ public Completable deleteIfExist() { } /** - * Removes the object in scope in an asynchronous way. Field {@link DataObject#state()} is marked as + * Removes the object in scope in an asynchronous way. Field {@link DataObject#syncState()} is marked as * {@link State#TO_POST} and {@link DeletableDataObject#deleted()} as true. * Unlike {@link #blockingDelete()}, it doesn't throw an exception if the object doesn't exist. * It blocks the thread and finishes as soon as the object is deleted in the database. diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithValueObjectRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithValueObjectRepositoryImpl.java index 547b1da833..987694851e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithValueObjectRepositoryImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/object/internal/ReadWriteWithValueObjectRepositoryImpl.java @@ -60,7 +60,7 @@ public ReadWriteWithValueObjectRepositoryImpl(ObjectWithoutUidStore store, /** * Removes the object in scope in an asynchronous way. It removes the value in the database and propagates - * the changes to modify the {@link DataObject#state()} of the parent, so it's updated in the server in + * the changes to modify the {@link DataObject#syncState()} of the parent, so it's updated in the server in * the next upload. * It returns a {@code Completable} that completes as soon as the object is deleted in the database. * The {@code Completable} fails if the object doesn't exist. @@ -73,7 +73,7 @@ public Completable delete() { /** * Removes the object in scope in a synchronous way. It removes the value in the database and propagates - * the changes to modify the {@link DataObject#state()} of the parent, so it's updated in the server in + * the changes to modify the {@link DataObject#syncState()} of the parent, so it's updated in the server in * the next upload. * It blocks the thread and finishes as soon as the object is deleted in the database. * @@ -89,7 +89,7 @@ public void blockingDelete() throws D2Error { /** * Removes the object in scope in an asynchronous way. It removes the value in the database and propagates - * the changes to modify the {@link DataObject#state()} of the parent, so it's updated in the server in + * the changes to modify the {@link DataObject#syncState()} of the parent, so it's updated in the server in * the next upload. * It returns a {@code Completable} that completes as soon as the object is deleted in the database. * Unlike {@link #delete()}, it doesn't throw an exception if the object doesn't exist. @@ -103,7 +103,7 @@ public Completable deleteIfExist() { /** * Removes the object in scope in a synchronous way. It removes the value in the database and propagates - * the changes to modify the {@link DataObject#state()} of the parent, so it's updated in the server in + * the changes to modify the {@link DataObject#syncState()} of the parent, so it's updated in the server in * the next upload. * Unlike {@link #blockingDelete()}, it doesn't throw an exception if the object doesn't exist. * It blocks the thread and finishes as soon as the object is deleted in the database. diff --git a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java index ddeb5e914c..270cd8e396 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/dataset/DataSetCompleteRegistrationObjectRepository.java @@ -106,7 +106,8 @@ public void blockingSet() { } else { DataSetCompleteRegistration newRecord = dataSetCompleteRegistration.toBuilder() .deleted(false) - .syncState(dataSetCompleteRegistration.state() == State.TO_POST ? State.TO_POST : State.TO_UPDATE) + .syncState(dataSetCompleteRegistration.syncState() == State.TO_POST ? + State.TO_POST : State.TO_UPDATE) .build(); dataSetCompleteRegistrationStore.updateWhere(newRecord); } @@ -129,7 +130,7 @@ public void blockingDelete() throws D2Error { "because no longer exists") .build(); } else { - if (dataSetCompleteRegistration.state() == State.TO_POST) { + if (dataSetCompleteRegistration.syncState() == State.TO_POST) { dataSetCompleteRegistrationStore.deleteWhere(dataSetCompleteRegistration); } else { DataSetCompleteRegistration deletedRecord = dataSetCompleteRegistration.toBuilder() diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java index 55774889c5..a7c511d591 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueObjectRepository.java @@ -95,7 +95,7 @@ public Completable delete() { @Override public void blockingDelete() throws D2Error { DataValue dataValue = blockingGetWithoutChildren(); - if (dataValue.state() == State.TO_POST) { + if (dataValue.syncState() == State.TO_POST) { super.delete(dataValue); } else { setObject(dataValue.toBuilder().deleted(true).syncState(State.TO_UPDATE).build()); @@ -106,7 +106,7 @@ private DataValue.Builder setBuilder() { Date date = new Date(); if (blockingExists()) { DataValue dataValue = blockingGetWithoutChildren(); - State state = dataValue.state() == State.TO_POST ? State.TO_POST : State.TO_UPDATE; + State state = dataValue.syncState() == State.TO_POST ? State.TO_POST : State.TO_UPDATE; return dataValue.toBuilder() .syncState(state) .lastUpdated(date); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java index 5f408e6c10..eee16c9fd8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java @@ -94,7 +94,7 @@ public Unit setAssignedUser(String assignedUser) throws D2Error { private Event.Builder updateBuilder() { Event event = blockingGetWithoutChildren(); Date updateDate = new Date(); - State state = event.state(); + State state = event.syncState(); state = state == State.TO_POST ? state : State.TO_UPDATE; return event.toBuilder() diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipOrphanCleanerImpl.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipOrphanCleanerImpl.java index 532e1b0abc..664d1a8a9c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipOrphanCleanerImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipOrphanCleanerImpl.java @@ -67,7 +67,7 @@ public boolean deleteOrphan(O instance, Collection relationships) { int count = 0; for (Relationship existingRelationship : existingRelationships) { - if (isSynced(existingRelationship.state()) && + if (isSynced(existingRelationship.syncState()) && !isInRelationshipList(existingRelationship, relationships(relationships))) { relationshipStore.delete(existingRelationship.uid()); count++; diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt index 4b20ff179d..ae2bd0e326 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/StatePersistorHelper.kt @@ -52,7 +52,7 @@ internal class StatePersistorHelper @Inject internal constructor() { private fun getStateToSet(o: O, forcedState: State?): State where O : DataObject, O : ObjectWithUidInterface { return forcedState - ?: if (o.state() == State.UPLOADING) State.TO_UPDATE else o.state() + ?: if (o.syncState() == State.UPLOADING) State.TO_UPDATE else o.syncState() } fun persistStates(map: Map>, store: IdentifiableDeletableDataObjectStore<*>) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java index e7cc2cecae..c1ea119e60 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandler.java @@ -105,8 +105,8 @@ protected void afterObjectHandled(final TrackedEntityInstance trackedEntityInsta TrackedEntityInstanceInternalAccessor.accessEnrollments(trackedEntityInstance); if (enrollments != null) { enrollmentHandler.handleMany(enrollments, enrollment -> enrollment.toBuilder() - .state(State.SYNCED) .syncState(State.SYNCED) + .aggregatedSyncState(State.SYNCED) .build(), overwrite); } @@ -123,12 +123,12 @@ protected void afterObjectHandled(final TrackedEntityInstance trackedEntityInsta @Override protected TrackedEntityInstance addRelationshipState(TrackedEntityInstance o) { - return o.toBuilder().state(State.RELATIONSHIP).syncState(State.RELATIONSHIP).build(); + return o.toBuilder().aggregatedSyncState(State.RELATIONSHIP).syncState(State.RELATIONSHIP).build(); } @Override protected TrackedEntityInstance addSyncedState(TrackedEntityInstance o) { - return o.toBuilder().state(State.SYNCED).syncState(State.SYNCED).build(); + return o.toBuilder().aggregatedSyncState(State.SYNCED).syncState(State.SYNCED).build(); } @Override diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/enrollment/EnrollmentSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/enrollment/EnrollmentSamples.java index 0d69011015..5ec34bd0b4 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/enrollment/EnrollmentSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/enrollment/EnrollmentSamples.java @@ -65,7 +65,8 @@ public static Enrollment get(String uid, String organisationUnit, String program .geometry(Geometry.builder() .type(FeatureType.POINT) .coordinates("[21.21, 23.23]").build()) - .state(State.TO_POST) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .deleted(false) .build(); } diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/TrackedEntityInstanceSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/TrackedEntityInstanceSamples.java index 972a66e56b..4e8e179a51 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/TrackedEntityInstanceSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/TrackedEntityInstanceSamples.java @@ -58,7 +58,8 @@ public static TrackedEntityInstance get(String uid, String organisationUnit, Str .type(FeatureType.POLYGON) .coordinates("[11.0, 11.0]") .build()) - .state(State.TO_POST) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .deleted(false) .build(); } diff --git a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManagerShould.java b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManagerShould.java index 20cfc922b4..ee9586d438 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManagerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDHISVersionManagerShould.java @@ -102,7 +102,7 @@ public void transform_2_30_relationship_into_equivalent_compatible_relationship( assert230Fields(compatible); assertThat(compatible.uid()).isEqualTo(UID); assertThat(compatible.relative()).isNull(); - assertThat(compatible.state()).isEqualTo(STATE); + assertThat(compatible.syncState()).isEqualTo(STATE); assertThat(compatible.deleted()).isEqualTo(DELETED); } @@ -121,7 +121,7 @@ public void transform_2_30_relationship_into_compatible_229_relationship() { assertThat(compatible.trackedEntityInstanceA()).isEqualTo(FROM_UID); assertThat(compatible.trackedEntityInstanceB()).isEqualTo(TO_UID); assertThat(compatible.uid()).isEqualTo(TYPE); - assertThat(compatible.state()).isEqualTo(STATE); + assertThat(compatible.syncState()).isEqualTo(STATE); assertThat(compatible.deleted()).isEqualTo(DELETED); } diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java index d7ed958f46..1b5e7df30b 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceHandlerShould.java @@ -123,8 +123,8 @@ public void setUp() throws Exception { when(trackedEntityInstance.uid()).thenReturn(TEI_UID); when(trackedEntityInstance.toBuilder()).thenReturn(teiBuilder); - when(teiBuilder.state(State.SYNCED)).thenReturn(teiBuilder); when(teiBuilder.syncState(State.SYNCED)).thenReturn(teiBuilder); + when(teiBuilder.aggregatedSyncState(State.SYNCED)).thenReturn(teiBuilder); when(teiBuilder.build()).thenReturn(trackedEntityInstance); when(TrackedEntityInstanceInternalAccessor.accessEnrollments(trackedEntityInstance)) .thenReturn(Collections.singletonList(enrollment)); @@ -223,8 +223,8 @@ public void do_not_invoke_cleaners_if_not_full_update() { public void invoke_relationship_handler_with_relationship_from_version_manager() { when(relationshipVersionManager.getRelativeTei(relationship229Compatible, TEI_UID)).thenReturn(relative); when(relative.toBuilder()).thenReturn(relativeBuilder); - when(relativeBuilder.state(any(State.class))).thenReturn(relativeBuilder); when(relativeBuilder.syncState(any(State.class))).thenReturn(relativeBuilder); + when(relativeBuilder.aggregatedSyncState(any(State.class))).thenReturn(relativeBuilder); when(relativeBuilder.build()).thenReturn(relative); trackedEntityInstanceHandler.handleMany(Collections.singletonList(trackedEntityInstance), false, From 14f72f5767bcbc583d11edb20cc8f87cf3103f84 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 2 Jul 2021 15:55:57 +0200 Subject: [PATCH 108/308] [androsdk-1383] Fix visualization store --- .../core/visualization/VisualizationStore.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt index 11fa9953ac..639ec5d462 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt @@ -29,6 +29,10 @@ package org.hisp.dhis.android.core.visualization 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.IntegerListColumnAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.RelativePeriodsColumnAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore @@ -52,7 +56,7 @@ internal object VisualizationStore { w.bind(17, o.showHierarchy()) w.bind(18, o.rowTotals()) w.bind(19, o.rowSubTotals()) - w.bind(10, o.colTotals()) + w.bind(20, o.colTotals()) w.bind(21, o.colSubTotals()) w.bind(22, o.showDimensionLabels()) w.bind(23, o.percentStackedValues()) @@ -60,16 +64,16 @@ internal object VisualizationStore { w.bind(25, o.skipRounding()) w.bind(26, o.displayDensity()) w.bind(27, o.digitGroupSeparator()) - w.bind(28, o.relativePeriods()) - w.bind(29, o.filterDimensions()) - w.bind(20, o.rowDimensions()) - w.bind(31, o.columnDimensions()) - w.bind(32, o.organisationUnitLevels()) + w.bind(28, RelativePeriodsColumnAdapter.serialize(o.relativePeriods())) + w.bind(29, StringListColumnAdapter.serialize(o.filterDimensions())) + w.bind(30, StringListColumnAdapter.serialize(o.rowDimensions())) + w.bind(31, StringListColumnAdapter.serialize(o.columnDimensions())) + w.bind(32, IntegerListColumnAdapter.serialize(o.organisationUnitLevels())) w.bind(33, o.userOrganisationUnit()) w.bind(34, o.userOrganisationUnitChildren()) w.bind(35, o.userOrganisationUnitGrandChildren()) - w.bind(36, o.organisationUnits()) - w.bind(37, o.periods())) + w.bind(36, ObjectWithUidListColumnAdapter.serialize(o.organisationUnits())) + w.bind(37, ObjectWithUidListColumnAdapter.serialize(o.periods())) } } From feee8dd583b9857d57920704b7623981343b3c75 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 18 Jun 2021 17:10:25 +0200 Subject: [PATCH 109/308] [androsdk-1383] Visualization pojo --- .../core/visualization/Visualization.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java new file mode 100644 index 0000000000..e45225fe79 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.BaseIdentifiableObject; +import org.hisp.dhis.android.core.common.CoreObject; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_Visualization.Builder.class) +public abstract class Visualization extends BaseIdentifiableObject implements CoreObject { + + @Nullable + @JsonProperty() + public abstract String description(); + + @Nullable + @JsonProperty() + public abstract String displayDescription(); + + @Nullable + @JsonProperty() + public abstract String displayFormName(); + + public static Builder builder() { + return new $$AutoValue_Visualization.Builder(); + } + + public static Visualization create(Cursor cursor) { + return AutoValue_Visualization.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder extends BaseIdentifiableObject.Builder { + + public abstract Builder id(Long id); + + public abstract Builder description(String description); + + public abstract Builder displayDescription(String displayDescription); + + public abstract Builder displayFormName(String displayFormName); + + public abstract Visualization build(); + } +} \ No newline at end of file From 6b0946eb656217dd58d867e6fa35b801a8c1e36d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:29:04 +0200 Subject: [PATCH 110/308] [androsdk-1383] Add visualization enums --- .../visualization/DataDimensionItemType.kt | 39 ++++++++++++++++ .../core/visualization/DigitGroupSeparator.kt | 34 ++++++++++++++ .../core/visualization/DisplayDensity.kt | 35 ++++++++++++++ .../visualization/HideEmptyItemStrategy.kt | 40 ++++++++++++++++ .../core/visualization/VisualizationType.kt | 46 +++++++++++++++++++ 5 files changed, 194 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt new file mode 100644 index 0000000000..c883f4dd91 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemType.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class DataDimensionItemType { + INDICATOR, + DATA_ELEMENT, + DATA_ELEMENT_OPERAND, + REPORTING_RATE, + PROGRAM_INDICATOR, + PROGRAM_DATA_ELEMENT, + PROGRAM_ATTRIBUTE, + VALIDATION_RULE +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt new file mode 100644 index 0000000000..dcd0ab8dd8 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DigitGroupSeparator.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class DigitGroupSeparator { + COMMA, + SPACE, + NONE +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt new file mode 100644 index 0000000000..de46799620 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DisplayDensity.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class DisplayDensity { + COMFORTABLE, + NORMAL, + COMPACT, + NONE +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt new file mode 100644 index 0000000000..c4bc87875d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/HideEmptyItemStrategy.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class HideEmptyItemStrategy { + NONE, + BEFORE_FIRST, + AFTER_LAST, + BEFORE_FIRST_AFTER_LAST, + ALL; + + open fun isHide(): Boolean { + return this == BEFORE_FIRST || this == AFTER_LAST || this == BEFORE_FIRST_AFTER_LAST || this == ALL + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt new file mode 100644 index 0000000000..c91c0e9bc7 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationType.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +enum class VisualizationType { + COLUMN, + STACKED_COLUMN, + BAR, + STACKED_BAR, + LINE, + AREA, + PIE, + RADAR, + GAUGE, + YEAR_OVER_YEAR_LINE, + YEAR_OVER_YEAR_COLUMN, + SINGLE_VALUE, + PIVOT_TABLE, + SCATTER, + BUBBLE +} From fe0e9f1a182a8c01fe2c3f81adfcbd387f646bcf Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:29:27 +0200 Subject: [PATCH 111/308] [androsdk-1383] Add visualization enum column adapters --- .../DigitGroupSeparatorColumnAdapter.kt | 36 +++++++++++++++++++ .../internal/DisplayDensityColumnAdapter.kt | 36 +++++++++++++++++++ .../HideEmptyItemStrategyColumnAdapter.kt | 36 +++++++++++++++++++ .../VisualizationTypeColumnAdapter.kt | 36 +++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt new file mode 100644 index 0000000000..8a284a38c3 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DigitGroupSeparatorColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.DigitGroupSeparator + +class DigitGroupSeparatorColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return DigitGroupSeparator::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt new file mode 100644 index 0000000000..defcefe168 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DisplayDensityColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.DisplayDensity + +class DisplayDensityColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return DisplayDensity::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt new file mode 100644 index 0000000000..f48303e1e0 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/HideEmptyItemStrategyColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.HideEmptyItemStrategy + +class HideEmptyItemStrategyColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return HideEmptyItemStrategy::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt new file mode 100644 index 0000000000..58b7e16b5a --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/VisualizationTypeColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.VisualizationType + +class VisualizationTypeColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return VisualizationType::class.java + } +} From 030c6443fda88fa41ebf9ba79a8d5908d4043423 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:29:49 +0200 Subject: [PATCH 112/308] [androsdk-1383] Add CategoryDimension and DataDimensionItem --- .../core/visualization/CategoryDimension.java | 79 ++++++++++++ .../core/visualization/DataDimensionItem.java | 114 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java new file mode 100644 index 0000000000..41aa0be768 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUid; + +import java.util.List; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_CategoryDimension.Builder.class) +public abstract class CategoryDimension implements CoreObject { + + @Nullable + @JsonProperty() + public abstract ObjectWithUid category(); + + @Nullable + @JsonProperty() + public abstract List categoryOptions(); + + public static Builder builder() { + return new $$AutoValue_CategoryDimension.Builder(); + } + + public static CategoryDimension create(Cursor cursor) { + return AutoValue_CategoryDimension.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder { + + public abstract Builder id(Long id); + + public abstract Builder category(ObjectWithUid category); + + public abstract Builder categoryOptions(List categoryOptions); + + public abstract CategoryDimension build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java new file mode 100644 index 0000000000..2cdf523cc6 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUid; + +@AutoValue +@JsonDeserialize(builder = $$AutoValue_DataDimensionItem.Builder.class) +public abstract class DataDimensionItem implements CoreObject { + + @Nullable + @JsonProperty() + public abstract DataDimensionItemType dataDimensionItemType(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid indicator(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid dataElement(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid dataElementOperand(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid reportingRate(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid programIndicator(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid programDataElement(); + + @Nullable + @JsonProperty() + public abstract ObjectWithUid programAttribute(); + + + public static Builder builder() { + return new $$AutoValue_DataDimensionItem.Builder(); + } + + public static DataDimensionItem create(Cursor cursor) { + return AutoValue_DataDimensionItem.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder { + + public abstract Builder id(Long id); + + public abstract Builder dataDimensionItemType(DataDimensionItemType dataDimensionItemType); + + public abstract Builder indicator(ObjectWithUid indicator); + + public abstract Builder dataElement(ObjectWithUid dataElement); + + public abstract Builder dataElementOperand(ObjectWithUid dataElementOperand); + + public abstract Builder reportingRate(ObjectWithUid reportingRate); + + public abstract Builder programIndicator(ObjectWithUid programIndicator); + + public abstract Builder programDataElement(ObjectWithUid programDataElement); + + public abstract Builder programAttribute(ObjectWithUid programAttribute); + + public abstract DataDimensionItem build(); + } +} \ No newline at end of file From ec2eaf07b3d3b42a0192a85fee4b1c96c5511bf0 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 16:30:05 +0200 Subject: [PATCH 113/308] [androsdk-1383] Extend visualization pojo --- .../core/visualization/Visualization.java | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index e45225fe79..fb17049b68 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -35,10 +35,21 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DigitGroupSeparatorColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DisplayDensityColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.HideEmptyItemStrategyColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.VisualizationTypeColumnAdapter; import org.hisp.dhis.android.core.common.BaseIdentifiableObject; import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUid; +import org.hisp.dhis.android.core.common.RelativePeriod; + +import java.util.HashMap; +import java.util.List; @AutoValue @JsonDeserialize(builder = $$AutoValue_Visualization.Builder.class) @@ -56,6 +67,145 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @JsonProperty() public abstract String displayFormName(); + @Nullable + @JsonProperty() + @ColumnAdapter(VisualizationTypeColumnAdapter.class) + public abstract VisualizationType type(); + + @Nullable + @JsonProperty() + public abstract Boolean hideTitle(); + + @Nullable + @JsonProperty() + public abstract Boolean hideSubtitle(); + + @Nullable + @JsonProperty() + public abstract Boolean hideEmptyColumns(); + + @Nullable + @JsonProperty() + public abstract Boolean hideEmptyRows(); + + @Nullable + @JsonProperty() + @ColumnAdapter(HideEmptyItemStrategyColumnAdapter.class) + public abstract HideEmptyItemStrategy hideEmptyRowItems(); + + @Nullable + @JsonProperty() + public abstract Boolean hideLegend(); + + @Nullable + @JsonProperty() + public abstract Boolean showHierarchy(); + + @Nullable + @JsonProperty() + public abstract Boolean rowTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean rowSubTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean colTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean colSubTotals(); + + @Nullable + @JsonProperty() + public abstract Boolean showDimensionLabels(); + + @Nullable + @JsonProperty() + public abstract Boolean percentStackedValues(); + + @Nullable + @JsonProperty() + public abstract Boolean noSpaceBetweenColumns(); + + @Nullable + @JsonProperty() + public abstract Boolean skipRounding(); + + @Nullable + @JsonProperty() + @ColumnAdapter(DisplayDensityColumnAdapter.class) + public abstract DisplayDensity displayDensity(); + + @Nullable + @JsonProperty() + @ColumnAdapter(DigitGroupSeparatorColumnAdapter.class) + public abstract DigitGroupSeparator digitGroupSeparator(); + + @Nullable + @JsonProperty() + public abstract HashMap relativePeriods(); + + @Nullable + @JsonProperty() + public abstract List categoryDimensions(); + + @Nullable + @JsonProperty() + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List filterDimensions(); + + @Nullable + @JsonProperty() + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List rowDimensions(); + + @Nullable + @JsonProperty() + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List columnDimensions(); + + @Nullable + @JsonProperty() + public abstract List dataDimensionItems(); + + @Nullable + @JsonProperty() + public abstract List organisationUnitLevels(); + + @Nullable + @JsonProperty() + public abstract Boolean userOrganisationUnit(); + + @Nullable + @JsonProperty() + public abstract Boolean userOrganisationUnitChildren(); + + @Nullable + @JsonProperty() + public abstract Boolean userOrganisationUnitGrandChildren(); + + @Nullable + @JsonProperty() + public abstract List organisationUnits(); + + @Nullable + @JsonProperty() + public abstract List columns(); + + @Nullable + @JsonProperty() + public abstract List periods(); + + @Nullable + @JsonProperty() + public abstract List filters(); + + @Nullable + @JsonProperty() + public abstract List rows(); + public static Builder builder() { return new $$AutoValue_Visualization.Builder(); } @@ -78,6 +228,72 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder relativePeriods); + + public abstract Builder categoryDimension(CategoryDimension categoryDimension); + + public abstract Builder filterDimensions(List filterDimensions); + + public abstract Builder rowDimensions(List rowDimensions); + + public abstract Builder columnDimensions(List columnDimensions); + + public abstract Builder dataDimensionItems(List dataDimensionItems); + + public abstract Builder organisationUnitLevels(List organisationUnitLevels); + + public abstract Builder userOrganisationUnit(Boolean userOrganisationUnit); + + public abstract Builder userOrganisationUnitChildren(Boolean userOrganisationUnitChildren); + + public abstract Builder userOrganisationUnitGrandChildren(Boolean userOrganisationUnitGrandChildren); + + public abstract Builder organisationUnits(List organisationUnits); + + public abstract Builder columns(List columns); + + public abstract Builder periods(List periods); + + public abstract Builder filters(List filters); + + public abstract Builder rows(List rows); + public abstract Visualization build(); } } \ No newline at end of file From 27b1ec328ff6c98b5468b9c59e654b6377469e33 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 17:39:55 +0200 Subject: [PATCH 114/308] [androsdk-1383] Add column adapters needed for Visualizations --- .../CategoryDimensionListColumnAdapter.kt | 47 ++++++++++++++ .../internal/IntegerListColumnAdapter.kt | 46 +++++++++++++ .../JSONObjectHashMapColumnAdapter.kt | 65 +++++++++++++++++++ .../ObjectWithUidListColumnAdapter.kt | 47 ++++++++++++++ .../internal/RelativePeriodsColumnAdapter.kt | 47 ++++++++++++++ .../DataDimensionItemTypeColumnAdapter.kt | 36 ++++++++++ ...oreDataDimensionItemListColumnAdapter.java | 37 +++++++++++ 7 files changed, 325 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt new file mode 100644 index 0000000000..5a6053c9fd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.visualization.CategoryDimension + +internal class CategoryDimensionListColumnAdapter : JSONObjectListColumnAdapter() { + override fun getObjectClass(): Class> { + return ArrayList().javaClass + } + + override fun serialize(o: List?): String? = CategoryDimensionListColumnAdapter.serialize(o) + + companion object { + fun serialize(o: List?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt new file mode 100644 index 0000000000..8880c8d478 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/IntegerListColumnAdapter.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory + +internal class IntegerListColumnAdapter : JSONObjectListColumnAdapter() { + override fun getObjectClass(): Class> { + return ArrayList().javaClass + } + + override fun serialize(o: List?): String? = IntegerListColumnAdapter.serialize(o) + + companion object { + fun serialize(o: List?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt new file mode 100644 index 0000000000..7630eb8bec --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import android.content.ContentValues +import android.database.Cursor +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.JsonMappingException +import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory + +internal abstract class JSONObjectHashMapColumnAdapter : ColumnTypeAdapter> { + protected abstract fun getObjectClass(): Class> + + override fun fromCursor(cursor: Cursor, columnName: String): HashMap { + val columnIndex = cursor.getColumnIndex(columnName) + val str = cursor.getString(columnIndex) + return try { + ObjectMapperFactory.objectMapper().readValue(str, getObjectClass()) + } catch (e: JsonProcessingException) { + hashMapOf() + } catch (e: JsonMappingException) { + hashMapOf() + } catch (e: IllegalArgumentException) { + hashMapOf() + } catch (e: IllegalStateException) { + hashMapOf() + } + } + + override fun toContentValues(contentValues: ContentValues, columnName: String, o: HashMap?) { + try { + contentValues.put(columnName, serialize(o)) + } catch (e: JsonProcessingException) { + e.printStackTrace() + } + } + + abstract fun serialize(o: HashMap?): String? +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt new file mode 100644 index 0000000000..da0d49fef9 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.common.ObjectWithUid + +internal class ObjectWithUidListColumnAdapter : JSONObjectListColumnAdapter() { + override fun getObjectClass(): Class> { + return ArrayList().javaClass + } + + override fun serialize(o: List?): String? = ObjectWithUidListColumnAdapter.serialize(o) + + companion object { + fun serialize(o: List?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt new file mode 100644 index 0000000000..e9048ac470 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal + +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.common.RelativePeriod + +internal class RelativePeriodsColumnAdapter : JSONObjectHashMapColumnAdapter() { + override fun getObjectClass(): Class> { + return HashMap().javaClass + } + + override fun serialize(o: HashMap?): String? = RelativePeriodsColumnAdapter.serialize(o) + + companion object { + fun serialize(o: HashMap?): String? { + return o?.let { + ObjectMapperFactory.objectMapper().writeValueAsString(it) + } + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt new file mode 100644 index 0000000000..db0f93899e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/DataDimensionItemTypeColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.visualization.DataDimensionItemType + +class DataDimensionItemTypeColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return DataDimensionItemType::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java new file mode 100644 index 0000000000..58c76cfcbe --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreDataDimensionItemListColumnAdapter.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.ignore.internal; + +import org.hisp.dhis.android.core.visualization.DataDimensionItem; + +import java.util.List; + +public final class IgnoreDataDimensionItemListColumnAdapter + extends IgnoreColumnAdapter> { +} \ No newline at end of file From 291908437ed41f0154f99a55c6f62ab41178e63b Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 29 Jun 2021 17:40:31 +0200 Subject: [PATCH 115/308] [androsdk-1383] Add adapters to pojos --- .../core/visualization/CategoryDimension.java | 5 +++++ .../core/visualization/DataDimensionItem.java | 11 +++++++++++ .../core/visualization/Visualization.java | 16 +++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java index 41aa0be768..d3a806144d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java @@ -35,8 +35,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.identifiable.internal.ObjectWithUidColumnAdapter; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; @@ -48,10 +51,12 @@ public abstract class CategoryDimension implements CoreObject { @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid category(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List categoryOptions(); public static Builder builder() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java index 2cdf523cc6..6195a38ccc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java @@ -35,8 +35,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DataDimensionItemTypeColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.identifiable.internal.ObjectWithUidColumnAdapter; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; @@ -46,34 +49,42 @@ public abstract class DataDimensionItem implements CoreObject { @Nullable @JsonProperty() + @ColumnAdapter(DataDimensionItemTypeColumnAdapter.class) public abstract DataDimensionItemType dataDimensionItemType(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid indicator(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid dataElement(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid dataElementOperand(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid reportingRate(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programIndicator(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programDataElement(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programAttribute(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index fb17049b68..f227ee9e1c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -38,11 +38,16 @@ import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.CategoryDimensionListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.IntegerListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.RelativePeriodsColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DigitGroupSeparatorColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DisplayDensityColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.HideEmptyItemStrategyColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.VisualizationTypeColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreDataDimensionItemListColumnAdapter; import org.hisp.dhis.android.core.common.BaseIdentifiableObject; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; @@ -145,10 +150,12 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() + @ColumnAdapter(RelativePeriodsColumnAdapter.class) public abstract HashMap relativePeriods(); @Nullable @JsonProperty() + @ColumnAdapter(CategoryDimensionListColumnAdapter.class) public abstract List categoryDimensions(); @Nullable @@ -168,10 +175,12 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() + @ColumnAdapter(IgnoreDataDimensionItemListColumnAdapter.class) public abstract List dataDimensionItems(); @Nullable @JsonProperty() + @ColumnAdapter(IntegerListColumnAdapter.class) public abstract List organisationUnitLevels(); @Nullable @@ -188,22 +197,27 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List organisationUnits(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List columns(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List periods(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List filters(); @Nullable @JsonProperty() + @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List rows(); public static Builder builder() { @@ -266,7 +280,7 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder relativePeriods); - public abstract Builder categoryDimension(CategoryDimension categoryDimension); + public abstract Builder categoryDimensions(List categoryDimensions); public abstract Builder filterDimensions(List filterDimensions); From c3056f375174477235ef3b006c22be8127fd910e Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 30 Jun 2021 13:33:00 +0200 Subject: [PATCH 116/308] [androsdk-1383] Update visualization pojo and adapters --- .../android/core/common/RelativePeriod.kt | 89 ++++++++++--------- .../core/visualization/Visualization.java | 33 ++----- 2 files changed, 52 insertions(+), 70 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt b/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt index 85abdf8ced..71a994008b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/RelativePeriod.kt @@ -27,6 +27,7 @@ */ package org.hisp.dhis.android.core.common +import com.fasterxml.jackson.annotation.JsonAlias import org.hisp.dhis.android.core.period.PeriodType @Suppress("MagicNumber") @@ -37,47 +38,49 @@ enum class RelativePeriod constructor( internal val periodsThisYear: Boolean = false, internal val periodsLastYear: Boolean = false ) { - TODAY(PeriodType.Daily, 0, 1), - YESTERDAY(PeriodType.Daily, -1, 0), - LAST_3_DAYS(PeriodType.Daily, -3, 0), - LAST_7_DAYS(PeriodType.Daily, -7, 0), - LAST_14_DAYS(PeriodType.Daily, -14, 0), - LAST_30_DAYS(PeriodType.Daily, -30, 0), - LAST_60_DAYS(PeriodType.Daily, -60, 0), - LAST_90_DAYS(PeriodType.Daily, -90, 0), - LAST_180_DAYS(PeriodType.Daily, -180, 0), - THIS_MONTH(PeriodType.Monthly, 0, 1), - LAST_MONTH(PeriodType.Monthly, -1, 0), - THIS_BIMONTH(PeriodType.BiMonthly, 0, 1), - LAST_BIMONTH(PeriodType.BiMonthly, -1, 0), - THIS_QUARTER(PeriodType.Quarterly, 0, 1), - LAST_QUARTER(PeriodType.Quarterly, -1, 0), - THIS_SIX_MONTH(PeriodType.SixMonthly, 0, 1), - LAST_SIX_MONTH(PeriodType.SixMonthly, -1, 0), - WEEKS_THIS_YEAR(PeriodType.Weekly, null, null, true, false), - MONTHS_THIS_YEAR(PeriodType.Monthly, null, null, true, false), - BIMONTHS_THIS_YEAR(PeriodType.BiMonthly, null, null, true, false), - QUARTERS_THIS_YEAR(PeriodType.Quarterly, null, null, true, false), - THIS_YEAR(PeriodType.Yearly, 0, 1), - MONTHS_LAST_YEAR(PeriodType.Monthly, null, null, false, true), - QUARTERS_LAST_YEAR(PeriodType.Quarterly, null, null, false, true), - LAST_YEAR(PeriodType.Yearly, -1, 0), - LAST_5_YEARS(PeriodType.Yearly, -5, 0), - LAST_12_MONTHS(PeriodType.Monthly, -12, 0), - LAST_6_MONTHS(PeriodType.Monthly, -6, 0), - LAST_3_MONTHS(PeriodType.Monthly, -3, 0), - LAST_6_BIMONTHS(PeriodType.BiMonthly, -6, 0), - LAST_4_QUARTERS(PeriodType.Quarterly, -4, 0), - LAST_2_SIXMONTHS(PeriodType.SixMonthly, -2, 0), - THIS_FINANCIAL_YEAR(PeriodType.FinancialApril, 0, 1), - LAST_FINANCIAL_YEAR(PeriodType.FinancialApril, -1, 0), - LAST_5_FINANCIAL_YEARS(PeriodType.FinancialApril, -5, 0), - THIS_WEEK(PeriodType.Weekly, 0, 1), - LAST_WEEK(PeriodType.Weekly, -1, 0), - THIS_BIWEEK(PeriodType.BiWeekly, 0, 1), - LAST_BIWEEK(PeriodType.BiWeekly, -1, 0), - LAST_4_WEEKS(PeriodType.Weekly, -4, 0), - LAST_4_BIWEEKS(PeriodType.BiWeekly, -4, 0), - LAST_12_WEEKS(PeriodType.Weekly, -12, 0), - LAST_52_WEEKS(PeriodType.Weekly, -52, 0) + @JsonAlias("today", "thisDay") TODAY(PeriodType.Daily, 0, 1), + @JsonAlias("yesterday") YESTERDAY(PeriodType.Daily, -1, 0), + @JsonAlias("last3Days") LAST_3_DAYS(PeriodType.Daily, -3, 0), + @JsonAlias("last7Days") LAST_7_DAYS(PeriodType.Daily, -7, 0), + @JsonAlias("last14Days") LAST_14_DAYS(PeriodType.Daily, -14, 0), + @JsonAlias("last30Days") LAST_30_DAYS(PeriodType.Daily, -30, 0), + @JsonAlias("last60Days") LAST_60_DAYS(PeriodType.Daily, -60, 0), + @JsonAlias("last90Days") LAST_90_DAYS(PeriodType.Daily, -90, 0), + @JsonAlias("last180Days") LAST_180_DAYS(PeriodType.Daily, -180, 0), + @JsonAlias("thisMonth") THIS_MONTH(PeriodType.Monthly, 0, 1), + @JsonAlias("lastMonth") LAST_MONTH(PeriodType.Monthly, -1, 0), + @JsonAlias("thisBimonth") THIS_BIMONTH(PeriodType.BiMonthly, 0, 1), + @JsonAlias("lastBimonth") LAST_BIMONTH(PeriodType.BiMonthly, -1, 0), + @JsonAlias("thisQuarter") THIS_QUARTER(PeriodType.Quarterly, 0, 1), + @JsonAlias("lastQuarter") LAST_QUARTER(PeriodType.Quarterly, -1, 0), + @JsonAlias("thisSixMonth") THIS_SIX_MONTH(PeriodType.SixMonthly, 0, 1), + @JsonAlias("lastSixMonth") LAST_SIX_MONTH(PeriodType.SixMonthly, -1, 0), + @JsonAlias("weeksThisYear") WEEKS_THIS_YEAR(PeriodType.Weekly, null, null, true, false), + @JsonAlias("monthsThisYear") MONTHS_THIS_YEAR(PeriodType.Monthly, null, null, true, false), + @JsonAlias("biMonthsThisYear") BIMONTHS_THIS_YEAR(PeriodType.BiMonthly, null, null, true, false), + @JsonAlias("quartersThisYear") QUARTERS_THIS_YEAR(PeriodType.Quarterly, null, null, true, false), + @JsonAlias("thisYear") THIS_YEAR(PeriodType.Yearly, 0, 1), + @JsonAlias("monthsLastYear") MONTHS_LAST_YEAR(PeriodType.Monthly, null, null, false, true), + @JsonAlias("quartersLastYear") QUARTERS_LAST_YEAR(PeriodType.Quarterly, null, null, false, true), + @JsonAlias("lastYear") LAST_YEAR(PeriodType.Yearly, -1, 0), + @JsonAlias("last5Years") LAST_5_YEARS(PeriodType.Yearly, -5, 0), + @JsonAlias("last10Years") LAST_10_YEARS(PeriodType.Yearly, -10, 0), + @JsonAlias("last12Months") LAST_12_MONTHS(PeriodType.Monthly, -12, 0), + @JsonAlias("last6Months") LAST_6_MONTHS(PeriodType.Monthly, -6, 0), + @JsonAlias("last3Months") LAST_3_MONTHS(PeriodType.Monthly, -3, 0), + @JsonAlias("last6BiMonths") LAST_6_BIMONTHS(PeriodType.BiMonthly, -6, 0), + @JsonAlias("last4Quarters") LAST_4_QUARTERS(PeriodType.Quarterly, -4, 0), + @JsonAlias("last2SixMonths") LAST_2_SIXMONTHS(PeriodType.SixMonthly, -2, 0), + @JsonAlias("thisFinancialYear") THIS_FINANCIAL_YEAR(PeriodType.FinancialApril, 0, 1), + @JsonAlias("lastFinancialYear") LAST_FINANCIAL_YEAR(PeriodType.FinancialApril, -1, 0), + @JsonAlias("last5FinancialYears") LAST_5_FINANCIAL_YEARS(PeriodType.FinancialApril, -5, 0), + @JsonAlias("last10FinancialYears") LAST_10_FINANCIAL_YEARS(PeriodType.FinancialApril, -10, 0), + @JsonAlias("thisWeek") THIS_WEEK(PeriodType.Weekly, 0, 1), + @JsonAlias("lastWeek") LAST_WEEK(PeriodType.Weekly, -1, 0), + @JsonAlias("thisBiWeek") THIS_BIWEEK(PeriodType.BiWeekly, 0, 1), + @JsonAlias("lastBiWeek") LAST_BIWEEK(PeriodType.BiWeekly, -1, 0), + @JsonAlias("last4Weeks") LAST_4_WEEKS(PeriodType.Weekly, -4, 0), + @JsonAlias("last4BiWeeks") LAST_4_BIWEEKS(PeriodType.BiWeekly, -4, 0), + @JsonAlias("last12Weeks") LAST_12_WEEKS(PeriodType.Weekly, -12, 0), + @JsonAlias("last52Weeks") LAST_52_WEEKS(PeriodType.Weekly, -52, 0) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index f227ee9e1c..e21b6eb467 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -38,7 +38,6 @@ import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; -import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.CategoryDimensionListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.IntegerListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.RelativePeriodsColumnAdapter; @@ -47,6 +46,7 @@ import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.DisplayDensityColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.HideEmptyItemStrategyColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.VisualizationTypeColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreCategoryDimensionListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreDataDimensionItemListColumnAdapter; import org.hisp.dhis.android.core.common.BaseIdentifiableObject; import org.hisp.dhis.android.core.common.CoreObject; @@ -151,12 +151,12 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(RelativePeriodsColumnAdapter.class) - public abstract HashMap relativePeriods(); + public abstract HashMap relativePeriods(); // Cell, but delete false @Nullable @JsonProperty() - @ColumnAdapter(CategoryDimensionListColumnAdapter.class) - public abstract List categoryDimensions(); + @ColumnAdapter(IgnoreCategoryDimensionListColumnAdapter.class) + public abstract List categoryDimensions(); // Table with visualization, category and coptino @Nullable @JsonProperty() @@ -176,7 +176,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(IgnoreDataDimensionItemListColumnAdapter.class) - public abstract List dataDimensionItems(); + public abstract List dataDimensionItems(); // Table with visualization id, type and uids with FK. @Nullable @JsonProperty() @@ -198,28 +198,13 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List organisationUnits(); - - @Nullable - @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List columns(); + public abstract List organisationUnits(); // Cell @Nullable @JsonProperty() @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List periods(); - @Nullable - @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List filters(); - - @Nullable - @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List rows(); - public static Builder builder() { return new $$AutoValue_Visualization.Builder(); } @@ -300,14 +285,8 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder organisationUnits); - public abstract Builder columns(List columns); - public abstract Builder periods(List periods); - public abstract Builder filters(List filters); - - public abstract Builder rows(List rows); - public abstract Visualization build(); } } \ No newline at end of file From 01d80335f3fb007d7850fbe8e1159163b8ec0cfe Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 30 Jun 2021 13:33:15 +0200 Subject: [PATCH 117/308] [androsdk-1383] Add some tests --- ...reCategoryDimensionListColumnAdapter.java} | 22 ++----- .../visualization/VisualizationSamples.java | 58 +++++++++++++++++++ .../visualization/visualization.json | 20 ++++--- .../visualization/VisualizationShould.java | 54 +++++++++++++++++ 4 files changed, 130 insertions(+), 24 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/{custom/internal/CategoryDimensionListColumnAdapter.kt => ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java} (69%) create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java create mode 100644 core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java similarity index 69% rename from core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt rename to core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java index 5a6053c9fd..cc9ea128ac 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/CategoryDimensionListColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreCategoryDimensionListColumnAdapter.java @@ -25,23 +25,13 @@ * (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.arch.db.adapters.custom.internal -import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory -import org.hisp.dhis.android.core.visualization.CategoryDimension +package org.hisp.dhis.android.core.arch.db.adapters.ignore.internal; -internal class CategoryDimensionListColumnAdapter : JSONObjectListColumnAdapter() { - override fun getObjectClass(): Class> { - return ArrayList().javaClass - } +import org.hisp.dhis.android.core.visualization.CategoryDimension; - override fun serialize(o: List?): String? = CategoryDimensionListColumnAdapter.serialize(o) +import java.util.List; - companion object { - fun serialize(o: List?): String? { - return o?.let { - ObjectMapperFactory.objectMapper().writeValueAsString(it) - } - } - } -} +public final class IgnoreCategoryDimensionListColumnAdapter + extends IgnoreColumnAdapter> { +} \ No newline at end of file diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java new file mode 100644 index 0000000000..f6056bbee9 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.visualization; + +import org.hisp.dhis.android.core.common.BaseIdentifiableObject; +import org.hisp.dhis.android.core.visualization.Visualization; + +import java.text.ParseException; +import java.util.Date; + +import static org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.fillIdentifiableProperties; + +public class VisualizationSamples { + + public static Visualization get() { + Visualization.Builder builder = Visualization.builder(); + + fillIdentifiableProperties(builder); + return builder + .id(1L) + .build(); + } + + private static Date getDate(String dateStr) { + try { + return BaseIdentifiableObject.DATE_FORMAT.parse(dateStr); + } catch (ParseException e) { + e.printStackTrace(); + return null; + } + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/visualization/visualization.json b/core/src/sharedTest/resources/visualization/visualization.json index 3b59a760fb..b29fc47348 100644 --- a/core/src/sharedTest/resources/visualization/visualization.json +++ b/core/src/sharedTest/resources/visualization/visualization.json @@ -26,6 +26,7 @@ "displayDensity": "NORMAL", "digitGroupSeparator": "COMMA", "relativePeriods": { + "today": true, "thisYear": false, "quartersLastYear": false, "last30Days": false, @@ -193,26 +194,29 @@ "id": "vWbkYPRmKyS" } ], - "columns": [ + "periods": [ { - "id": "dx" + "id": "202102" }, { - "id": "fMZEcRHuamy" + "id": "202103" }, { - "id": "fkAkrdC7eJF" + "id": "2021S2" } ], - "periods": [ + + + + "columns": [ { - "id": "202102" + "id": "dx" }, { - "id": "202103" + "id": "fMZEcRHuamy" }, { - "id": "2021S2" + "id": "fkAkrdC7eJF" } ], "filters": [ diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java new file mode 100644 index 0000000000..80167be179 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import org.hisp.dhis.android.core.common.BaseObjectShould; +import org.hisp.dhis.android.core.common.ObjectShould; +import org.hisp.dhis.android.core.data.visualization.VisualizationSamples; +import org.junit.Test; + +import java.io.IOException; +import java.text.ParseException; + +import static com.google.common.truth.Truth.assertThat; + +public class VisualizationShould extends BaseObjectShould implements ObjectShould { + + public VisualizationShould() { + super("visualization/visualization.json"); + } + + @Override + @Test + public void map_from_json_string() throws IOException, ParseException { + Visualization jsonVisualization = objectMapper.readValue(jsonStream, Visualization.class); + Visualization expectedVisualization = VisualizationSamples.get().toBuilder().id(null).build(); + assertThat(jsonVisualization).isEqualTo(expectedVisualization); + } +} \ No newline at end of file From 579b9c362c753f9bfa206329e32e2857b9a52e21 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 1 Jul 2021 12:57:44 +0200 Subject: [PATCH 118/308] [androsdk-1383] Improve relative periods column adapter --- .../db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt | 2 +- .../org/hisp/dhis/android/core/visualization/Visualization.java | 2 +- core/src/sharedTest/resources/visualization/visualization.json | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt index e9048ac470..781caf7c52 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -40,7 +40,7 @@ internal class RelativePeriodsColumnAdapter : JSONObjectHashMapColumnAdapter?): String? { return o?.let { - ObjectMapperFactory.objectMapper().writeValueAsString(it) + ObjectMapperFactory.objectMapper().writeValueAsString(it.filter { it.value }) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index e21b6eb467..182862db57 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -151,7 +151,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(RelativePeriodsColumnAdapter.class) - public abstract HashMap relativePeriods(); // Cell, but delete false + public abstract HashMap relativePeriods(); @Nullable @JsonProperty() diff --git a/core/src/sharedTest/resources/visualization/visualization.json b/core/src/sharedTest/resources/visualization/visualization.json index b29fc47348..f57476a51f 100644 --- a/core/src/sharedTest/resources/visualization/visualization.json +++ b/core/src/sharedTest/resources/visualization/visualization.json @@ -26,7 +26,6 @@ "displayDensity": "NORMAL", "digitGroupSeparator": "COMMA", "relativePeriods": { - "today": true, "thisYear": false, "quartersLastYear": false, "last30Days": false, From 76d5e5fe5b8e034989e2206044e689bf4a4d4ace Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 1 Jul 2021 12:57:58 +0200 Subject: [PATCH 119/308] [androsdk-1383] Add visualization table info --- .../visualization/VisualizationTableInfo.kt | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt new file mode 100644 index 0000000000..4e1c8fdc66 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns +import org.hisp.dhis.android.core.common.IdentifiableColumns + +object VisualizationTableInfo { + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "Visualization" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : IdentifiableColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + DESCRIPTION, + DISPLAY_DESCRIPTION, + DISPLAY_FORM_NAME, + TYPE, + HIDE_TITLE, + HIDE_SUBTITLE, + HIDE_EMPTY_COLUMNS, + HIDE_EMPTY_ROWS, + HIDE_EMPTY_ROW_ITEMS, + HIDE_LEGEND, + SHOW_HIERARCHY, + ROW_TOTALS, + ROW_SUB_TOTALS, + COL_TOTALS, + COL_SUB_TOTALS, + SHOW_DIMENSION_LABELS, + PERCENT_STACKED_VALUES, + NO_SPACE_BETWEEN_COLUMNS, + SKIP_ROUNDING, + DISPLAY_DENSITY, + DIGIT_GROUP_SEPARATOR, + RELATIVE_PERIODS, + FILTER_DIMENSIONS, + ROW_DIMENSIONS, + COLUMN_DIMENSIONS, + ORGANISATION_UNIT_LEVELS, + USER_ORGANISATION_UNIT, + USER_ORGANISATION_UNIT_CHILDREN, + USER_ORGANISATION_UNIT_GRAND_CHILDREN, + ORGANISATION_UNITS, + PERIODS + ) + } + + companion object { + const val DESCRIPTION = "description" + const val DISPLAY_DESCRIPTION = "displayDescription" + const val DISPLAY_FORM_NAME = "displayFormName" + const val TYPE = "type" + const val HIDE_TITLE = "hideTitle" + const val HIDE_SUBTITLE = "hideSubtitle" + const val HIDE_EMPTY_COLUMNS = "hideEmptyColumns" + const val HIDE_EMPTY_ROWS = "hideEmptyRows" + const val HIDE_EMPTY_ROW_ITEMS = "hideEmptyRowItems" + const val HIDE_LEGEND = "hideLegend" + const val SHOW_HIERARCHY = "showHierarchy" + const val ROW_TOTALS = "rowTotals" + const val ROW_SUB_TOTALS = "rowSubTotals" + const val COL_TOTALS = "colTotals" + const val COL_SUB_TOTALS = "colSubTotals" + const val SHOW_DIMENSION_LABELS = "showDimensionLabels" + const val PERCENT_STACKED_VALUES = "percentStackedValues" + const val NO_SPACE_BETWEEN_COLUMNS = "noSpaceBetweenColumns" + const val SKIP_ROUNDING = "skipRounding" + const val DISPLAY_DENSITY = "displayDensity" + const val DIGIT_GROUP_SEPARATOR = "digitGroupSeparator" + const val RELATIVE_PERIODS = "relativePeriods" + const val FILTER_DIMENSIONS = "filterDimensions" + const val ROW_DIMENSIONS = "rowDimensions" + const val COLUMN_DIMENSIONS = "columnDimensions" + const val ORGANISATION_UNIT_LEVELS = "organisationUnitLevels" + const val USER_ORGANISATION_UNIT = "userOrganisationUnit" + const val USER_ORGANISATION_UNIT_CHILDREN = "userOrganisationUnitChildren" + const val USER_ORGANISATION_UNIT_GRAND_CHILDREN = "userOrganisationUnitGrandChildren" + const val ORGANISATION_UNITS = "organisationUnits" + const val PERIODS = "periods" + } + } +} From 4bb5325979c2b9fea5e428234fc23c21e75944e2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 1 Jul 2021 13:26:00 +0200 Subject: [PATCH 120/308] [androsdk-1383] Add visualization store --- .../core/visualization/VisualizationStore.kt | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt new file mode 100644 index 0000000000..11fa9953ac --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory + +@Suppress("MagicNumber") +internal object VisualizationStore { + private val BINDER = object : IdentifiableStatementBinder() { + override fun bindToStatement(o: Visualization, w: StatementWrapper) { + super.bindToStatement(o, w) + w.bind(7, o.description()) + w.bind(8, o.displayDescription()) + w.bind(9, o.displayFormName()) + w.bind(10, o.type()) + w.bind(11, o.hideTitle()) + w.bind(12, o.hideSubtitle()) + w.bind(13, o.hideEmptyColumns()) + w.bind(14, o.hideEmptyRows()) + w.bind(15, o.hideEmptyRowItems()) + w.bind(16, o.hideLegend()) + w.bind(17, o.showHierarchy()) + w.bind(18, o.rowTotals()) + w.bind(19, o.rowSubTotals()) + w.bind(10, o.colTotals()) + w.bind(21, o.colSubTotals()) + w.bind(22, o.showDimensionLabels()) + w.bind(23, o.percentStackedValues()) + w.bind(24, o.noSpaceBetweenColumns()) + w.bind(25, o.skipRounding()) + w.bind(26, o.displayDensity()) + w.bind(27, o.digitGroupSeparator()) + w.bind(28, o.relativePeriods()) + w.bind(29, o.filterDimensions()) + w.bind(20, o.rowDimensions()) + w.bind(31, o.columnDimensions()) + w.bind(32, o.organisationUnitLevels()) + w.bind(33, o.userOrganisationUnit()) + w.bind(34, o.userOrganisationUnitChildren()) + w.bind(35, o.userOrganisationUnitGrandChildren()) + w.bind(36, o.organisationUnits()) + w.bind(37, o.periods())) + } + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return StoreFactory.objectWithUidStore( + databaseAdapter, VisualizationTableInfo.TABLE_INFO, BINDER + ) { cursor: Cursor -> Visualization.create(cursor) } + } +} From b0e4526e7c03d3c189ded42580f1bbc19023e62e Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 2 Jul 2021 15:55:57 +0200 Subject: [PATCH 121/308] [androsdk-1383] Fix visualization store --- .../core/visualization/VisualizationStore.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt index 11fa9953ac..639ec5d462 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt @@ -29,6 +29,10 @@ package org.hisp.dhis.android.core.visualization 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.IntegerListColumnAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.RelativePeriodsColumnAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore @@ -52,7 +56,7 @@ internal object VisualizationStore { w.bind(17, o.showHierarchy()) w.bind(18, o.rowTotals()) w.bind(19, o.rowSubTotals()) - w.bind(10, o.colTotals()) + w.bind(20, o.colTotals()) w.bind(21, o.colSubTotals()) w.bind(22, o.showDimensionLabels()) w.bind(23, o.percentStackedValues()) @@ -60,16 +64,16 @@ internal object VisualizationStore { w.bind(25, o.skipRounding()) w.bind(26, o.displayDensity()) w.bind(27, o.digitGroupSeparator()) - w.bind(28, o.relativePeriods()) - w.bind(29, o.filterDimensions()) - w.bind(20, o.rowDimensions()) - w.bind(31, o.columnDimensions()) - w.bind(32, o.organisationUnitLevels()) + w.bind(28, RelativePeriodsColumnAdapter.serialize(o.relativePeriods())) + w.bind(29, StringListColumnAdapter.serialize(o.filterDimensions())) + w.bind(30, StringListColumnAdapter.serialize(o.rowDimensions())) + w.bind(31, StringListColumnAdapter.serialize(o.columnDimensions())) + w.bind(32, IntegerListColumnAdapter.serialize(o.organisationUnitLevels())) w.bind(33, o.userOrganisationUnit()) w.bind(34, o.userOrganisationUnitChildren()) w.bind(35, o.userOrganisationUnitGrandChildren()) - w.bind(36, o.organisationUnits()) - w.bind(37, o.periods())) + w.bind(36, ObjectWithUidListColumnAdapter.serialize(o.organisationUnits())) + w.bind(37, ObjectWithUidListColumnAdapter.serialize(o.periods())) } } From 918aef5ef5310ef00b12835bee6bb349f515628a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 2 Jul 2021 17:47:26 +0200 Subject: [PATCH 122/308] [androsdk-1383] Add migrations and snapshot --- core/src/main/assets/migrations/104.sql | 1 + core/src/main/assets/snapshots/{103.sql => 104.sql} | 1 + .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 core/src/main/assets/migrations/104.sql rename core/src/main/assets/snapshots/{103.sql => 104.sql} (98%) diff --git a/core/src/main/assets/migrations/104.sql b/core/src/main/assets/migrations/104.sql new file mode 100644 index 0000000000..d09922de4e --- /dev/null +++ b/core/src/main/assets/migrations/104.sql @@ -0,0 +1 @@ +CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/103.sql b/core/src/main/assets/snapshots/104.sql similarity index 98% rename from core/src/main/assets/snapshots/103.sql rename to core/src/main/assets/snapshots/104.sql index 6d39554abd..39bf464de0 100644 --- a/core/src/main/assets/snapshots/103.sql +++ b/core/src/main/assets/snapshots/104.sql @@ -111,3 +111,4 @@ CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMEN CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); +CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index 0ab9812033..5aafddb5ee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 103; + static final int VERSION = 104; private final AssetManager assetManager; private final int targetVersion; From cf119e74cb116379ef19853422c7ed65d7b3a910 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 2 Jul 2021 17:47:54 +0200 Subject: [PATCH 123/308] [androsdk-1383] Add visualization handler --- .../hisp/dhis/android/core/visualization/Visualization.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index 182862db57..ec8f159d1f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -156,7 +156,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(IgnoreCategoryDimensionListColumnAdapter.class) - public abstract List categoryDimensions(); // Table with visualization, category and coptino + public abstract List categoryDimensions(); @Nullable @JsonProperty() @@ -176,7 +176,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(IgnoreDataDimensionItemListColumnAdapter.class) - public abstract List dataDimensionItems(); // Table with visualization id, type and uids with FK. + public abstract List dataDimensionItems(); @Nullable @JsonProperty() @@ -198,7 +198,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List organisationUnits(); // Cell + public abstract List organisationUnits(); @Nullable @JsonProperty() From 3cfbe15381702ae02ccee59fcc7db64610977b5f Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 2 Jul 2021 17:48:23 +0200 Subject: [PATCH 124/308] [androsdk-1383] Add visualization store test and improve samples --- .../VisualizationStoreIntegrationShould.kt | 55 ++++++++++++++ .../visualization/VisualizationHandler.kt} | 48 +++++------- .../visualization/VisualizationSamples.kt | 74 +++++++++++++++++++ .../visualization/VisualizationShould.java | 2 +- 4 files changed, 150 insertions(+), 29 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt rename core/src/{sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java => main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt} (65%) create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt new file mode 100644 index 0000000000..516995593e --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.data.database.IdentifiableObjectStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.data.visualization.VisualizationSamples +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.hisp.dhis.android.core.visualization.HideEmptyItemStrategy +import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationStore +import org.hisp.dhis.android.core.visualization.VisualizationTableInfo +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class VisualizationStoreIntegrationShould : IdentifiableObjectStoreAbstractIntegrationShould( + VisualizationStore.create(TestDatabaseAdapterFactory.get()), + VisualizationTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() +) { + override fun buildObject(): Visualization { + return VisualizationSamples.visualization() + } + + override fun buildObjectToUpdate(): Visualization { + return VisualizationSamples.visualization().toBuilder() + .hideEmptyRowItems(HideEmptyItemStrategy.AFTER_LAST) + .build() + } +} diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt similarity index 65% rename from core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java rename to core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt index f6056bbee9..e58630587e 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt @@ -25,34 +25,26 @@ * (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.visualization; - -import org.hisp.dhis.android.core.common.BaseIdentifiableObject; -import org.hisp.dhis.android.core.visualization.Visualization; - -import java.text.ParseException; -import java.util.Date; - -import static org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.fillIdentifiableProperties; - -public class VisualizationSamples { - - public static Visualization get() { - Visualization.Builder builder = Visualization.builder(); - - fillIdentifiableProperties(builder); - return builder - .id(1L) - .build(); +package org.hisp.dhis.android.core.visualization + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.arch.handlers.internal.ObjectWithoutUidHandlerImpl +import javax.inject.Inject + +@Reusable +internal class VisualizationHandler @Inject constructor( + store: ObjectWithoutUidStore +) : ObjectWithoutUidHandlerImpl(store) { + + override fun beforeCollectionHandled( + oCollection: Collection + ): Collection { + store.delete() + return oCollection } - private static Date getDate(String dateStr) { - try { - return BaseIdentifiableObject.DATE_FORMAT.parse(dateStr); - } catch (ParseException e) { - e.printStackTrace(); - return null; - } + override fun afterObjectHandled(o: Visualization, action: HandleAction) { } -} \ No newline at end of file +} diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt new file mode 100644 index 0000000000..40553d99ce --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.visualization + +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.common.RelativePeriod +import org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.fillIdentifiableProperties +import org.hisp.dhis.android.core.visualization.* + +object VisualizationSamples { + fun visualization(): Visualization { + val builder: Visualization.Builder = Visualization.builder() + fillIdentifiableProperties(builder) + return builder + .id(1L) + .description("description") + .displayDescription("displayDescription") + .displayFormName("displayFormName") + .type(VisualizationType.RADAR) + .hideTitle(false) + .hideSubtitle(true) + .hideEmptyColumns(false) + .hideEmptyRows(true) + .hideEmptyRowItems(HideEmptyItemStrategy.BEFORE_FIRST) + .hideLegend(false) + .showHierarchy(false) + .rowTotals(true) + .rowSubTotals(true) + .colTotals(false) + .colSubTotals(true) + .showDimensionLabels(false) + .percentStackedValues(true) + .noSpaceBetweenColumns(false) + .skipRounding(true) + .displayDensity(DisplayDensity.COMFORTABLE) + .digitGroupSeparator(DigitGroupSeparator.COMMA) + .relativePeriods(hashMapOf(RelativePeriod.TODAY to true, RelativePeriod.LAST_MONTH to false)) + .filterDimensions(listOf("one", "two", "three")) + .rowDimensions(listOf("a", "b", "c")) + .columnDimensions(listOf("rome", "paris", "berlin")) + .organisationUnitLevels(listOf(1, 2, 3)) + .userOrganisationUnit(true) + .userOrganisationUnitChildren(false) + .userOrganisationUnitGrandChildren(true) + .organisationUnits(listOf(ObjectWithUid.create("org_unit_1"), ObjectWithUid.create("org_unit_2"))) + .periods(listOf(ObjectWithUid.create("2021"), ObjectWithUid.create("2022"))) + .build() + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java index 80167be179..a4d186a11c 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java @@ -48,7 +48,7 @@ public VisualizationShould() { @Test public void map_from_json_string() throws IOException, ParseException { Visualization jsonVisualization = objectMapper.readValue(jsonStream, Visualization.class); - Visualization expectedVisualization = VisualizationSamples.get().toBuilder().id(null).build(); + Visualization expectedVisualization = VisualizationSamples.INSTANCE.visualization().toBuilder().id(null).build(); assertThat(jsonVisualization).isEqualTo(expectedVisualization); } } \ No newline at end of file From a010ef71a30e1af7156241a5e30a2a07d2321eb6 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 2 Jul 2021 17:53:04 +0200 Subject: [PATCH 125/308] [androsdk-1383] Remove todos and fix test --- .../hisp/dhis/android/core/visualization/Visualization.java | 6 +++--- .../android/core/visualization/VisualizationShould.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index 182862db57..ec8f159d1f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -156,7 +156,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(IgnoreCategoryDimensionListColumnAdapter.class) - public abstract List categoryDimensions(); // Table with visualization, category and coptino + public abstract List categoryDimensions(); @Nullable @JsonProperty() @@ -176,7 +176,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(IgnoreDataDimensionItemListColumnAdapter.class) - public abstract List dataDimensionItems(); // Table with visualization id, type and uids with FK. + public abstract List dataDimensionItems(); @Nullable @JsonProperty() @@ -198,7 +198,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(ObjectWithUidListColumnAdapter.class) - public abstract List organisationUnits(); // Cell + public abstract List organisationUnits(); @Nullable @JsonProperty() diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java index 80167be179..62e174e423 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java @@ -48,7 +48,8 @@ public VisualizationShould() { @Test public void map_from_json_string() throws IOException, ParseException { Visualization jsonVisualization = objectMapper.readValue(jsonStream, Visualization.class); - Visualization expectedVisualization = VisualizationSamples.get().toBuilder().id(null).build(); + Visualization expectedVisualization = VisualizationSamples.INSTANCE.visualization() + .toBuilder().id(null).build(); assertThat(jsonVisualization).isEqualTo(expectedVisualization); } } \ No newline at end of file From b8a210b2bb490a186ff2ec57da1c94d5fe0d9ba5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 5 Jul 2021 12:05:36 +0200 Subject: [PATCH 126/308] [ANDROSDK-1395] Undo accidental change in datavalue test --- .../DataValueObjectRepositoryMockIntegrationShould.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java index 929ca2508f..a287d3048e 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datavalue/DataValueObjectRepositoryMockIntegrationShould.java @@ -99,7 +99,7 @@ public void set_state_to_delete_if_state_is_not_to_post() throws D2Error { assertThat(repository.blockingGet().syncState()).isEqualTo(State.ERROR); repository.blockingDelete(); assertThat(repository.blockingExists()).isEqualTo(Boolean.TRUE); - assertThat(repository.blockingGet().syncState()).isEqualTo(Boolean.TRUE); + assertThat(repository.blockingGet().deleted()).isEqualTo(Boolean.TRUE); assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); } @@ -111,12 +111,12 @@ public void set_not_deleted_when_updating_deleted_value() throws D2Error { DataValueStore.create(databaseAdapter).setState(repository.blockingGet(), State.TO_UPDATE); repository.blockingDelete(); - assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); assertThat(repository.blockingGet().deleted()).isEqualTo(Boolean.TRUE); + assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); repository.blockingSet("new_value"); + assertThat(repository.blockingGet().deleted()).isEqualTo(Boolean.FALSE); assertThat(repository.blockingGet().syncState()).isEqualTo(State.TO_UPDATE); - assertThat(repository.blockingGet().syncState()).isEqualTo(Boolean.FALSE); } @Test From 4f4be05d4ea6ea79ab7baf1be8f0417e72a47e8c Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 6 Jul 2021 12:30:55 +0200 Subject: [PATCH 127/308] [ANDROSDK-1395] Adapt deprecated state builder --- .../org/hisp/dhis/android/core/enrollment/Enrollment.java | 4 ++-- .../android/core/trackedentity/TrackedEntityInstance.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java index 6e4d4fdd97..b89f017fa0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java @@ -234,11 +234,11 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder relationships); From 6cfbaadd8d0bbf6645c72ee14579a4a54d569edd Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 5 Jul 2021 14:11:08 +0200 Subject: [PATCH 128/308] [ANDROSDK-1387] Base structure; AnalyticsServiceHelper --- .../analytics/aggregated/AnalyticsModel.kt | 23 +++-- .../aggregated/AnalyticsRepositoryImpl.kt | 61 ++++++++++++++ .../aggregated/AnalyticsRepositoryParams.kt | 34 ++++++++ .../aggregated/DimensionalResponse.kt | 2 +- .../mock/DimensionalResponseSamples.kt | 2 +- .../aggregated/service/AnalyticsService.kt | 67 +++++++++++++++ .../service/AnalyticsServiceEvaluationItem.kt | 37 ++++++++ .../service/AnalyticsServiceHelper.kt | 84 +++++++++++++++++++ 8 files changed, 300 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index fe8701b722..a43d1c151b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -45,6 +45,7 @@ sealed class MetadataItem(val id: String, val displayName: String) { displayName: String, val categoryOptionGroupSet: String ) : MetadataItem(uid, displayName) + class OrganisationUnit(uid: String, displayName: String) : MetadataItem(uid, displayName) class Period( periodId: String, @@ -58,12 +59,12 @@ sealed class Dimension { object Data : Dimension() object Period : Dimension() object OrganisationUnit : Dimension() - class Category(val uid: String) : Dimension() - class CategoryOptionGroupSet(val uid: String) : Dimension() + data class Category(val uid: String) : Dimension() + data class CategoryOptionGroupSet(val uid: String) : Dimension() } sealed class DimensionItem(val dimension: Dimension) { - sealed class DataItem : DimensionItem(Dimension.Data) { + sealed class DataItem : DimensionItem(Dimension.Data), AbsoluteDimensionItem { data class DataElement(val uid: String) : DataItem() data class DataElementOperand(val uid: String, val categoryOptionCombo: String) : DataItem() data class Indicator(val uid: String) : DataItem() @@ -71,21 +72,27 @@ sealed class DimensionItem(val dimension: Dimension) { } sealed class PeriodItem : DimensionItem(Dimension.Period) { - data class Absolute(val periodId: String) : PeriodItem() + data class Absolute(val periodId: String) : PeriodItem(), AbsoluteDimensionItem data class Relative(val relative: RelativePeriod) : PeriodItem() } sealed class OrganisationUnitItem : DimensionItem(Dimension.OrganisationUnit) { - data class Absolute(val uids: List) : OrganisationUnitItem() + data class Absolute(val uid: String) : OrganisationUnitItem(), AbsoluteDimensionItem data class Relative(val relative: RelativeOrganisationUnit) : OrganisationUnitItem() data class Level(val uid: String) : OrganisationUnitItem() data class Group(val uid: String) : OrganisationUnitItem() } - class CategoryItem(val uid: String, val categoryOptions: List) : DimensionItem(Dimension.Category(uid)) + class CategoryItem( + val uid: String, + val categoryOption: String + ) : DimensionItem(Dimension.Category(uid)), AbsoluteDimensionItem + class CategoryOptionGroupSetItem( val uid: String, - val categoryOptionGroups: List - ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid)) + val categoryOptionGroup: String + ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid)), AbsoluteDimensionItem } + +interface AbsoluteDimensionItem \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt new file mode 100644 index 0000000000..6e7eaffa4c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +import io.reactivex.Single +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsService +import javax.inject.Inject + +internal class AnalyticsRepositoryImpl @Inject constructor( + private val params: AnalyticsRepositoryParams, + private val analyticsService: AnalyticsService +) : AnalyticsRepository { + + override fun withDimension(dimensionItem: DimensionItem): AnalyticsRepositoryImpl { + return updateParams { params -> params.copy(dimensions = params.dimensions + dimensionItem) } + } + + override fun withFilter(dimensionItem: DimensionItem): AnalyticsRepositoryImpl { + return updateParams { params -> params.copy(filters = params.filters + dimensionItem) } + } + + override fun evaluate(): Single { + return Single.fromCallable { blockingEvaluate() } + } + + override fun blockingEvaluate(): DimensionalResponse { + return analyticsService.evaluate(params) + } + + private fun updateParams( + func: (params: AnalyticsRepositoryParams) -> AnalyticsRepositoryParams + ): AnalyticsRepositoryImpl { + return AnalyticsRepositoryImpl(func(params), analyticsService) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt new file mode 100644 index 0000000000..0ef40210fa --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +internal data class AnalyticsRepositoryParams( + val dimensions: List, + val filters: List +) \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt index a79eaa9565..688f88f5e1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt @@ -30,7 +30,7 @@ package org.hisp.dhis.android.core.analytics.aggregated data class DimensionalResponse( val metadata: Map, - val dimensions: List, + val dimensions: Set, val filters: List, val values: List ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt index ed1c6ff391..b9b26f52f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -57,7 +57,7 @@ object DimensionalResponseSamples { orgunit1 to MetadataItem.OrganisationUnit(orgunit1, "Ngelehun CHC"), orgunit2 to MetadataItem.OrganisationUnit(orgunit2, "Njandama MCHP") ), - dimensions = listOf(Dimension.Data, Dimension.Category(co1), Dimension.Period), + dimensions = setOf(Dimension.Data, Dimension.Category(co1), Dimension.Period), filters = listOf(orgunit1, orgunit2), values = listOf( DimensionalValue( diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt new file mode 100644 index 0000000000..48a08d88a9 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.Dimension +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue +import javax.inject.Inject + +internal class AnalyticsService @Inject constructor( + private val analyticsServiceHelper: AnalyticsServiceHelper +) { + + fun evaluate(params: AnalyticsRepositoryParams): DimensionalResponse { + if (params.dimensions.isEmpty()) { + throw RuntimeException("At least one dimension must be specified") + } + + if ((params.dimensions + params.filters).none { it.dimension == Dimension.Data }) { + throw RuntimeException("At least one data dimension must be specified") + } + + val dimensions = analyticsServiceHelper.getDimensions(params) + val evaluationItems = analyticsServiceHelper.getEvaluationItems(params, dimensions) + + val values = evaluationItems.map { evaluateItem(it) } + + // TODO + return DimensionalResponse( + metadata = emptyMap(), + dimensions = dimensions, + filters = listOf(), + values = values + ) + } + + private fun evaluateItem(evaluationItem: AnalyticsServiceEvaluationItem): DimensionalValue { + TODO() + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt new file mode 100644 index 0000000000..50448cbbdc --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem + +internal data class AnalyticsServiceEvaluationItem( + val dimensionItems: List, + val filters: List +) \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt new file mode 100644 index 0000000000..0f8efbf477 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.* +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams +import javax.inject.Inject + +internal class AnalyticsServiceHelper @Inject constructor() { + + fun getDimensions(params: AnalyticsRepositoryParams): Set { + return params.dimensions.map { it.dimension }.toSet() + } + + fun getEvaluationItems( + params: AnalyticsRepositoryParams, + dimensions: Set + ): List { + val absoluteDimensionItemList = dimensions.map { dimension -> + params.dimensions + .filter { it.dimension == dimension } + .map { item -> toAbsoluteDimensionItems(item) } + } + + val dimensionCartesianProductList = absoluteDimensionItemList + .fold(listOf(listOf())) { acc, dimension -> + acc.flatMap { list -> dimension.map { element -> list + element } } + } + + return dimensionCartesianProductList.map { dimensionList -> + AnalyticsServiceEvaluationItem( + dimensionItems = dimensionList, + filters = params.filters + ) + } + } + + private fun toAbsoluteDimensionItems(item: DimensionItem): List { + return when(item) { + is DimensionItem.DataItem -> listOf(item) + is DimensionItem.PeriodItem -> + when(item) { + is DimensionItem.PeriodItem.Absolute -> listOf(item) + is DimensionItem.PeriodItem.Relative -> listOf() + } + is DimensionItem.OrganisationUnitItem -> + when(item) { + // TODO + is DimensionItem.OrganisationUnitItem.Absolute -> listOf(item) + is DimensionItem.OrganisationUnitItem.Relative -> listOf() + is DimensionItem.OrganisationUnitItem.Level -> listOf() + is DimensionItem.OrganisationUnitItem.Group -> listOf() + } + is DimensionItem.CategoryItem -> listOf(item) + is DimensionItem.CategoryOptionGroupSetItem -> listOf(item) + } + } +} From 004b624045bb81cefaa1f18cae8e28fa8d3f14c9 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 5 Jul 2021 14:46:04 +0200 Subject: [PATCH 129/308] [ANDROSDK-1387] Add AnalyticsServiceHelper unit tests --- .../analytics/aggregated/AnalyticsModel.kt | 2 +- .../service/AnalyticsServiceHelper.kt | 39 +++- .../service/AnalyticsServiceHelperSamples.kt | 56 +++++ .../service/AnalyticsServiceHelperShould.kt | 198 ++++++++++++++++++ 4 files changed, 286 insertions(+), 9 deletions(-) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index a43d1c151b..e7818fbb55 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -79,7 +79,7 @@ sealed class DimensionItem(val dimension: Dimension) { sealed class OrganisationUnitItem : DimensionItem(Dimension.OrganisationUnit) { data class Absolute(val uid: String) : OrganisationUnitItem(), AbsoluteDimensionItem data class Relative(val relative: RelativeOrganisationUnit) : OrganisationUnitItem() - data class Level(val uid: String) : OrganisationUnitItem() + data class Level(val level: Int) : OrganisationUnitItem() data class Group(val uid: String) : OrganisationUnitItem() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt index 0f8efbf477..057ba915b3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt @@ -28,11 +28,21 @@ package org.hisp.dhis.android.core.analytics.aggregated.service -import org.hisp.dhis.android.core.analytics.aggregated.* +import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.Dimension +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo +import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import javax.inject.Inject -internal class AnalyticsServiceHelper @Inject constructor() { +internal class AnalyticsServiceHelper @Inject constructor( + private val periodGenerator: ParentPeriodGenerator, + private val organisationUnitStore: IdentifiableObjectStore +) { fun getDimensions(params: AnalyticsRepositoryParams): Set { return params.dimensions.map { it.dimension }.toSet() @@ -45,7 +55,7 @@ internal class AnalyticsServiceHelper @Inject constructor() { val absoluteDimensionItemList = dimensions.map { dimension -> params.dimensions .filter { it.dimension == dimension } - .map { item -> toAbsoluteDimensionItems(item) } + .flatMap { item -> toAbsoluteDimensionItems(item) } } val dimensionCartesianProductList = absoluteDimensionItemList @@ -67,18 +77,31 @@ internal class AnalyticsServiceHelper @Inject constructor() { is DimensionItem.PeriodItem -> when(item) { is DimensionItem.PeriodItem.Absolute -> listOf(item) - is DimensionItem.PeriodItem.Relative -> listOf() + is DimensionItem.PeriodItem.Relative -> + periodGenerator.generateRelativePeriods(item.relative).map { period -> + DimensionItem.PeriodItem.Absolute(period.periodId()!!) + } } is DimensionItem.OrganisationUnitItem -> when(item) { - // TODO is DimensionItem.OrganisationUnitItem.Absolute -> listOf(item) - is DimensionItem.OrganisationUnitItem.Relative -> listOf() - is DimensionItem.OrganisationUnitItem.Level -> listOf() - is DimensionItem.OrganisationUnitItem.Group -> listOf() + is DimensionItem.OrganisationUnitItem.Relative -> TODO() + is DimensionItem.OrganisationUnitItem.Level -> + queryOrgunitsByLevel(item.level).map { orgunitUid -> + DimensionItem.OrganisationUnitItem.Absolute(orgunitUid) + } + is DimensionItem.OrganisationUnitItem.Group -> TODO() } is DimensionItem.CategoryItem -> listOf(item) is DimensionItem.CategoryOptionGroupSetItem -> listOf(item) } } + + private fun queryOrgunitsByLevel(level: Int): List { + val whereClause = WhereClauseBuilder() + .appendKeyNumberValue(OrganisationUnitTableInfo.Columns.LEVEL, level) + .build() + + return organisationUnitStore.selectUidsWhere(whereClause) + } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt new file mode 100644 index 0000000000..75a54683eb --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.common.RelativePeriod + +object AnalyticsServiceHelperSamples { + + val dataElementItem1 = DimensionItem.DataItem.DataElement("uid1") + val dataElementItem2 = DimensionItem.DataItem.DataElement("uid2") + val programIndicatorItem = DimensionItem.DataItem.ProgramIndicator("pi1") + val indicatorItem = DimensionItem.DataItem.Indicator("i1") + + val periodAbsolute1 = DimensionItem.PeriodItem.Absolute("202101") + val periodAbsolute2 = DimensionItem.PeriodItem.Absolute("202102") + val periodLast3Days = DimensionItem.PeriodItem.Relative(RelativePeriod.LAST_3_DAYS) + + val orgunitAbsolute = DimensionItem.OrganisationUnitItem.Absolute("ou1") + val orgunitLevel3 = DimensionItem.OrganisationUnitItem.Level(3) + + val categoryItem1_1 = DimensionItem.CategoryItem("c1", "co11") + val categoryItem1_2 = DimensionItem.CategoryItem("c1", "co12") + val categoryItem2_1 = DimensionItem.CategoryItem("c2", "co21") + + val categoryOptionGroupSetItem1_1 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog11") + val categoryOptionGroupSetItem1_2 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog12") + val categoryOptionGroupSetItem2_1 = DimensionItem.CategoryOptionGroupSetItem("cogs2", "cog21") + +} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt new file mode 100644 index 0000000000..16fd48834c --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt @@ -0,0 +1,198 @@ + +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import com.google.common.truth.Truth.assertThat +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.Dimension +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.period.Period +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s +import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class AnalyticsServiceHelperShould { + + private val periodGenerator: ParentPeriodGenerator = mock() + + private val organisationUnitStore: IdentifiableObjectStore = mock() + + private val helper = AnalyticsServiceHelper(periodGenerator, organisationUnitStore) + + @Test + fun `Should extract unique dimension values`() { + val params = AnalyticsRepositoryParams( + dimensions = listOf( + s.dataElementItem1, + s.dataElementItem2, + s.periodAbsolute1, + s.periodAbsolute2, + s.programIndicatorItem, + s.indicatorItem, + s.periodLast3Days, + s.categoryItem1_1, + s.orgunitAbsolute, + s.categoryItem1_2, + s.categoryItem2_1, + s.categoryOptionGroupSetItem1_1 + ), + filters = listOf() + ) + + val dimensionSet = helper.getDimensions(params) + + assertThat(dimensionSet).containsExactly( + Dimension.Data, + Dimension.Period, + Dimension.OrganisationUnit, + Dimension.Category(s.categoryItem1_1.uid), + Dimension.Category(s.categoryItem2_1.uid), + Dimension.CategoryOptionGroupSet(s.categoryOptionGroupSetItem1_1.uid) + ) + } + + @Test + fun `Should generate cartesian product based on given dimensions using absolute arguments`() { + val params = AnalyticsRepositoryParams( + dimensions = listOf( + s.dataElementItem1, + s.periodAbsolute1, + s.indicatorItem, + s.periodAbsolute2, + s.orgunitAbsolute, + s.categoryItem1_1, + s.categoryItem1_2 + ), + filters = listOf() + ) + val dimensions = setOf(Dimension.Period, Dimension.Data, Dimension.OrganisationUnit, + Dimension.Category(s.categoryItem1_1.uid)) + + val items = helper.getEvaluationItems(params, dimensions) + + assertThat(items).containsExactly( + item(s.periodAbsolute1, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_1 ), + item(s.periodAbsolute1, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_2 ), + item(s.periodAbsolute1, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_1 ), + item(s.periodAbsolute1, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_2 ), + item(s.periodAbsolute2, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_1 ), + item(s.periodAbsolute2, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_2 ), + item(s.periodAbsolute2, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_1 ), + item(s.periodAbsolute2, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_2 ) + ) + } + + @Test + fun `Should ignore missing dimensions`() { + val params = AnalyticsRepositoryParams( + dimensions = listOf( + s.dataElementItem1, + s.periodAbsolute1, + s.orgunitAbsolute, + s.categoryItem1_1 + ), + filters = listOf() + ) + val dimensions = setOf(Dimension.Period, Dimension.Data, Dimension.Category(s.categoryItem1_1.uid)) + + val items = helper.getEvaluationItems(params, dimensions) + + assertThat(items).containsExactly( + item(s.periodAbsolute1, s.dataElementItem1, s.categoryItem1_1) + ) + } + + @Test + fun `Should evaluate relative periods`() { + whenever(periodGenerator.generateRelativePeriods(s.periodLast3Days.relative)) + .thenReturn(listOf( + Period.builder().periodId("20210701").build(), + Period.builder().periodId("20210702").build(), + Period.builder().periodId("20210703").build() + )) + + val params = AnalyticsRepositoryParams( + dimensions = listOf( + s.dataElementItem1, + s.periodLast3Days, + s.orgunitAbsolute + ), + filters = listOf() + ) + val dimensions = setOf(Dimension.Data, Dimension.Period, Dimension.OrganisationUnit) + + val items = helper.getEvaluationItems(params, dimensions) + + assertThat(items).containsExactly( + item(s.dataElementItem1, DimensionItem.PeriodItem.Absolute("20210701"), s.orgunitAbsolute), + item(s.dataElementItem1, DimensionItem.PeriodItem.Absolute("20210702"), s.orgunitAbsolute), + item(s.dataElementItem1, DimensionItem.PeriodItem.Absolute("20210703"), s.orgunitAbsolute) + ) + } + + @Test + fun `Should evaluate orgunits by level`() { + whenever(organisationUnitStore.selectUidsWhere(any())).thenReturn(listOf("orgunit1", "orgunit2", "orgunit3")) + + val params = AnalyticsRepositoryParams( + dimensions = listOf( + s.dataElementItem1, + s.periodAbsolute1, + s.orgunitLevel3 + ), + filters = listOf() + ) + val dimensions = setOf(Dimension.Data, Dimension.Period, Dimension.OrganisationUnit) + + val items = helper.getEvaluationItems(params, dimensions) + + assertThat(items).containsExactly( + item(s.dataElementItem1, s.periodAbsolute1, DimensionItem.OrganisationUnitItem.Absolute("orgunit1")), + item(s.dataElementItem1, s.periodAbsolute1, DimensionItem.OrganisationUnitItem.Absolute("orgunit2")), + item(s.dataElementItem1, s.periodAbsolute1, DimensionItem.OrganisationUnitItem.Absolute("orgunit3")) + ) + } + + private fun item(vararg items: AbsoluteDimensionItem): AnalyticsServiceEvaluationItem { + return AnalyticsServiceEvaluationItem( + dimensionItems = items.toList(), + filters = listOf() + ) + } +} \ No newline at end of file From 9c9610bfa74dbef64849951ae38f69807cd62e3a Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 6 Jul 2021 13:56:41 +0200 Subject: [PATCH 130/308] [ANDROSDK-1387] Implement analytics metadata helper --- .../analytics/aggregated/AnalyticsModel.kt | 81 ++++++----- .../aggregated/mock/AggregatedSamples.kt | 54 ++++++-- .../mock/DimensionalResponseSamples.kt | 40 +++--- .../mock/GridAnalyticsResponseSamples.kt | 72 +++++----- .../aggregated/service/AnalyticsService.kt | 7 +- .../service/AnalyticsServiceMetadataHelper.kt | 130 ++++++++++++++++++ .../service/AnalyticsServiceHelperSamples.kt | 8 +- 7 files changed, 282 insertions(+), 110 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index e7818fbb55..b6da3f4470 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -28,31 +28,38 @@ package org.hisp.dhis.android.core.analytics.aggregated -import java.util.* +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.category.CategoryOption import org.hisp.dhis.android.core.common.RelativeOrganisationUnit import org.hisp.dhis.android.core.common.RelativePeriod -import org.hisp.dhis.android.core.period.PeriodType +import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.dataelement.DataElementOperand +import org.hisp.dhis.android.core.indicator.Indicator +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitGroup +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel +import org.hisp.dhis.android.core.period.Period +import org.hisp.dhis.android.core.program.ProgramIndicator sealed class MetadataItem(val id: String, val displayName: String) { - class DataElement(uid: String, displayName: String) : MetadataItem(uid, displayName) - class Indicator(uid: String, displayName: String) : MetadataItem(uid, displayName) - class ProgramIndicator(uid: String, displayName: String) : MetadataItem(uid, displayName) - class Category(uid: String, displayName: String) : MetadataItem(uid, displayName) - class CategoryOption(uid: String, displayName: String, val category: String) : MetadataItem(uid, displayName) - class CategoryOptionGroupSet(uid: String, displayName: String) : MetadataItem(uid, displayName) - class CategoryOptionGroup( - uid: String, - displayName: String, - val categoryOptionGroupSet: String - ) : MetadataItem(uid, displayName) + class DataElementItem(val item: DataElement) : MetadataItem(item.uid(), item.displayName()!!) + class DataElementOperandItem(val item: DataElementOperand) : MetadataItem(item.uid()!!, item.uid()!!) + class IndicatorItem(val item: Indicator) : MetadataItem(item.uid(), item.displayName()!!) + class ProgramIndicatorItem(val item: ProgramIndicator) : MetadataItem(item.uid(), item.displayName()!!) - class OrganisationUnit(uid: String, displayName: String) : MetadataItem(uid, displayName) - class Period( - periodId: String, - val periodType: PeriodType, - val startData: Date, - val endDate: Date - ) : MetadataItem(periodId, periodId) + class CategoryItem(val item: Category) : MetadataItem(item.uid(), item.displayName()!!) + class CategoryOptionItem(val item: CategoryOption) : MetadataItem(item.uid(), item.displayName()!!) + + class CategoryOptionGroupSetItem(uid: String, displayName: String) : MetadataItem(uid, displayName) + class CategoryOptionGroupItem(uid: String, displayName: String) : MetadataItem(uid, displayName) + + class OrganisationUnitItem(val item: OrganisationUnit) : MetadataItem(item.uid(), item.displayName()!!) + class OrganisationUnitLevelItem(val item: OrganisationUnitLevel) : MetadataItem(item.uid(), item.displayName()!!) + class OrganisationUnitGroupItem(val item: OrganisationUnitGroup) : MetadataItem(item.uid(), item.displayName()!!) + class OrganisationUnitRelativeItem(val item: RelativeOrganisationUnit) : MetadataItem(item.name, item.name) + + class PeriodItem(val item: Period) : MetadataItem(item.periodId()!!, item.periodId()!!) + class RelativePeriodItem(val item: RelativePeriod) : MetadataItem(item.name, item.name) } sealed class Dimension { @@ -63,36 +70,36 @@ sealed class Dimension { data class CategoryOptionGroupSet(val uid: String) : Dimension() } -sealed class DimensionItem(val dimension: Dimension) { - sealed class DataItem : DimensionItem(Dimension.Data), AbsoluteDimensionItem { - data class DataElement(val uid: String) : DataItem() - data class DataElementOperand(val uid: String, val categoryOptionCombo: String) : DataItem() - data class Indicator(val uid: String) : DataItem() - data class ProgramIndicator(val uid: String) : DataItem() +sealed class DimensionItem(val dimension: Dimension, val id: String) { + sealed class DataItem(id: String) : DimensionItem(Dimension.Data, id), AbsoluteDimensionItem { + data class DataElementItem(val uid: String) : DataItem(uid) + data class DataElementOperandItem(val uid: String, val categoryOptionCombo: String) : DataItem(uid) + data class IndicatorItem(val uid: String) : DataItem(uid) + data class ProgramIndicatorItem(val uid: String) : DataItem(uid) } - sealed class PeriodItem : DimensionItem(Dimension.Period) { - data class Absolute(val periodId: String) : PeriodItem(), AbsoluteDimensionItem - data class Relative(val relative: RelativePeriod) : PeriodItem() + sealed class PeriodItem(id: String) : DimensionItem(Dimension.Period, id) { + data class Absolute(val periodId: String) : PeriodItem(periodId), AbsoluteDimensionItem + data class Relative(val relative: RelativePeriod) : PeriodItem(relative.name) } - sealed class OrganisationUnitItem : DimensionItem(Dimension.OrganisationUnit) { - data class Absolute(val uid: String) : OrganisationUnitItem(), AbsoluteDimensionItem - data class Relative(val relative: RelativeOrganisationUnit) : OrganisationUnitItem() - data class Level(val level: Int) : OrganisationUnitItem() - data class Group(val uid: String) : OrganisationUnitItem() + sealed class OrganisationUnitItem(id: String) : DimensionItem(Dimension.OrganisationUnit, id) { + data class Absolute(val uid: String) : OrganisationUnitItem(uid), AbsoluteDimensionItem + data class Relative(val relative: RelativeOrganisationUnit) : OrganisationUnitItem(relative.name) + data class Level(val level: Int) : OrganisationUnitItem(level.toString()) + data class Group(val uid: String) : OrganisationUnitItem(uid) } class CategoryItem( val uid: String, val categoryOption: String - ) : DimensionItem(Dimension.Category(uid)), AbsoluteDimensionItem + ) : DimensionItem(Dimension.Category(uid), categoryOption), AbsoluteDimensionItem class CategoryOptionGroupSetItem( val uid: String, val categoryOptionGroup: String - ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid)), AbsoluteDimensionItem + ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid), categoryOptionGroup), AbsoluteDimensionItem } -interface AbsoluteDimensionItem \ No newline at end of file +internal interface AbsoluteDimensionItem \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt index 5b7c729c8d..8b01c3fdf9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt @@ -28,17 +28,53 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.category.CategoryOption +import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.period.Period + object AggregatedSamples { - const val dataElement1 = "fbfJHSPpUQD" // ANC 1st visit - const val dataElement2 = "cYeuwXTCPkU" // ANC 2nd visit + val dataElement1 = DataElement.builder() + .uid("fbfJHSPpUQD") + .displayName("ANC 1st visit") + .build() + + val dataElement2 = DataElement.builder() + .uid("cYeuwXTCPkU") + .displayName("ANC 2nd visit") + .build() + + val cc1 = Category.builder() + .uid("fMZEcRHuamy") + .displayName("Fixed / Outreach") + .build() + + val co1 = CategoryOption.builder() + .uid("pq2XI5kz2BY") + .displayName("Fixed") + .build() + + val co2 = CategoryOption.builder() + .uid("PT59n8BQbqM") + .name("Outreach") + .build() + + val period1 = Period.builder() + .periodId("202103") + .build() - const val cc1 = "fMZEcRHuamy" // Fixed / Outreach - const val co1 = "pq2XI5kz2BY" // Fixed - const val co2 = "PT59n8BQbqM" // Outreach + val period2 = Period.builder() + .periodId("202104") + .build() - const val period1 = "202103" - const val period2 = "202102" + val orgunit1 = OrganisationUnit.builder() + .uid("DiszpKrYNg8") + .displayName("Ngelehun") + .build() - const val orgunit1 = "DiszpKrYNg8" // Ngelehun - const val orgunit2 = "g8upMTyEZGZ" // Njandama + val orgunit2 = OrganisationUnit.builder() + .uid("g8upMTyEZGZ") + .name("Njandama") + .build() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt index b9b26f52f1..9a9a500d1e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock -import java.util.* import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue @@ -42,54 +41,53 @@ import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.or import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit2 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period2 -import org.hisp.dhis.android.core.period.PeriodType object DimensionalResponseSamples { val sample1 = DimensionalResponse( metadata = mapOf( - dataElement1 to MetadataItem.DataElement(dataElement1, "ANC 1st visit"), - dataElement2 to MetadataItem.DataElement(dataElement2, "ANC 2nd visit"), - co1 to MetadataItem.CategoryOption(co1, "Fixed", cc1), - co2 to MetadataItem.CategoryOption(co2, "Outreach", cc1), - cc1 to MetadataItem.Category(cc1, "Fixed / Outreach"), - period1 to MetadataItem.Period(period1, PeriodType.Daily, Date(), Date()), - period2 to MetadataItem.Period(period2, PeriodType.Daily, Date(), Date()), - orgunit1 to MetadataItem.OrganisationUnit(orgunit1, "Ngelehun CHC"), - orgunit2 to MetadataItem.OrganisationUnit(orgunit2, "Njandama MCHP") + dataElement1.uid() to MetadataItem.DataElementItem(dataElement1), + dataElement2.uid() to MetadataItem.DataElementItem(dataElement2), + co1.uid() to MetadataItem.CategoryOptionItem(co1), + co2.uid() to MetadataItem.CategoryOptionItem(co2), + cc1.uid() to MetadataItem.CategoryItem(cc1), + period1.periodId()!! to MetadataItem.PeriodItem(period1), + period2.periodId()!! to MetadataItem.PeriodItem(period2), + orgunit1.uid() to MetadataItem.OrganisationUnitItem(orgunit1), + orgunit2.uid() to MetadataItem.OrganisationUnitItem(orgunit2) ), - dimensions = setOf(Dimension.Data, Dimension.Category(co1), Dimension.Period), - filters = listOf(orgunit1, orgunit2), + dimensions = setOf(Dimension.Data, Dimension.Category(cc1.uid()), Dimension.Period), + filters = listOf(orgunit1.uid(), orgunit2.uid()), values = listOf( DimensionalValue( - listOf(dataElement1, co1, period1), + listOf(dataElement1.uid(), co1.uid(), period1.periodId()!!), "34.5" ), DimensionalValue( - listOf(dataElement1, co2, period1), + listOf(dataElement1.uid(), co2.uid(), period1.periodId()!!), "10.0" ), DimensionalValue( - listOf(dataElement2, co1, period1), + listOf(dataElement2.uid(), co1.uid(), period1.periodId()!!), "13" ), DimensionalValue( - listOf(dataElement2, co2, period1), + listOf(dataElement2.uid(), co2.uid(), period1.periodId()!!), "15" ), DimensionalValue( - listOf(dataElement1, co1, period2), + listOf(dataElement1.uid(), co1.uid(), period2.periodId()!!), "34.5" ), DimensionalValue( - listOf(dataElement1, co2, period2), + listOf(dataElement1.uid(), co2.uid(), period2.periodId()!!), "10.0" ), DimensionalValue( - listOf(dataElement2, co1, period2), + listOf(dataElement2.uid(), co1.uid(), period2.periodId()!!), "13" ), DimensionalValue( - listOf(dataElement2, co2, period2), + listOf(dataElement2.uid(), co2.uid(), period2.periodId()!!), "15" ) ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt index 05ccce346b..7073f81d8b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock -import java.util.* import org.hisp.dhis.android.core.analytics.aggregated.* import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co1 @@ -39,88 +38,87 @@ import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.or import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit2 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.period2 -import org.hisp.dhis.android.core.period.PeriodType object GridAnalyticsResponseSamples { val sample1 = GridAnalyticsResponse( metadata = mapOf( - dataElement1 to MetadataItem.DataElement(dataElement1, "ANC 1st visit"), - dataElement2 to MetadataItem.DataElement(dataElement2, "ANC 2nd visit"), - co1 to MetadataItem.CategoryOption(co1, "Fixed", cc1), - co2 to MetadataItem.CategoryOption(co2, "Outreach", cc1), - cc1 to MetadataItem.Category(cc1, "Fixed / Outreach"), - period1 to MetadataItem.Period(period1, PeriodType.Daily, Date(), Date()), - period2 to MetadataItem.Period(period2, PeriodType.Daily, Date(), Date()), - orgunit1 to MetadataItem.OrganisationUnit(orgunit1, "Ngelehun CHC"), - orgunit2 to MetadataItem.OrganisationUnit(orgunit2, "Njandama MCHP") + dataElement1.uid() to MetadataItem.DataElementItem(dataElement1), + dataElement2.uid() to MetadataItem.DataElementItem(dataElement2), + co1.uid() to MetadataItem.CategoryOptionItem(co1), + co2.uid() to MetadataItem.CategoryOptionItem(co2), + cc1.uid() to MetadataItem.CategoryItem(cc1), + period1.periodId()!! to MetadataItem.PeriodItem(period1), + period2.periodId()!! to MetadataItem.PeriodItem(period2), + orgunit1.uid() to MetadataItem.OrganisationUnitItem(orgunit1), + orgunit2.uid() to MetadataItem.OrganisationUnitItem(orgunit2) ), headers = GridHeader( columns = listOf( listOf( - GridHeaderItem(dataElement1, 2), - GridHeaderItem(dataElement2, 2) + GridHeaderItem(dataElement1.uid(), 2), + GridHeaderItem(dataElement2.uid(), 2) ), listOf( - GridHeaderItem(co1, 1), - GridHeaderItem(co2, 1), - GridHeaderItem(co1, 1), - GridHeaderItem(co2, 1) + GridHeaderItem(co1.uid(), 1), + GridHeaderItem(co2.uid(), 1), + GridHeaderItem(co1.uid(), 1), + GridHeaderItem(co2.uid(), 1) ) ), rows = listOf( listOf( - GridHeaderItem(period1, 1), - GridHeaderItem(period2, 1) + GridHeaderItem(period1.periodId()!!, 1), + GridHeaderItem(period2.periodId()!!, 1) ) ) ), dimensions = GridDimension( - columns = listOf(Dimension.Data, Dimension.Category(co1)), + columns = listOf(Dimension.Data, Dimension.Category(cc1.uid())), rows = listOf(Dimension.Period) ), - filters = listOf(orgunit1, orgunit2), + filters = listOf(orgunit1.uid(), orgunit2.uid()), values = listOf( listOf( GridResponseValue( - listOf(dataElement1, co1), - listOf(period1), + listOf(dataElement1.uid(), co1.uid()), + listOf(period1.periodId()!!), "34.5" ), GridResponseValue( - listOf(dataElement1, co2), - listOf(period1), + listOf(dataElement1.uid(), co2.uid()), + listOf(period1.periodId()!!), "10.0" ), GridResponseValue( - listOf(dataElement2, co1), - listOf(period1), + listOf(dataElement2.uid(), co1.uid()), + listOf(period1.periodId()!!), "13" ), GridResponseValue( - listOf(dataElement2, co2), - listOf(period1), + listOf(dataElement2.uid(), co2.uid()), + listOf(period1.periodId()!!), "15" ) ), listOf( GridResponseValue( - listOf(dataElement1, co1), - listOf(period2), + listOf(dataElement1.uid(), co1.uid()), + listOf(period2.periodId()!!), "34.5" ), GridResponseValue( - listOf(dataElement1, co2), - listOf(period2), + listOf(dataElement1.uid(), co2.uid()), + listOf(period2.periodId()!!), "10.0" ), GridResponseValue( - listOf(dataElement2, co1), - listOf(period2), + listOf(dataElement2.uid(), co1.uid()), + listOf(period2.periodId()!!), "13" ), GridResponseValue( - listOf(dataElement2, co2), - listOf(period2), + listOf(dataElement2.uid(), co2.uid()), + listOf(period2.periodId()!!), "15" ) ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt index 48a08d88a9..a6514dccd3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt @@ -35,7 +35,8 @@ import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue import javax.inject.Inject internal class AnalyticsService @Inject constructor( - private val analyticsServiceHelper: AnalyticsServiceHelper + private val analyticsServiceHelper: AnalyticsServiceHelper, + private val analyticsServiceMetadataHelper: AnalyticsServiceMetadataHelper ) { fun evaluate(params: AnalyticsRepositoryParams): DimensionalResponse { @@ -50,11 +51,13 @@ internal class AnalyticsService @Inject constructor( val dimensions = analyticsServiceHelper.getDimensions(params) val evaluationItems = analyticsServiceHelper.getEvaluationItems(params, dimensions) + val metadata = analyticsServiceMetadataHelper.getMetadata(evaluationItems) + val values = evaluationItems.map { evaluateItem(it) } // TODO return DimensionalResponse( - metadata = emptyMap(), + metadata = metadata, dimensions = dimensions, filters = listOf(), values = values diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt new file mode 100644 index 0000000000..c7c6518028 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.category.CategoryOption +import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.dataelement.DataElementOperand +import org.hisp.dhis.android.core.indicator.Indicator +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitGroup +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevelTableInfo +import org.hisp.dhis.android.core.period.internal.PeriodHelper +import org.hisp.dhis.android.core.program.ProgramIndicator +import javax.inject.Inject + +internal class AnalyticsServiceMetadataHelper @Inject constructor( + private val categoryStore: IdentifiableObjectStore, + private val categoryOptionStore: IdentifiableObjectStore, + private val dataElementStore: IdentifiableObjectStore, + private val dataElementOperandStore: IdentifiableObjectStore, + private val indicatorStore: IdentifiableObjectStore, + private val organisationUnitStore: IdentifiableObjectStore, + private val organisationUnitGroupStore: IdentifiableObjectStore, + private val organisationUnitLevelStore: IdentifiableObjectStore, + private val programIndicatorStore: IdentifiableObjectStore, + private val periodHelper: PeriodHelper +) { + + fun getMetadata(evaluationItems: List): Map { + val metadata: MutableMap = mutableMapOf() + + evaluationItems.forEach { evaluationItem -> + (evaluationItem.dimensionItems + evaluationItem.filters) + .map { it as DimensionItem } + .forEach { item -> + if (!metadata.containsKey(item.id)) { + getMetadataItems(item).forEach { metadataItem -> + metadata += metadataItem.id to metadataItem + } + } + } + } + + return metadata + } + + private fun getMetadataItems(item: DimensionItem): List { + return when (item) { + is DimensionItem.DataItem -> listOf( + when (item) { + is DimensionItem.DataItem.DataElementItem -> dataElementStore.selectByUid(item.uid)!! + .let { dataElement -> MetadataItem.DataElementItem(dataElement) } + // TODO Build a meaningful name for DataElementOperand + is DimensionItem.DataItem.DataElementOperandItem -> dataElementOperandStore.selectByUid(item.uid)!! + .let { dataElementOperand -> MetadataItem.DataElementOperandItem(dataElementOperand) } + is DimensionItem.DataItem.IndicatorItem -> indicatorStore.selectByUid(item.uid)!! + .let { indicator -> MetadataItem.IndicatorItem(indicator) } + is DimensionItem.DataItem.ProgramIndicatorItem -> programIndicatorStore.selectByUid(item.uid)!! + .let { programIndicator -> MetadataItem.ProgramIndicatorItem(programIndicator) } + }) + + is DimensionItem.PeriodItem -> listOf( + when (item) { + is DimensionItem.PeriodItem.Absolute -> periodHelper.blockingGetPeriodForPeriodId(item.periodId) + .let { period -> MetadataItem.PeriodItem(period) } + is DimensionItem.PeriodItem.Relative -> + MetadataItem.RelativePeriodItem(item.relative) + }) + + is DimensionItem.OrganisationUnitItem -> listOf( + when (item) { + is DimensionItem.OrganisationUnitItem.Absolute -> organisationUnitStore.selectByUid(item.uid)!! + .let { organisationUnit -> MetadataItem.OrganisationUnitItem(organisationUnit) } + is DimensionItem.OrganisationUnitItem.Relative -> + MetadataItem.OrganisationUnitRelativeItem(item.relative) + is DimensionItem.OrganisationUnitItem.Level -> { + val levelClauseBuilder = WhereClauseBuilder() + .appendKeyNumberValue(OrganisationUnitLevelTableInfo.Columns.LEVEL, item.level) + .build() + organisationUnitLevelStore.selectOneWhere(levelClauseBuilder)!! + .let { level -> MetadataItem.OrganisationUnitLevelItem(level) } + } + is DimensionItem.OrganisationUnitItem.Group -> organisationUnitGroupStore.selectByUid(item.uid)!! + .let { organisationUnitGroup -> MetadataItem.OrganisationUnitGroupItem(organisationUnitGroup) } + }) + + is DimensionItem.CategoryItem -> listOf( + categoryStore.selectByUid(item.uid)!! + .let { category -> MetadataItem.CategoryItem(category) }, + categoryOptionStore.selectByUid(item.categoryOption)!! + .let { categoryOption -> MetadataItem.CategoryOptionItem(categoryOption) } + ) + + // TODO + is DimensionItem.CategoryOptionGroupSetItem -> listOf() + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt index 75a54683eb..2ff51ef441 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt @@ -33,10 +33,10 @@ import org.hisp.dhis.android.core.common.RelativePeriod object AnalyticsServiceHelperSamples { - val dataElementItem1 = DimensionItem.DataItem.DataElement("uid1") - val dataElementItem2 = DimensionItem.DataItem.DataElement("uid2") - val programIndicatorItem = DimensionItem.DataItem.ProgramIndicator("pi1") - val indicatorItem = DimensionItem.DataItem.Indicator("i1") + val dataElementItem1 = DimensionItem.DataItem.DataElementItem("uid1") + val dataElementItem2 = DimensionItem.DataItem.DataElementItem("uid2") + val programIndicatorItem = DimensionItem.DataItem.ProgramIndicatorItem("pi1") + val indicatorItem = DimensionItem.DataItem.IndicatorItem("i1") val periodAbsolute1 = DimensionItem.PeriodItem.Absolute("202101") val periodAbsolute2 = DimensionItem.PeriodItem.Absolute("202102") From 926b0ae6f49d1a71c940c9ce0ff2417eca008052 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 6 Jul 2021 14:58:43 +0200 Subject: [PATCH 131/308] [ANDROSDK-1387] Add analytics metadata helper test --- .../aggregated/mock/AggregatedSamples.kt | 30 +++++- .../mock/DimensionalResponseSamples.kt | 24 ++--- .../mock/GridAnalyticsResponseSamples.kt | 32 +++--- .../service/AnalyticsServiceHelperSamples.kt | 21 ++-- .../AnalyticsServiceMetadataHelperShould.kt | 99 +++++++++++++++++++ 5 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt index 8b01c3fdf9..def5a0ac45 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/AggregatedSamples.kt @@ -31,8 +31,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.category.CategoryOption import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.indicator.Indicator import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.period.Period +import org.hisp.dhis.android.core.program.ProgramIndicator object AggregatedSamples { val dataElement1 = DataElement.builder() @@ -45,19 +47,39 @@ object AggregatedSamples { .displayName("ANC 2nd visit") .build() + val programIndicator1 = ProgramIndicator.builder() + .uid("p2Zxg0wcPQ3") + .displayName("BCG doses") + .build() + + val indicator1 = Indicator.builder() + .uid("Uvn6LCg7dVU") + .displayName("ANC 1 Coverage") + .build() + val cc1 = Category.builder() .uid("fMZEcRHuamy") .displayName("Fixed / Outreach") .build() - val co1 = CategoryOption.builder() + val co11 = CategoryOption.builder() .uid("pq2XI5kz2BY") .displayName("Fixed") .build() - val co2 = CategoryOption.builder() + val co12 = CategoryOption.builder() .uid("PT59n8BQbqM") - .name("Outreach") + .displayName("Outreach") + .build() + + val cc2 = Category.builder() + .uid("cX5k9anHEHd") + .displayName("Gender") + .build() + + val co21 = CategoryOption.builder() + .uid("jRbMi0aBjYn") + .displayName("Male") .build() val period1 = Period.builder() @@ -75,6 +97,6 @@ object AggregatedSamples { val orgunit2 = OrganisationUnit.builder() .uid("g8upMTyEZGZ") - .name("Njandama") + .displayName("Njandama") .build() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt index 9a9a500d1e..acf323e973 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -33,8 +33,8 @@ import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 -import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co1 -import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co11 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co12 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement2 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit1 @@ -47,8 +47,8 @@ object DimensionalResponseSamples { metadata = mapOf( dataElement1.uid() to MetadataItem.DataElementItem(dataElement1), dataElement2.uid() to MetadataItem.DataElementItem(dataElement2), - co1.uid() to MetadataItem.CategoryOptionItem(co1), - co2.uid() to MetadataItem.CategoryOptionItem(co2), + co11.uid() to MetadataItem.CategoryOptionItem(co11), + co12.uid() to MetadataItem.CategoryOptionItem(co12), cc1.uid() to MetadataItem.CategoryItem(cc1), period1.periodId()!! to MetadataItem.PeriodItem(period1), period2.periodId()!! to MetadataItem.PeriodItem(period2), @@ -59,35 +59,35 @@ object DimensionalResponseSamples { filters = listOf(orgunit1.uid(), orgunit2.uid()), values = listOf( DimensionalValue( - listOf(dataElement1.uid(), co1.uid(), period1.periodId()!!), + listOf(dataElement1.uid(), co11.uid(), period1.periodId()!!), "34.5" ), DimensionalValue( - listOf(dataElement1.uid(), co2.uid(), period1.periodId()!!), + listOf(dataElement1.uid(), co12.uid(), period1.periodId()!!), "10.0" ), DimensionalValue( - listOf(dataElement2.uid(), co1.uid(), period1.periodId()!!), + listOf(dataElement2.uid(), co11.uid(), period1.periodId()!!), "13" ), DimensionalValue( - listOf(dataElement2.uid(), co2.uid(), period1.periodId()!!), + listOf(dataElement2.uid(), co12.uid(), period1.periodId()!!), "15" ), DimensionalValue( - listOf(dataElement1.uid(), co1.uid(), period2.periodId()!!), + listOf(dataElement1.uid(), co11.uid(), period2.periodId()!!), "34.5" ), DimensionalValue( - listOf(dataElement1.uid(), co2.uid(), period2.periodId()!!), + listOf(dataElement1.uid(), co12.uid(), period2.periodId()!!), "10.0" ), DimensionalValue( - listOf(dataElement2.uid(), co1.uid(), period2.periodId()!!), + listOf(dataElement2.uid(), co11.uid(), period2.periodId()!!), "13" ), DimensionalValue( - listOf(dataElement2.uid(), co2.uid(), period2.periodId()!!), + listOf(dataElement2.uid(), co12.uid(), period2.periodId()!!), "15" ) ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt index 7073f81d8b..e5662c0818 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt @@ -30,8 +30,8 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock import org.hisp.dhis.android.core.analytics.aggregated.* import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 -import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co1 -import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co2 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co11 +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co12 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.dataElement2 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.orgunit1 @@ -44,8 +44,8 @@ object GridAnalyticsResponseSamples { metadata = mapOf( dataElement1.uid() to MetadataItem.DataElementItem(dataElement1), dataElement2.uid() to MetadataItem.DataElementItem(dataElement2), - co1.uid() to MetadataItem.CategoryOptionItem(co1), - co2.uid() to MetadataItem.CategoryOptionItem(co2), + co11.uid() to MetadataItem.CategoryOptionItem(co11), + co12.uid() to MetadataItem.CategoryOptionItem(co12), cc1.uid() to MetadataItem.CategoryItem(cc1), period1.periodId()!! to MetadataItem.PeriodItem(period1), period2.periodId()!! to MetadataItem.PeriodItem(period2), @@ -59,10 +59,10 @@ object GridAnalyticsResponseSamples { GridHeaderItem(dataElement2.uid(), 2) ), listOf( - GridHeaderItem(co1.uid(), 1), - GridHeaderItem(co2.uid(), 1), - GridHeaderItem(co1.uid(), 1), - GridHeaderItem(co2.uid(), 1) + GridHeaderItem(co11.uid(), 1), + GridHeaderItem(co12.uid(), 1), + GridHeaderItem(co11.uid(), 1), + GridHeaderItem(co12.uid(), 1) ) ), rows = listOf( @@ -80,44 +80,44 @@ object GridAnalyticsResponseSamples { values = listOf( listOf( GridResponseValue( - listOf(dataElement1.uid(), co1.uid()), + listOf(dataElement1.uid(), co11.uid()), listOf(period1.periodId()!!), "34.5" ), GridResponseValue( - listOf(dataElement1.uid(), co2.uid()), + listOf(dataElement1.uid(), co12.uid()), listOf(period1.periodId()!!), "10.0" ), GridResponseValue( - listOf(dataElement2.uid(), co1.uid()), + listOf(dataElement2.uid(), co11.uid()), listOf(period1.periodId()!!), "13" ), GridResponseValue( - listOf(dataElement2.uid(), co2.uid()), + listOf(dataElement2.uid(), co12.uid()), listOf(period1.periodId()!!), "15" ) ), listOf( GridResponseValue( - listOf(dataElement1.uid(), co1.uid()), + listOf(dataElement1.uid(), co11.uid()), listOf(period2.periodId()!!), "34.5" ), GridResponseValue( - listOf(dataElement1.uid(), co2.uid()), + listOf(dataElement1.uid(), co12.uid()), listOf(period2.periodId()!!), "10.0" ), GridResponseValue( - listOf(dataElement2.uid(), co1.uid()), + listOf(dataElement2.uid(), co11.uid()), listOf(period2.periodId()!!), "13" ), GridResponseValue( - listOf(dataElement2.uid(), co2.uid()), + listOf(dataElement2.uid(), co12.uid()), listOf(period2.periodId()!!), "15" ) diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt index 2ff51ef441..065314a060 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt @@ -29,25 +29,26 @@ package org.hisp.dhis.android.core.analytics.aggregated.service import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples import org.hisp.dhis.android.core.common.RelativePeriod object AnalyticsServiceHelperSamples { - val dataElementItem1 = DimensionItem.DataItem.DataElementItem("uid1") - val dataElementItem2 = DimensionItem.DataItem.DataElementItem("uid2") - val programIndicatorItem = DimensionItem.DataItem.ProgramIndicatorItem("pi1") - val indicatorItem = DimensionItem.DataItem.IndicatorItem("i1") + val dataElementItem1 = DimensionItem.DataItem.DataElementItem(AggregatedSamples.dataElement1.uid()) + val dataElementItem2 = DimensionItem.DataItem.DataElementItem(AggregatedSamples.dataElement2.uid()) + val programIndicatorItem = DimensionItem.DataItem.ProgramIndicatorItem(AggregatedSamples.programIndicator1.uid()) + val indicatorItem = DimensionItem.DataItem.IndicatorItem(AggregatedSamples.indicator1.uid()) - val periodAbsolute1 = DimensionItem.PeriodItem.Absolute("202101") - val periodAbsolute2 = DimensionItem.PeriodItem.Absolute("202102") + val periodAbsolute1 = DimensionItem.PeriodItem.Absolute(AggregatedSamples.period1.periodId()!!) + val periodAbsolute2 = DimensionItem.PeriodItem.Absolute(AggregatedSamples.period2.periodId()!!) val periodLast3Days = DimensionItem.PeriodItem.Relative(RelativePeriod.LAST_3_DAYS) - val orgunitAbsolute = DimensionItem.OrganisationUnitItem.Absolute("ou1") + val orgunitAbsolute = DimensionItem.OrganisationUnitItem.Absolute(AggregatedSamples.orgunit1.uid()) val orgunitLevel3 = DimensionItem.OrganisationUnitItem.Level(3) - val categoryItem1_1 = DimensionItem.CategoryItem("c1", "co11") - val categoryItem1_2 = DimensionItem.CategoryItem("c1", "co12") - val categoryItem2_1 = DimensionItem.CategoryItem("c2", "co21") + val categoryItem1_1 = DimensionItem.CategoryItem(AggregatedSamples.cc1.uid(), AggregatedSamples.co11.uid()) + val categoryItem1_2 = DimensionItem.CategoryItem(AggregatedSamples.cc1.uid(), AggregatedSamples.co12.uid()) + val categoryItem2_1 = DimensionItem.CategoryItem(AggregatedSamples.cc2.uid(), AggregatedSamples.co21.uid()) val categoryOptionGroupSetItem1_1 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog11") val categoryOptionGroupSetItem1_2 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog12") diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt new file mode 100644 index 0000000000..2aac37b35c --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import com.google.common.truth.Truth.assertThat +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.category.CategoryOption +import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.dataelement.DataElementOperand +import org.hisp.dhis.android.core.indicator.Indicator +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitGroup +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel +import org.hisp.dhis.android.core.period.internal.PeriodHelper +import org.hisp.dhis.android.core.program.ProgramIndicator +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s + +@RunWith(JUnit4::class) +class AnalyticsServiceMetadataHelperShould { + + private val categoryStore: IdentifiableObjectStore = mock() + private val categoryOptionStore: IdentifiableObjectStore = mock() + private val dataElementStore: IdentifiableObjectStore = mock() + private val dataElementOperandStore: IdentifiableObjectStore = mock() + private val indicatorStore: IdentifiableObjectStore = mock() + private val organisationUnitStore: IdentifiableObjectStore = mock() + private val organisationUnitGroupStore: IdentifiableObjectStore = mock() + private val organisationUnitLevelStore: IdentifiableObjectStore = mock() + private val programIndicatorStore: IdentifiableObjectStore = mock() + private val periodHelper: PeriodHelper = mock() + + private val helper = AnalyticsServiceMetadataHelper( + categoryStore, + categoryOptionStore, + dataElementStore, + dataElementOperandStore, + indicatorStore, + organisationUnitStore, + organisationUnitGroupStore, + organisationUnitLevelStore, + programIndicatorStore, + periodHelper + ) + + @Test + fun `Should extract category and category option metadata items`() { + whenever(categoryStore.selectByUid(s.categoryItem1_1.uid)).thenReturn(AggregatedSamples.cc1) + whenever(categoryOptionStore.selectByUid(s.categoryItem1_1.categoryOption)).thenReturn(AggregatedSamples.co11) + whenever(categoryOptionStore.selectByUid(s.categoryItem1_2.categoryOption)).thenReturn(AggregatedSamples.co12) + + val evaluationItems = listOf( + AnalyticsServiceEvaluationItem( + dimensionItems = listOf(s.categoryItem1_1, s.categoryItem1_2), + filters = listOf() + ) + ) + + val metadataMap = helper.getMetadata(evaluationItems) + + assertThat(metadataMap.keys).containsExactly( + s.categoryItem1_1.uid, + s.categoryItem1_1.categoryOption, + s.categoryItem1_2.categoryOption + ) + } +} \ No newline at end of file From 8921294d904d43245be612b36b299ec95e7681c3 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 7 Jul 2021 10:50:14 +0200 Subject: [PATCH 132/308] [androsdk-1383] Complete visualizationShould test --- .../visualization/VisualizationSamples.kt | 103 +++++++++++------- .../visualization/visualization.json | 2 +- .../visualization_simplified.json | 97 +++++++++++++++++ .../visualization/VisualizationShould.java | 5 +- 4 files changed, 165 insertions(+), 42 deletions(-) create mode 100644 core/src/sharedTest/resources/visualization/visualization_simplified.json diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt index 40553d99ce..8b876a64db 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationSamples.kt @@ -29,46 +29,71 @@ package org.hisp.dhis.android.core.data.visualization import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.common.RelativePeriod -import org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.fillIdentifiableProperties +import org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils import org.hisp.dhis.android.core.visualization.* object VisualizationSamples { - fun visualization(): Visualization { - val builder: Visualization.Builder = Visualization.builder() - fillIdentifiableProperties(builder) - return builder - .id(1L) - .description("description") - .displayDescription("displayDescription") - .displayFormName("displayFormName") - .type(VisualizationType.RADAR) - .hideTitle(false) - .hideSubtitle(true) - .hideEmptyColumns(false) - .hideEmptyRows(true) - .hideEmptyRowItems(HideEmptyItemStrategy.BEFORE_FIRST) - .hideLegend(false) - .showHierarchy(false) - .rowTotals(true) - .rowSubTotals(true) - .colTotals(false) - .colSubTotals(true) - .showDimensionLabels(false) - .percentStackedValues(true) - .noSpaceBetweenColumns(false) - .skipRounding(true) - .displayDensity(DisplayDensity.COMFORTABLE) - .digitGroupSeparator(DigitGroupSeparator.COMMA) - .relativePeriods(hashMapOf(RelativePeriod.TODAY to true, RelativePeriod.LAST_MONTH to false)) - .filterDimensions(listOf("one", "two", "three")) - .rowDimensions(listOf("a", "b", "c")) - .columnDimensions(listOf("rome", "paris", "berlin")) - .organisationUnitLevels(listOf(1, 2, 3)) - .userOrganisationUnit(true) - .userOrganisationUnitChildren(false) - .userOrganisationUnitGrandChildren(true) - .organisationUnits(listOf(ObjectWithUid.create("org_unit_1"), ObjectWithUid.create("org_unit_2"))) - .periods(listOf(ObjectWithUid.create("2021"), ObjectWithUid.create("2022"))) - .build() - } + + private const val DATE_STR = "2021-06-16T14:26:50.195" + private val DATE = FillPropertiesTestUtils.parseDate(DATE_STR) + + fun visualization(): Visualization = Visualization.builder() + .id(1L) + .uid("PYBH8ZaAQnC") + .name("Android SDK Visualization sample") + .displayName("Android SDK Visualization sample") + .created(DATE) + .lastUpdated(DATE) + .description("Sample visualization for the Android SDK") + .displayDescription("Sample visualization for the Android SDK") + .displayFormName("Android SDK Visualization sample") + .type(VisualizationType.PIVOT_TABLE) + .hideTitle(false) + .hideSubtitle(false) + .hideEmptyColumns(false) + .hideEmptyRows(false) + .hideEmptyRowItems(HideEmptyItemStrategy.NONE) + .hideLegend(false) + .showHierarchy(false) + .rowTotals(true) + .rowSubTotals(false) + .colTotals(false) + .colSubTotals(false) + .showDimensionLabels(false) + .percentStackedValues(false) + .noSpaceBetweenColumns(false) + .skipRounding(false) + .displayDensity(DisplayDensity.NORMAL) + .digitGroupSeparator(DigitGroupSeparator.COMMA) + .relativePeriods(hashMapOf(RelativePeriod.THIS_YEAR to false, RelativePeriod.LAST_12_MONTHS to true)) + .categoryDimensions( + listOf( + CategoryDimension.builder() + .category(ObjectWithUid.create("fMZEcRHuamy")) + .categoryOptions(listOf(ObjectWithUid.create("qkPbeWaFsnU"), ObjectWithUid.create("wbrDrL2aYEc"))) + .build() + ) + ) + .filterDimensions(listOf("ou")) + .rowDimensions(listOf("pe")) + .columnDimensions(listOf("dx", "fMZEcRHuamy", "fkAkrdC7eJF")) + .dataDimensionItems( + listOf( + DataDimensionItem.builder() + .dataDimensionItemType(DataDimensionItemType.INDICATOR) + .indicator(ObjectWithUid.create("Uvn6LCg7dVU")) + .build(), + DataDimensionItem.builder() + .dataDimensionItemType(DataDimensionItemType.DATA_ELEMENT) + .dataElement(ObjectWithUid.create("cYeuwXTCPkU")) + .build() + ) + ) + .organisationUnitLevels(listOf(3)) + .userOrganisationUnit(false) + .userOrganisationUnitChildren(false) + .userOrganisationUnitGrandChildren(false) + .organisationUnits(listOf(ObjectWithUid.create("YuQRtpLP10I"), ObjectWithUid.create("vWbkYPRmKyS"))) + .periods(listOf(ObjectWithUid.create("202102"), ObjectWithUid.create("202103"), ObjectWithUid.create("2021S2"))) + .build() } diff --git a/core/src/sharedTest/resources/visualization/visualization.json b/core/src/sharedTest/resources/visualization/visualization.json index f57476a51f..533490fc2e 100644 --- a/core/src/sharedTest/resources/visualization/visualization.json +++ b/core/src/sharedTest/resources/visualization/visualization.json @@ -15,7 +15,7 @@ "hideEmptyRowItems": "NONE", "hideLegend": false, "showHierarchy": false, - "rowTotals": false, + "rowTotals": true, "rowSubTotals": false, "colTotals": false, "colSubTotals": false, diff --git a/core/src/sharedTest/resources/visualization/visualization_simplified.json b/core/src/sharedTest/resources/visualization/visualization_simplified.json new file mode 100644 index 0000000000..7bec14d6e4 --- /dev/null +++ b/core/src/sharedTest/resources/visualization/visualization_simplified.json @@ -0,0 +1,97 @@ +{ + "id": "PYBH8ZaAQnC", + "name": "Android SDK Visualization sample", + "displayName": "Android SDK Visualization sample", + "description": "Sample visualization for the Android SDK", + "displayDescription": "Sample visualization for the Android SDK", + "displayFormName": "Android SDK Visualization sample", + "lastUpdated": "2021-06-16T14:26:50.195", + "created": "2021-06-16T14:26:50.195", + "type": "PIVOT_TABLE", + "hideTitle": false, + "hideSubtitle": false, + "hideEmptyColumns": false, + "hideEmptyRows": false, + "hideEmptyRowItems": "NONE", + "hideLegend": false, + "showHierarchy": false, + "rowTotals": true, + "rowSubTotals": false, + "colTotals": false, + "colSubTotals": false, + "showDimensionLabels": false, + "percentStackedValues": false, + "noSpaceBetweenColumns": false, + "skipRounding": false, + "displayDensity": "NORMAL", + "digitGroupSeparator": "COMMA", + "relativePeriods": { + "thisYear": false, + "last12Months": true + }, + "categoryDimensions": [ + { + "category": { + "id": "fMZEcRHuamy" + }, + "categoryOptions": [ + { + "id": "qkPbeWaFsnU" + }, + { + "id": "wbrDrL2aYEc" + } + ] + } + ], + "filterDimensions": [ + "ou" + ], + "rowDimensions": [ + "pe" + ], + "columnDimensions": [ + "dx", + "fMZEcRHuamy", + "fkAkrdC7eJF" + ], + "dataDimensionItems": [ + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "Uvn6LCg7dVU" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "cYeuwXTCPkU" + } + } + ], + "organisationUnitLevels": [ + 3 + ], + "userOrganisationUnit": false, + "userOrganisationUnitChildren": false, + "userOrganisationUnitGrandChildren": false, + "organisationUnits": [ + { + "id": "YuQRtpLP10I" + }, + { + "id": "vWbkYPRmKyS" + } + ], + "periods": [ + { + "id": "202102" + }, + { + "id": "202103" + }, + { + "id": "2021S2" + } + ] +} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java index 62e174e423..59a5f4f3fe 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/VisualizationShould.java @@ -41,13 +41,14 @@ public class VisualizationShould extends BaseObjectShould implements ObjectShould { public VisualizationShould() { - super("visualization/visualization.json"); + super("visualization/visualization_simplified.json"); } @Override @Test public void map_from_json_string() throws IOException, ParseException { - Visualization jsonVisualization = objectMapper.readValue(jsonStream, Visualization.class); + Visualization jsonVisualization = objectMapper.readValue(jsonStream, Visualization.class) + .toBuilder().id(null).build(); Visualization expectedVisualization = VisualizationSamples.INSTANCE.visualization() .toBuilder().id(null).build(); assertThat(jsonVisualization).isEqualTo(expectedVisualization); From ba8147787bf316ff3628ef1452fea1268e3ae68d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 7 Jul 2021 12:11:03 +0200 Subject: [PATCH 133/308] [androsdk-1383] Add VisualizationCategoryDimensionLink --- .../VisualizationStoreIntegrationShould.kt | 1 - .../VisualizationCategoryDimensionLink.java | 74 +++++++++++++++++++ ...alizationCategoryDimensionLinkTableInfo.kt | 62 ++++++++++++++++ ...lizationCategoryDimensionEntityDIModule.kt | 55 ++++++++++++++ ...VisualizationCategoryDimensionLinkStore.kt | 53 +++++++++++++ .../{ => internal}/VisualizationHandler.kt | 26 ++++++- .../{ => internal}/VisualizationStore.kt | 4 +- 7 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLink.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionEntityDIModule.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt rename core/src/main/java/org/hisp/dhis/android/core/visualization/{ => internal}/VisualizationHandler.kt (64%) rename core/src/main/java/org/hisp/dhis/android/core/visualization/{ => internal}/VisualizationStore.kt (96%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt index 516995593e..ba69683f9f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStoreIntegrationShould.kt @@ -33,7 +33,6 @@ import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFact import org.hisp.dhis.android.core.utils.runner.D2JunitRunner import org.hisp.dhis.android.core.visualization.HideEmptyItemStrategy import org.hisp.dhis.android.core.visualization.Visualization -import org.hisp.dhis.android.core.visualization.VisualizationStore import org.hisp.dhis.android.core.visualization.VisualizationTableInfo import org.junit.runner.RunWith diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLink.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLink.java new file mode 100644 index 0000000000..6761aad2dd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLink.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import android.database.Cursor; + +import androidx.annotation.NonNull; + +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.BaseObject; +import org.hisp.dhis.android.core.common.CoreObject; + +@AutoValue +public abstract class VisualizationCategoryDimensionLink implements CoreObject { + + @NonNull + public abstract String visualization(); + + @NonNull + public abstract String category(); + + @NonNull + public abstract String categoryOption(); + + public static Builder builder() { + return new $$AutoValue_VisualizationCategoryDimensionLink.Builder(); + } + + public abstract Builder toBuilder(); + + public static VisualizationCategoryDimensionLink create(Cursor cursor) { + return $AutoValue_VisualizationCategoryDimensionLink.createFromCursor(cursor); + } + + @AutoValue.Builder + public static abstract class Builder extends BaseObject.Builder { + public abstract Builder id(Long id); + + public abstract Builder visualization(String visualization); + + public abstract Builder category(String category); + + public abstract Builder categoryOption(String categoryOption); + + public abstract VisualizationCategoryDimensionLink build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt new file mode 100644 index 0000000000..a392d53e6c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns + +object VisualizationCategoryDimensionLinkTableInfo { + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "VisualizationCategoryDimensionLink" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : CoreColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + VISUALIZATION, + CATEGORY, + CATEGORY_OPTION + ) + } + + companion object { + const val VISUALIZATION = "visualization" + const val CATEGORY = "category" + const val CATEGORY_OPTION = "categoryOption" + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionEntityDIModule.kt new file mode 100644 index 0000000000..c96544b9f6 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionEntityDIModule.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore +import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler +import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandlerImpl +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink + +@Module +internal class VisualizationCategoryDimensionEntityDIModule { + + @Provides + @Reusable + fun store(databaseAdapter: DatabaseAdapter): LinkStore { + return VisualizationCategoryDimensionLinkStore.create(databaseAdapter) + } + + @Provides + @Reusable + fun handler(store: LinkStore): + LinkHandler { + return LinkHandlerImpl(store) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt new file mode 100644 index 0000000000..2eca2cd075 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +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.internal.LinkStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo + +internal object VisualizationCategoryDimensionLinkStore { + private val BINDER = StatementBinder { o: VisualizationCategoryDimensionLink, w: StatementWrapper -> + w.bind(1, o.visualization()) + w.bind(2, o.category()) + w.bind(3, o.categoryOption()) + } + + fun create(databaseAdapter: DatabaseAdapter): LinkStore { + return StoreFactory.linkStore( + databaseAdapter, + VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO, + VisualizationCategoryDimensionLinkTableInfo.Columns.CATEGORY_OPTION, + BINDER + ) { VisualizationCategoryDimensionLink.create(it) } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt similarity index 64% rename from core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt rename to core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index e58630587e..a4ba551f01 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -25,17 +25,24 @@ * (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.visualization +package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler import org.hisp.dhis.android.core.arch.handlers.internal.ObjectWithoutUidHandlerImpl +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.visualization.CategoryDimension +import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink import javax.inject.Inject @Reusable internal class VisualizationHandler @Inject constructor( - store: ObjectWithoutUidStore + store: ObjectWithoutUidStore, + private val visualizationCategoryDimensionLinkHandler: + LinkHandler ) : ObjectWithoutUidHandlerImpl(store) { override fun beforeCollectionHandled( @@ -46,5 +53,18 @@ internal class VisualizationHandler @Inject constructor( } override fun afterObjectHandled(o: Visualization, action: HandleAction) { + o.categoryDimensions()?.forEach { categoryDimension: CategoryDimension -> + categoryDimension.category()?.let { + visualizationCategoryDimensionLinkHandler.handleMany( + it.uid(), categoryDimension.categoryOptions() + ) { categoryOption: ObjectWithUid -> + VisualizationCategoryDimensionLink.builder() + .visualization(o.uid()) + .categoryOption(categoryDimension.category()?.uid()) + .categoryOption(categoryOption.uid()) + .build() + } + } + } } -} +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStore.kt similarity index 96% rename from core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt rename to core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStore.kt index 639ec5d462..87a4e63946 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationStore.kt @@ -25,7 +25,7 @@ * (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.visualization +package org.hisp.dhis.android.core.visualization.internal import android.database.Cursor import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter @@ -37,6 +37,8 @@ import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableSt import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory +import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationTableInfo @Suppress("MagicNumber") internal object VisualizationStore { From c5382313da9ae9cd1940104070e9270f07a0e3a7 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 7 Jul 2021 12:45:33 +0200 Subject: [PATCH 134/308] [androsdk-1383] Add VisualizationCategoryDimensionLink migration and table --- core/src/main/assets/migrations/104.sql | 3 ++- core/src/main/assets/snapshots/104.sql | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/assets/migrations/104.sql b/core/src/main/assets/migrations/104.sql index d09922de4e..b2c713d697 100644 --- a/core/src/main/assets/migrations/104.sql +++ b/core/src/main/assets/migrations/104.sql @@ -1 +1,2 @@ -CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); \ No newline at end of file +CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/104.sql b/core/src/main/assets/snapshots/104.sql index 39bf464de0..ad194953ae 100644 --- a/core/src/main/assets/snapshots/104.sql +++ b/core/src/main/assets/snapshots/104.sql @@ -112,3 +112,4 @@ CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, p CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); From f71ecea2c885175acbf7daeac2810c792dec7455 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 7 Jul 2021 12:46:47 +0200 Subject: [PATCH 135/308] [androsdk-1383] Add VisualizationCategoryDimensionLink table info, store and test --- .../LinkStoreAbstractIntegrationShould.java | 2 +- ...goryDimensionLinkStoreIntegrationShould.kt | 58 +++++++++++++++++++ ...alizationCategoryDimensionLinkTableInfo.kt | 9 +++ ...VisualizationCategoryDimensionLinkStore.kt | 2 +- ...sualizationCategoryDimensionLinkSamples.kt | 41 +++++++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/LinkStoreAbstractIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/LinkStoreAbstractIntegrationShould.java index 32716b4db6..d9b616b5d3 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/LinkStoreAbstractIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/LinkStoreAbstractIntegrationShould.java @@ -73,8 +73,8 @@ public void delete_link_for_master_uid() { @Test public void delete_links_for_master_should_delete_only_objects_with_the_master_key() { - store.insert(objectWithOtherMasterUid); store.insert(object); + store.insert(objectWithOtherMasterUid); store.deleteLinksForMasterUid(masterUid); M objectFromDb = store.selectFirst(); assertEqualsIgnoreId(objectFromDb, objectWithOtherMasterUid); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt new file mode 100644 index 0000000000..274795fb16 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.data.database.LinkStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.data.visualization.VisualizationCategoryDimensionLinkSamples +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class VisualizationCategoryDimensionLinkStoreIntegrationShould : + LinkStoreAbstractIntegrationShould( + VisualizationCategoryDimensionLinkStore.create(TestDatabaseAdapterFactory.get()), + VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() +) { + override fun addMasterUid(): String { + return VisualizationCategoryDimensionLinkSamples.visualizationCategoryDimensionLinkSamples().visualization() + } + + override fun buildObject(): VisualizationCategoryDimensionLink { + return VisualizationCategoryDimensionLinkSamples.visualizationCategoryDimensionLinkSamples() + } + + override fun buildObjectWithOtherMasterUid(): VisualizationCategoryDimensionLink { + return VisualizationCategoryDimensionLinkSamples.visualizationCategoryDimensionLinkSamples().toBuilder() + .visualization("visualization_uid_2") + .build() + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt index a392d53e6c..9f94a3d8c1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt @@ -53,6 +53,15 @@ object VisualizationCategoryDimensionLinkTableInfo { ) } + override fun whereUpdate(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + VISUALIZATION, + CATEGORY, + CATEGORY_OPTION + ) + } + companion object { const val VISUALIZATION = "visualization" const val CATEGORY = "category" diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt index 2eca2cd075..3e678f89da 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt @@ -46,7 +46,7 @@ internal object VisualizationCategoryDimensionLinkStore { return StoreFactory.linkStore( databaseAdapter, VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO, - VisualizationCategoryDimensionLinkTableInfo.Columns.CATEGORY_OPTION, + VisualizationCategoryDimensionLinkTableInfo.Columns.VISUALIZATION, BINDER ) { VisualizationCategoryDimensionLink.create(it) } } diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt new file mode 100644 index 0000000000..7a8c04f3f3 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.visualization + +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink + +object VisualizationCategoryDimensionLinkSamples { + + fun visualizationCategoryDimensionLinkSamples(): VisualizationCategoryDimensionLink = + VisualizationCategoryDimensionLink.builder() + .id(1L) + .visualization("visualization_uid") + .category("category_uid") + .categoryOption("category_option_uid") + .build() +} From fb4289f173f52494eaece3f2bfe88ef0f9adb81d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 7 Jul 2021 13:38:03 +0200 Subject: [PATCH 136/308] [androsdk-1383] Add VisualizationEntityDIModule and VisualizationFields --- .../internal/VisualizationEntityDIModule.kt | 62 ++++++++++++++ .../internal/VisualizationFields.kt | 80 +++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt new file mode 100644 index 0000000000..21068f44ce --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.di.internal.IdentifiableStoreProvider +import org.hisp.dhis.android.core.arch.handlers.internal.Handler +import org.hisp.dhis.android.core.visualization.Visualization + +@Module +internal class VisualizationEntityDIModule : IdentifiableStoreProvider { + + @Provides + @Reusable + override fun store(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return VisualizationStore.create(databaseAdapter) + } + + @Provides + @Reusable + fun handler(impl: VisualizationHandler): Handler { + return impl + } + +/* @Provides + @Reusable + fun childrenAppenders(databaseAdapter: DatabaseAdapter): Map> { + return Collections.singletonMap( + VisualizationFields.CATEGORY_DIMENSIONS, + VisualizationCategoryDimensionChildrenAppender.create(databaseAdapter) + ) + }*/ +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt new file mode 100644 index 0000000000..114083a50e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004-2021, 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), + fh.field(* 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.api.fields.internal.Fields +import org.hisp.dhis.android.core.arch.fields.internal.FieldsHelper +import org.hisp.dhis.android.core.visualization.* + +internal object VisualizationFields { + internal const val CATEGORY_DIMENSIONS = "categoryDimensions" + internal const val DATA_DIMENSION_ITEMS = "dataDimensionItems" + private val fh = FieldsHelper() + val uid = fh.uid() + + fun allFields(): Fields { + return Fields.builder() + .fields(fh.getIdentifiableFields()) + .fields( + fh.field(VisualizationTableInfo.Columns.DESCRIPTION), + fh.field(VisualizationTableInfo.Columns.DISPLAY_DESCRIPTION), + fh.field(VisualizationTableInfo.Columns.DISPLAY_FORM_NAME), + fh.field(VisualizationTableInfo.Columns.TYPE), + fh.field(VisualizationTableInfo.Columns.HIDE_TITLE), + fh.field(VisualizationTableInfo.Columns.HIDE_SUBTITLE), + fh.field(VisualizationTableInfo.Columns.HIDE_EMPTY_COLUMNS), + fh.field(VisualizationTableInfo.Columns.HIDE_EMPTY_ROWS), + fh.field(VisualizationTableInfo.Columns.HIDE_EMPTY_ROW_ITEMS), + fh.field(VisualizationTableInfo.Columns.HIDE_LEGEND), + fh.field(VisualizationTableInfo.Columns.SHOW_HIERARCHY), + fh.field(VisualizationTableInfo.Columns.ROW_TOTALS), + fh.field(VisualizationTableInfo.Columns.ROW_SUB_TOTALS), + fh.field(VisualizationTableInfo.Columns.COL_TOTALS), + fh.field(VisualizationTableInfo.Columns.COL_SUB_TOTALS), + fh.field(VisualizationTableInfo.Columns.SHOW_DIMENSION_LABELS), + fh.field(VisualizationTableInfo.Columns.PERCENT_STACKED_VALUES), + fh.field(VisualizationTableInfo.Columns.NO_SPACE_BETWEEN_COLUMNS), + fh.field(VisualizationTableInfo.Columns.SKIP_ROUNDING), + fh.field(VisualizationTableInfo.Columns.DISPLAY_DENSITY), + fh.field(VisualizationTableInfo.Columns.DIGIT_GROUP_SEPARATOR), + fh.field(VisualizationTableInfo.Columns.RELATIVE_PERIODS), + // fh.nestedField(CATEGORY_DIMENSIONS).with(CategoryDimensionFields.allFields), + fh.nestedField(VisualizationTableInfo.Columns.FILTER_DIMENSIONS), + fh.nestedField(VisualizationTableInfo.Columns.ROW_DIMENSIONS), + fh.nestedField(VisualizationTableInfo.Columns.COLUMN_DIMENSIONS), + // fh.nestedField(DATA_DIMENSION_ITEMS).with(DataDimensionItemsFields.allFields), + fh.nestedField(VisualizationTableInfo.Columns.ORGANISATION_UNIT_LEVELS), + fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT), + fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT_CHILDREN), + fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT_GRAND_CHILDREN), + fh.nestedFieldWithUid(VisualizationTableInfo.Columns.ORGANISATION_UNITS), + fh.nestedFieldWithUid(VisualizationTableInfo.Columns.PERIODS) + ) + .build() + } +} From 6b72a4207009bb6b6f01959ef527929ebd447193 Mon Sep 17 00:00:00 2001 From: andresmr Date: Mon, 5 Jul 2021 09:21:10 +0200 Subject: [PATCH 137/308] feat: [ANDROSDK-1384_MODELS] [ANDROSDK-1384] Analytics settings models --- .../settings/AnalyticsDhisVisualization.java | 94 +++++++++++++++++++ .../AnalyticsDhisVisualizationsGroup.java | 65 +++++++++++++ .../AnalyticsDhisVisualizationsSetting.java | 66 +++++++++++++ .../core/settings/AnalyticsSettings.java | 5 + 4 files changed, 230 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsGroup.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSetting.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java new file mode 100644 index 0000000000..21b8937bec --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.common.ObjectWithUidInterface; + +@AutoValue +@JsonDeserialize(builder = AutoValue_AnalyticsDhisVisualization.Builder.class) +public abstract class AnalyticsDhisVisualization implements CoreObject, ObjectWithUidInterface { + + @Nullable + public abstract String scopeUid(); + + @Nullable + public abstract String idGroup(); + + @Nullable + public abstract String name(); + + @Nullable + public abstract String scope(); + + @Nullable + public abstract String uid(); + + @Nullable + public abstract String timeStamp(); + + public static AnalyticsDhisVisualization create(Cursor cursor) { + return AutoValue_AnalyticsDhisVisualization.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + public static Builder builder() { + return new AutoValue_AnalyticsDhisVisualization.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public abstract static class Builder { + + public abstract Builder id(Long id); + + public abstract Builder scopeUid(String scopeUid); + + public abstract Builder idGroup(String idGroup); + + public abstract Builder name(String name); + + public abstract Builder scope(String scope); + + public abstract Builder uid(String uid); + + public abstract Builder timeStamp(String timeStamp); + + public abstract AnalyticsDhisVisualization build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsGroup.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsGroup.java new file mode 100644 index 0000000000..2bf1bd7328 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsGroup.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +@JsonDeserialize(builder = AutoValue_AnalyticsDhisVisualizationsGroup.Builder.class) +public abstract class AnalyticsDhisVisualizationsGroup { + + public abstract String name(); + + public abstract String id(); + + public abstract List visualizations(); + + public abstract Builder toBuilder(); + + public static Builder builder() { + return new AutoValue_AnalyticsDhisVisualizationsGroup.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public abstract static class Builder { + + public abstract Builder name(String name); + + public abstract Builder id(String id); + + public abstract Builder visualizations(List visualizations); + + public abstract AnalyticsDhisVisualizationsGroup build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSetting.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSetting.java new file mode 100644 index 0000000000..c9fd41071e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSetting.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import java.util.List; +import java.util.Map; + +@AutoValue +@JsonDeserialize(builder = AutoValue_AnalyticsDhisVisualizationsSetting.Builder.class) +public abstract class AnalyticsDhisVisualizationsSetting { + + public abstract List home(); + + public abstract Map> program(); + + public abstract Map> dataSet(); + + public abstract Builder toBuilder(); + + public static Builder builder() { + return new AutoValue_AnalyticsDhisVisualizationsSetting.Builder(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public abstract static class Builder { + + public abstract Builder home(List home); + + public abstract Builder program(Map> program); + + public abstract Builder dataSet(Map> dataSet); + + public abstract AnalyticsDhisVisualizationsSetting build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java index 34ffae3019..b15b9c0844 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java @@ -40,6 +40,8 @@ public abstract class AnalyticsSettings { public abstract List tei(); + public abstract AnalyticsDhisVisualizationsSetting dhisVisualizations(); + public static Builder builder() { return new AutoValue_AnalyticsSettings.Builder(); } @@ -47,8 +49,11 @@ public static Builder builder() { @AutoValue.Builder @JsonPOJOBuilder(withPrefix = "") public abstract static class Builder { + public abstract Builder tei(List tei); + public abstract Builder dhisVisualizations(AnalyticsDhisVisualizationsSetting dhisVisualizations); + public abstract AnalyticsSettings build(); } } \ No newline at end of file From 70137994f6733ca739b5c60ef34fea5f413bbff6 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 7 Jul 2021 12:29:59 +0200 Subject: [PATCH 138/308] [ANDROSDK-1384_MODELS] Return empty object for AnalyticsDhis2Visualizations --- .../settings/AnalyticsDhisVisualization.java | 8 +++---- .../core/settings/AnalyticsSettings.java | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java index 21b8937bec..d5d95e1b5c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java @@ -47,10 +47,10 @@ public abstract class AnalyticsDhisVisualization implements CoreObject, ObjectWi public abstract String scopeUid(); @Nullable - public abstract String idGroup(); + public abstract String groupUid(); @Nullable - public abstract String name(); + public abstract String groupName(); @Nullable public abstract String scope(); @@ -79,9 +79,9 @@ public abstract static class Builder { public abstract Builder scopeUid(String scopeUid); - public abstract Builder idGroup(String idGroup); + public abstract Builder groupUid(String groupUid); - public abstract Builder name(String name); + public abstract Builder groupName(String groupName); public abstract Builder scope(String scope); diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java index b15b9c0844..394e9dfe3a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java @@ -28,10 +28,13 @@ package org.hisp.dhis.android.core.settings; +import androidx.annotation.Nullable; + import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.google.auto.value.AutoValue; +import java.util.Collections; import java.util.List; @AutoValue @@ -40,6 +43,7 @@ public abstract class AnalyticsSettings { public abstract List tei(); + @Nullable public abstract AnalyticsDhisVisualizationsSetting dhisVisualizations(); public static Builder builder() { @@ -54,6 +58,21 @@ public abstract static class Builder { public abstract Builder dhisVisualizations(AnalyticsDhisVisualizationsSetting dhisVisualizations); - public abstract AnalyticsSettings build(); + public abstract AnalyticsSettings autoBuild(); + + //Auxiliary fields + abstract AnalyticsDhisVisualizationsSetting dhisVisualizations(); + + public AnalyticsSettings build() { + if (dhisVisualizations() == null) { + dhisVisualizations(AnalyticsDhisVisualizationsSetting.builder() + .home(Collections.emptyList()) + .program(Collections.emptyMap()) + .dataSet(Collections.emptyMap()) + .build()); + } + + return autoBuild(); + } } } \ No newline at end of file From 109183996e0e696464dcdaca006895036b1db6d5 Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 7 Jul 2021 14:20:39 +0200 Subject: [PATCH 139/308] [ANDROSDK-1384_MODELS] AnalyticsDhisVisualizationScope --- ...csDhisVisualizationScopeColumnAdapter.java | 38 +++++++++++++++++++ .../settings/AnalyticsDhisVisualization.java | 7 +++- .../AnalyticsDhisVisualizationScope.kt | 35 +++++++++++++++++ .../core/settings/AnalyticsSettings.java | 7 ++-- 4 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/AnalyticsDhisVisualizationScopeColumnAdapter.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/AnalyticsDhisVisualizationScopeColumnAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/AnalyticsDhisVisualizationScopeColumnAdapter.java new file mode 100644 index 0000000000..d341797b1a --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/AnalyticsDhisVisualizationScopeColumnAdapter.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal; + +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationScope; + +public class AnalyticsDhisVisualizationScopeColumnAdapter extends EnumColumnAdapter { + @Override + protected Class getEnumClass() { + return AnalyticsDhisVisualizationScope.class; + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java index d5d95e1b5c..cf555b457f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java @@ -34,8 +34,10 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.AnalyticsDhisVisualizationScopeColumnAdapter; import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; @@ -53,7 +55,8 @@ public abstract class AnalyticsDhisVisualization implements CoreObject, ObjectWi public abstract String groupName(); @Nullable - public abstract String scope(); + @ColumnAdapter(AnalyticsDhisVisualizationScopeColumnAdapter.class) + public abstract AnalyticsDhisVisualizationScope scope(); @Nullable public abstract String uid(); @@ -83,7 +86,7 @@ public abstract static class Builder { public abstract Builder groupName(String groupName); - public abstract Builder scope(String scope); + public abstract Builder scope(AnalyticsDhisVisualizationScope scope); public abstract Builder uid(String uid); diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt new file mode 100644 index 0000000000..43e455fa41 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings + +enum class AnalyticsDhisVisualizationScope { + HOME, + PROGRAM, + DATA_SET +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java index 394e9dfe3a..fae283baba 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettings.java @@ -28,8 +28,6 @@ package org.hisp.dhis.android.core.settings; -import androidx.annotation.Nullable; - import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.google.auto.value.AutoValue; @@ -43,7 +41,6 @@ public abstract class AnalyticsSettings { public abstract List tei(); - @Nullable public abstract AnalyticsDhisVisualizationsSetting dhisVisualizations(); public static Builder builder() { @@ -64,7 +61,9 @@ public abstract static class Builder { abstract AnalyticsDhisVisualizationsSetting dhisVisualizations(); public AnalyticsSettings build() { - if (dhisVisualizations() == null) { + try { + dhisVisualizations(); + } catch (IllegalStateException e) { dhisVisualizations(AnalyticsDhisVisualizationsSetting.builder() .home(Collections.emptyList()) .program(Collections.emptyMap()) From e83fd221c01e986301fab37b8b4ccce673bda4da Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 8 Jul 2021 14:00:19 +0200 Subject: [PATCH 140/308] [ANDROSDK-1387] Implement DataElement evaluator --- .../DataElementEvaluatorIntegrationShould.kt | 167 ++++++++++++++++++ .../evaluator/DataElementEvaluatorSamples.kt | 111 ++++++++++++ .../aggregated/service/AnalyticsService.kt | 13 +- .../AnalyticsServiceEvaluatorHelper.kt | 63 +++++++ .../service/evaluator/AnalyticsEvaluator.kt | 39 ++++ .../evaluator/AnalyticsEvaluatorHelper.kt | 60 +++++++ .../service/evaluator/DataElementEvaluator.kt | 114 ++++++++++++ .../custom/internal/DbDateColumnAdapter.java | 6 +- 8 files changed, 561 insertions(+), 12 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt new file mode 100644 index 0000000000..c280f89a3e --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.eventlinelist.aggregated.service.evaluator + +import com.google.common.truth.Truth.assertThat +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCombo +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionCombo +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodJune +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodMay +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ2 +import org.hisp.dhis.android.core.category.internal.CategoryComboStore +import org.hisp.dhis.android.core.category.internal.CategoryOptionComboStoreImpl +import org.hisp.dhis.android.core.dataelement.internal.DataElementStore +import org.hisp.dhis.android.core.datavalue.DataValue +import org.hisp.dhis.android.core.datavalue.internal.DataValueStore +import org.hisp.dhis.android.core.organisationunit.internal.OrganisationUnitStore +import org.hisp.dhis.android.core.period.internal.PeriodStoreImpl +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyDispatcher +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispatcher() { + + private val dataElementEvaluator = DataElementEvaluator(databaseAdapter) + + // Stores + private val dataValueStore = DataValueStore.create(databaseAdapter) + private val categoryComboStore = CategoryComboStore.create(databaseAdapter) + private val categoryOptionComboStore = CategoryOptionComboStoreImpl.create(databaseAdapter) + private val dataElementStore = DataElementStore.create(databaseAdapter) + private val organisationUnitStore = OrganisationUnitStore.create(databaseAdapter) + private val periodStore = PeriodStoreImpl.create(databaseAdapter) + + val metadata: Map = mapOf( + orgunitParent.uid() to MetadataItem.OrganisationUnitItem(orgunitParent), + orgunitChild1.uid() to MetadataItem.OrganisationUnitItem(orgunitChild1), + orgunitChild2.uid() to MetadataItem.OrganisationUnitItem(orgunitChild2), + dataElement.uid() to MetadataItem.DataElementItem(dataElement), + periodMay.periodId()!! to MetadataItem.PeriodItem(periodMay), + periodJune.periodId()!! to MetadataItem.PeriodItem(periodJune), + periodQ2.periodId()!! to MetadataItem.PeriodItem(periodQ2) + ) + + @Before + fun setUp() { + setUpClass() + + organisationUnitStore.insert(orgunitParent) + organisationUnitStore.insert(orgunitChild1) + organisationUnitStore.insert(orgunitChild2) + + categoryComboStore.insert(categoryCombo) + categoryOptionComboStore.insert(categoryOptionCombo) + + dataElementStore.insert(dataElement) + + periodStore.insert(periodMay) + periodStore.insert(periodJune) + periodStore.insert(periodQ2) + } + + @After + fun tearDown() { + organisationUnitStore.delete() + categoryComboStore.delete() + categoryOptionComboStore.delete() + dataElementStore.delete() + periodStore.delete() + dataValueStore.delete() + } + + @Test + fun should_aggregate_value_in_hierarchy() { + createDataValue("2", orgunitUid = orgunitParent.uid()) + createDataValue("3", orgunitUid = orgunitChild1.uid()) + createDataValue("4", orgunitUid = orgunitChild2.uid()) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement.uid()), + DimensionItem.PeriodItem.Absolute(periodJune.periodId()!!) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("9") + } + + @Test + fun should_aggregate_value_in_time() { + createDataValue("2", periodId = periodMay.periodId()!!) + createDataValue("3", periodId = periodJune.periodId()!!) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement.uid()), + DimensionItem.PeriodItem.Absolute(periodQ2.periodId()!!) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("5") + } + + private fun createDataValue( + value: String, + dataElementUid: String = dataElement.uid(), + orgunitUid: String = orgunitParent.uid(), + periodId: String = periodJune.periodId()!! + ) { + val dataValue = DataValue.builder() + .value(value) + .dataElement(dataElementUid) + .period(periodId) + .organisationUnit(orgunitUid) + .categoryOptionCombo(categoryOptionCombo.uid()) + .attributeOptionCombo(categoryOptionCombo.uid()) + .build() + + dataValueStore.insert(dataValue) + } +} diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt new file mode 100644 index 0000000000..1d9057bd8d --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.eventlinelist.aggregated.service.evaluator + +import org.hisp.dhis.android.core.arch.helpers.DateUtils +import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl +import org.hisp.dhis.android.core.category.CategoryCombo +import org.hisp.dhis.android.core.category.CategoryOptionCombo +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.common.ValueType +import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.period.Period +import org.hisp.dhis.android.core.period.PeriodType + +object DataElementEvaluatorSamples { + + val generator = UidGeneratorImpl() + + val orgunitParent: OrganisationUnit by lazy { + val uid = generator.generate() + OrganisationUnit.builder() + .uid(uid) + .displayName("Child 1") + .path("/${uid}") + .build() + } + + val orgunitChild1: OrganisationUnit by lazy { + val uid = generator.generate() + OrganisationUnit.builder() + .uid(uid) + .displayName("Child 1") + .parent(ObjectWithUid.create(orgunitParent.uid())) + .path("/${orgunitParent.uid()}/${uid}") + .build() + } + + val orgunitChild2: OrganisationUnit by lazy { + val uid = generator.generate() + OrganisationUnit.builder() + .uid(uid) + .displayName("Child 2") + .parent(ObjectWithUid.create(orgunitParent.uid())) + .path("/${orgunitParent.uid()}/${uid}") + .build() + } + + val categoryCombo: CategoryCombo = CategoryCombo.builder() + .uid(generator.generate()) + .build() + + val categoryOptionCombo: CategoryOptionCombo = CategoryOptionCombo.builder() + .uid(generator.generate()) + .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) + .build() + + val dataElement = DataElement.builder() + .uid(generator.generate()) + .displayName("Data element") + .valueType(ValueType.NUMBER) + .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) + .build() + + val periodMay: Period = Period.builder() + .periodId("202105") + .periodType(PeriodType.Monthly) + .startDate(DateUtils.DATE_FORMAT.parse("2021-05-01T00:00:00.000")) + .endDate(DateUtils.DATE_FORMAT.parse("2021-05-31T23:59:59.999")) + .build() + + val periodJune: Period = Period.builder() + .periodId("202106") + .periodType(PeriodType.Monthly) + .startDate(DateUtils.DATE_FORMAT.parse("2021-06-01T00:00:00.000")) + .endDate(DateUtils.DATE_FORMAT.parse("2021-06-30T23:59:59.999")) + .build() + + val periodQ2: Period = Period.builder() + .periodId("2021Q2") + .periodType(PeriodType.Quarterly) + .startDate(DateUtils.DATE_FORMAT.parse("2021-04-01T00:00:00.000")) + .endDate(DateUtils.DATE_FORMAT.parse("2021-06-30T23:59:59.999")) + .build() + +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt index a6514dccd3..c47c65b1c6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt @@ -31,12 +31,12 @@ package org.hisp.dhis.android.core.analytics.aggregated.service import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse -import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue import javax.inject.Inject internal class AnalyticsService @Inject constructor( private val analyticsServiceHelper: AnalyticsServiceHelper, - private val analyticsServiceMetadataHelper: AnalyticsServiceMetadataHelper + private val analyticsServiceMetadataHelper: AnalyticsServiceMetadataHelper, + private val analyticsServiceEvaluatorHelper: AnalyticsServiceEvaluatorHelper ) { fun evaluate(params: AnalyticsRepositoryParams): DimensionalResponse { @@ -53,18 +53,13 @@ internal class AnalyticsService @Inject constructor( val metadata = analyticsServiceMetadataHelper.getMetadata(evaluationItems) - val values = evaluationItems.map { evaluateItem(it) } + val values = evaluationItems.map { analyticsServiceEvaluatorHelper.evaluate(it, metadata) } - // TODO return DimensionalResponse( metadata = metadata, dimensions = dimensions, - filters = listOf(), + filters = params.filters.map { it.id }, values = values ) } - - private fun evaluateItem(evaluationItem: AnalyticsServiceEvaluationItem): DimensionalValue { - TODO() - } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt new file mode 100644 index 0000000000..e2cdbf79fa --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue +import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.AnalyticsEvaluator +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator +import javax.inject.Inject + +internal class AnalyticsServiceEvaluatorHelper @Inject constructor( + private val dataElementEvaluator: DataElementEvaluator +) { + + fun evaluate(evaluationItem: AnalyticsServiceEvaluationItem, + metadata: Map): DimensionalValue { + val dataItem = evaluationItem.dimensionItems.find { it is DimensionItem.DataItem } + + if (dataItem == null) { + TODO() + } + + val evaluator: AnalyticsEvaluator = + when (dataItem as DimensionItem.DataItem) { + is DimensionItem.DataItem.DataElementItem -> dataElementEvaluator + is DimensionItem.DataItem.DataElementOperandItem -> TODO() + is DimensionItem.DataItem.ProgramIndicatorItem -> TODO() + is DimensionItem.DataItem.IndicatorItem -> TODO() + } + + return DimensionalValue( + dimensions = evaluationItem.dimensionItems.map { (it as DimensionItem).id }, + value = evaluator.evaluate(evaluationItem, metadata) + ) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt new file mode 100644 index 0000000000..faa7b16a8e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service.evaluator + +import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem +import javax.inject.Inject + +internal interface AnalyticsEvaluator { + + fun evaluate(evaluationItem: AnalyticsServiceEvaluationItem, + metadata: Map): String? +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt new file mode 100644 index 0000000000..8a7b19e591 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service.evaluator + +import org.hisp.dhis.android.core.arch.helpers.DateUtils +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo +import org.hisp.dhis.android.core.period.Period +import org.hisp.dhis.android.core.period.PeriodTableInfo + +internal object AnalyticsEvaluatorHelper { + + fun getPeriodsClause(period: Period): String { + return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + + "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + + "WHERE " + + "${PeriodTableInfo.Columns.START_DATE} >= '${DateUtils.DATE_FORMAT.format(period.startDate()!!)}' " + + "AND " + + "${PeriodTableInfo.Columns.END_DATE} <= '${DateUtils.DATE_FORMAT.format(period.endDate()!!)}'" + } + + fun getOrgunitClause(orgunitUid: String): String { + return "SELECT ${OrganisationUnitTableInfo.Columns.UID} " + + "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + + "WHERE " + + "${OrganisationUnitTableInfo.Columns.PATH} LIKE '%$orgunitUid%'" + } + + fun getLevelOrgunitClause(level: Int): String { + return "SELECT ${OrganisationUnitTableInfo.Columns.UID} " + + "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + + "WHERE " + + "${OrganisationUnitTableInfo.Columns.LEVEL} = $level" + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt new file mode 100644 index 0000000000..a2b93005df --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service.evaluator + +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.datavalue.DataValueTableInfo +import javax.inject.Inject + +internal class DataElementEvaluator @Inject constructor( + private val databaseAdapter: DatabaseAdapter +) : AnalyticsEvaluator { + + override fun evaluate( + evaluationItem: AnalyticsServiceEvaluationItem, + metadata: Map + ): String? { + val items = (evaluationItem.dimensionItems + evaluationItem.filters).map { it as DimensionItem } + + val whereClause = + items.foldRight(WhereClauseBuilder()) { item, builder -> + appendWhereClause(item, builder, metadata) + } + .appendKeyNumberValue(DataValueTableInfo.Columns.DELETED, 0) + .build() + + val sqlQuery = + "SELECT SUM(${DataValueTableInfo.Columns.VALUE}) " + + "FROM ${DataValueTableInfo.TABLE_INFO.name()} " + + "WHERE $whereClause" + + return databaseAdapter.rawQuery(sqlQuery)?.use { c -> + c.moveToFirst() + c.getString(0) + } + } + + private fun appendWhereClause( + item: DimensionItem, + builder: WhereClauseBuilder, + metadata: Map + ): WhereClauseBuilder { + return when (item) { + is DimensionItem.DataItem -> + when (item) { + is DimensionItem.DataItem.DataElementItem -> + builder.appendKeyStringValue(DataValueTableInfo.Columns.DATA_ELEMENT, item.uid) + else -> TODO() + + } + + is DimensionItem.PeriodItem -> + when (item) { + is DimensionItem.PeriodItem.Absolute -> { + val periodItem = metadata[item.periodId] as MetadataItem.PeriodItem + builder.appendInSubQuery( + DataValueTableInfo.Columns.PERIOD, + AnalyticsEvaluatorHelper.getPeriodsClause(periodItem.item) + ) + } + is DimensionItem.PeriodItem.Relative -> TODO() + } + + is DimensionItem.OrganisationUnitItem -> + when (item) { + is DimensionItem.OrganisationUnitItem.Absolute -> + builder.appendInSubQuery( + DataValueTableInfo.Columns.ORGANISATION_UNIT, + AnalyticsEvaluatorHelper.getOrgunitClause(item.uid) + ) + is DimensionItem.OrganisationUnitItem.Level -> + builder.appendInSubQuery( + DataValueTableInfo.Columns.ORGANISATION_UNIT, + AnalyticsEvaluatorHelper.getLevelOrgunitClause(item.level) + ) + is DimensionItem.OrganisationUnitItem.Relative -> TODO() + is DimensionItem.OrganisationUnitItem.Group -> TODO() + } + + is DimensionItem.CategoryItem -> TODO() + + is DimensionItem.CategoryOptionGroupSetItem -> TODO() + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/DbDateColumnAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/DbDateColumnAdapter.java index 4201fe8115..9aae781cfc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/DbDateColumnAdapter.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/DbDateColumnAdapter.java @@ -33,7 +33,7 @@ import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter; -import org.hisp.dhis.android.core.common.BaseIdentifiableObject; +import org.hisp.dhis.android.core.arch.helpers.DateUtils; import java.text.ParseException; import java.util.Date; @@ -49,7 +49,7 @@ public Date fromCursor(Cursor cursor, String columnName) { Date date = null; if (sourceDate != null) { try { - date = BaseIdentifiableObject.DATE_FORMAT.parse(sourceDate); + date = DateUtils.DATE_FORMAT.parse(sourceDate); } catch (ParseException parseException) { // wrap checked exception into unchecked throw new RuntimeException(parseException); @@ -62,7 +62,7 @@ public Date fromCursor(Cursor cursor, String columnName) { @Override public void toContentValues(ContentValues contentValues, String columnName, Date date) { if (date != null) { - contentValues.put(columnName, BaseIdentifiableObject.DATE_FORMAT.format(date)); + contentValues.put(columnName, DateUtils.DATE_FORMAT.format(date)); } } } From 126a0c367f9b9002f39f31e2b67a8dfa4e6ce029 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Jul 2021 14:42:02 +0200 Subject: [PATCH 141/308] [androsdk-1383] Add VisualizationCategoryDimension children appender --- ...zationCategoryDimensionChildrenAppender.kt | 71 +++++++++++++++++++ .../internal/VisualizationEntityDIModule.kt | 6 +- 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionChildrenAppender.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionChildrenAppender.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionChildrenAppender.kt new file mode 100644 index 0000000000..8d7d267494 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionChildrenAppender.kt @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.visualization.CategoryDimension +import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo + +internal class VisualizationCategoryDimensionChildrenAppender +private constructor(private val childStore: LinkStore) : + ChildrenAppender() { + + override fun appendChildren(visualization: Visualization): Visualization { + val builder = visualization.toBuilder() + builder.categoryDimensions(getChildren(visualization)) + return builder.build() + } + + private fun getChildren(o: Visualization): List { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(VisualizationCategoryDimensionLinkTableInfo.Columns.VISUALIZATION, o.uid()) + .build() + return this.childStore.selectWhere(whereClause) + .groupBy { it.category() } + .map { + CategoryDimension.builder() + .category(ObjectWithUid.create(it.key)) + .categoryOptions(it.value.map { ObjectWithUid.create(it.categoryOption()) }) + .build() + } + } + + companion object { + fun create(databaseAdapter: DatabaseAdapter): ChildrenAppender { + return VisualizationCategoryDimensionChildrenAppender( + VisualizationCategoryDimensionLinkStore.create(databaseAdapter) + ) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt index 21068f44ce..944a2963a3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt @@ -34,7 +34,9 @@ import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.di.internal.IdentifiableStoreProvider import org.hisp.dhis.android.core.arch.handlers.internal.Handler +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender import org.hisp.dhis.android.core.visualization.Visualization +import java.util.* @Module internal class VisualizationEntityDIModule : IdentifiableStoreProvider { @@ -51,12 +53,12 @@ internal class VisualizationEntityDIModule : IdentifiableStoreProvider> { return Collections.singletonMap( VisualizationFields.CATEGORY_DIMENSIONS, VisualizationCategoryDimensionChildrenAppender.create(databaseAdapter) ) - }*/ + } } From 4f9b1314b0973cef7d40bae39c5bcdfe5871b809 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 8 Jul 2021 14:58:44 +0200 Subject: [PATCH 142/308] [androsdk-1383] Add VisualizationCollectionRepository --- .../VisualizationCollectionRepository.java | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java new file mode 100644 index 0000000000..620eb30f09 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization; + +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; +import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnlyIdentifiableCollectionRepositoryImpl; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.BooleanFilterConnector; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.EnumFilterConnector; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.StringFilterConnector; +import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; +import org.hisp.dhis.android.core.visualization.VisualizationTableInfo.Columns; +import org.hisp.dhis.android.core.visualization.internal.VisualizationFields; + +import java.util.Map; + +import javax.inject.Inject; + +import dagger.Reusable; + +@Reusable +public final class VisualizationCollectionRepository + extends ReadOnlyIdentifiableCollectionRepositoryImpl { + + @Inject + VisualizationCollectionRepository(final IdentifiableObjectStore store, + final Map> childrenAppenders, + final RepositoryScope scope) { + super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, + s -> new VisualizationCollectionRepository(store, childrenAppenders, s))); + } + + public StringFilterConnector byDescription() { + return cf.string(Columns.DESCRIPTION); + } + + public StringFilterConnector byDisplayDescription() { + return cf.string(Columns.DISPLAY_DESCRIPTION); + } + + public StringFilterConnector byDisplayFormName() { + return cf.string(Columns.DISPLAY_FORM_NAME); + } + + public EnumFilterConnector byType() { + return cf.enumC(Columns.TYPE); + } + + public BooleanFilterConnector byHideTitle() { + return cf.bool(Columns.HIDE_TITLE); + } + + public BooleanFilterConnector byHideSubtitle() { + return cf.bool(Columns.HIDE_SUBTITLE); + } + + public BooleanFilterConnector byHideEmptyColumns() { + return cf.bool(Columns.HIDE_EMPTY_COLUMNS); + } + + public BooleanFilterConnector byHideEmptyRows() { + return cf.bool(Columns.HIDE_EMPTY_ROWS); + } + + public EnumFilterConnector byHideEmptyRowItems() { + return cf.enumC(Columns.HIDE_EMPTY_ROW_ITEMS); + } + + public BooleanFilterConnector byHideLegend() { + return cf.bool(Columns.HIDE_LEGEND); + } + + public BooleanFilterConnector byShowHierarchy() { + return cf.bool(Columns.SHOW_HIERARCHY); + } + + public BooleanFilterConnector byRowTotals() { + return cf.bool(Columns.ROW_TOTALS); + } + + public BooleanFilterConnector byRowSubTotals() { + return cf.bool(Columns.ROW_SUB_TOTALS); + } + + public BooleanFilterConnector byColTotals() { + return cf.bool(Columns.COL_TOTALS); + } + + public BooleanFilterConnector byColSubTotals() { + return cf.bool(Columns.COL_SUB_TOTALS); + } + + public BooleanFilterConnector byShowDimensionLabels() { + return cf.bool(Columns.SHOW_DIMENSION_LABELS); + } + + public BooleanFilterConnector byPercentStackedValues() { + return cf.bool(Columns.PERCENT_STACKED_VALUES); + } + + public BooleanFilterConnector byNoSpaceBetweenColumns() { + return cf.bool(Columns.NO_SPACE_BETWEEN_COLUMNS); + } + + public BooleanFilterConnector bySkipRounding() { + return cf.bool(Columns.SKIP_ROUNDING); + } + + public EnumFilterConnector byDisplayDensity() { + return cf.enumC(Columns.DISPLAY_DENSITY); + } + + public EnumFilterConnector byDigitGroupSeparator() { + return cf.enumC(Columns.DIGIT_GROUP_SEPARATOR); + } + + public StringFilterConnector byRelativePeriods() { + return cf.string(Columns.RELATIVE_PERIODS); + } + + // CATEGORY_DIMENSIONS + + public StringFilterConnector byFilterDimensions() { + return cf.string(Columns.FILTER_DIMENSIONS); + } + + // FILTER_DIMENSIONS + + // ROW_DIMENSIONS + + // COLUMN_DIMENSIONS + + // DATA_DIMENSION_ITEMS + + // ORGANISATION_UNIT_LEVELS + + + public BooleanFilterConnector byUserOrganisationUnit() { + return cf.bool(Columns.USER_ORGANISATION_UNIT); + } + + public BooleanFilterConnector byUserOrganisationUnitChildren() { + return cf.bool(Columns.USER_ORGANISATION_UNIT_CHILDREN); + } + + public BooleanFilterConnector byUserOrganisationUnitGrandChildren() { + return cf.bool(Columns.USER_ORGANISATION_UNIT_GRAND_CHILDREN); + } + + // ORGANISATION_UNITS + + // PERIODS + + public VisualizationCollectionRepository withCategoryDimensions() { + return cf.withChild(VisualizationFields.CATEGORY_DIMENSIONS); + } +} From 49afb4a8404684f38da78e5d65280a9b0c8e129f Mon Sep 17 00:00:00 2001 From: andresmr Date: Fri, 9 Jul 2021 09:03:23 +0200 Subject: [PATCH 143/308] [ANDROSDK-1384_MODELS] refactor timestamp property and adding JSONProperty --- .../core/settings/AnalyticsDhisVisualization.java | 13 ++++++++++--- .../settings/AnalyticsDhisVisualizationScope.kt | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java index cf555b457f..9eb8236451 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualization.java @@ -30,8 +30,10 @@ import android.database.Cursor; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.gabrielittner.auto.value.cursor.ColumnAdapter; @@ -41,6 +43,8 @@ import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import static org.hisp.dhis.android.core.common.BaseIdentifiableObject.UID; + @AutoValue @JsonDeserialize(builder = AutoValue_AnalyticsDhisVisualization.Builder.class) public abstract class AnalyticsDhisVisualization implements CoreObject, ObjectWithUidInterface { @@ -58,11 +62,12 @@ public abstract class AnalyticsDhisVisualization implements CoreObject, ObjectWi @ColumnAdapter(AnalyticsDhisVisualizationScopeColumnAdapter.class) public abstract AnalyticsDhisVisualizationScope scope(); - @Nullable + @NonNull + @JsonProperty(UID) public abstract String uid(); @Nullable - public abstract String timeStamp(); + public abstract String timestamp(); public static AnalyticsDhisVisualization create(Cursor cursor) { return AutoValue_AnalyticsDhisVisualization.createFromCursor(cursor); @@ -88,9 +93,11 @@ public abstract static class Builder { public abstract Builder scope(AnalyticsDhisVisualizationScope scope); + @JsonProperty(UID) public abstract Builder uid(String uid); - public abstract Builder timeStamp(String timeStamp); + @JsonProperty("timestamp") + public abstract Builder timestamp(String timestamp); public abstract AnalyticsDhisVisualization build(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt index 43e455fa41..3cadd747ff 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationScope.kt @@ -32,4 +32,4 @@ enum class AnalyticsDhisVisualizationScope { HOME, PROGRAM, DATA_SET -} \ No newline at end of file +} From 8d7fb36489e43e35c1d8a148eca43bd4309f3377 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:25:01 +0200 Subject: [PATCH 144/308] [androsdk-1383] Update VisualizationCollectionRepository --- .../VisualizationCollectionRepository.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java index 620eb30f09..55f1f732e7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCollectionRepository.java @@ -33,6 +33,7 @@ import org.hisp.dhis.android.core.arch.repositories.filters.internal.BooleanFilterConnector; import org.hisp.dhis.android.core.arch.repositories.filters.internal.EnumFilterConnector; import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.IntegerFilterConnector; import org.hisp.dhis.android.core.arch.repositories.filters.internal.StringFilterConnector; import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; import org.hisp.dhis.android.core.visualization.VisualizationTableInfo.Columns; @@ -144,22 +145,21 @@ public StringFilterConnector byRelativePeriod return cf.string(Columns.RELATIVE_PERIODS); } - // CATEGORY_DIMENSIONS - public StringFilterConnector byFilterDimensions() { return cf.string(Columns.FILTER_DIMENSIONS); } - // FILTER_DIMENSIONS - - // ROW_DIMENSIONS - - // COLUMN_DIMENSIONS - - // DATA_DIMENSION_ITEMS + public StringFilterConnector byRowDimensions() { + return cf.string(Columns.ROW_DIMENSIONS); + } - // ORGANISATION_UNIT_LEVELS + public StringFilterConnector byColumnDimensions() { + return cf.string(Columns.COLUMN_DIMENSIONS); + } + public IntegerFilterConnector byOrganisationUnitLevels() { + return cf.integer(Columns.ORGANISATION_UNIT_LEVELS); + } public BooleanFilterConnector byUserOrganisationUnit() { return cf.bool(Columns.USER_ORGANISATION_UNIT); @@ -173,11 +173,11 @@ public BooleanFilterConnector byUserOrganisat return cf.bool(Columns.USER_ORGANISATION_UNIT_GRAND_CHILDREN); } - // ORGANISATION_UNITS - - // PERIODS - public VisualizationCollectionRepository withCategoryDimensions() { return cf.withChild(VisualizationFields.CATEGORY_DIMENSIONS); } + + public VisualizationCollectionRepository withDataDimensionItems() { + return cf.withChild(VisualizationFields.DATA_DIMENSION_ITEMS); + } } From c9343e3b076d9e920ab579465f95e54693bf72a3 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:31:43 +0200 Subject: [PATCH 145/308] [androsdk-1383] Add Visualization service and call --- .../internal/VisualizationCall.kt | 65 +++++++++++++++++++ .../internal/VisualizationFields.kt | 6 +- .../internal/VisualizationService.kt | 49 ++++++++++++++ 3 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt new file mode 100644 index 0000000000..3185c91a0f --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Reusable +import io.reactivex.Single +import org.hisp.dhis.android.core.arch.api.executors.internal.APIDownloader +import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall +import org.hisp.dhis.android.core.arch.handlers.internal.Handler +import org.hisp.dhis.android.core.common.internal.DataAccessFields +import org.hisp.dhis.android.core.visualization.Visualization +import javax.inject.Inject + +@Reusable +internal class VisualizationCall @Inject constructor( + private val handler: Handler, + private val service: VisualizationService, + private val apiDownloader: APIDownloader +) : UidsCall { + + companion object { + private const val MAX_UID_LIST_SIZE = 90 + } + + override fun download(uids: Set): Single> { + val accessDataReadFilter = "access." + DataAccessFields.read.eq(true).generateString() + return apiDownloader.downloadPartitioned( + uids, + MAX_UID_LIST_SIZE, + handler + ) { partitionUids: Set -> + service.getVisualizations( + VisualizationFields.allFields, + VisualizationFields.uid.`in`(partitionUids), + accessDataReadFilter, + paging = false + ) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt index 114083a50e..0dd348658f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt @@ -37,8 +37,8 @@ internal object VisualizationFields { private val fh = FieldsHelper() val uid = fh.uid() - fun allFields(): Fields { - return Fields.builder() + val allFields: Fields = + Fields.builder() .fields(fh.getIdentifiableFields()) .fields( fh.field(VisualizationTableInfo.Columns.DESCRIPTION), @@ -76,5 +76,5 @@ internal object VisualizationFields { fh.nestedFieldWithUid(VisualizationTableInfo.Columns.PERIODS) ) .build() - } + } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt new file mode 100644 index 0000000000..01950a565c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import io.reactivex.Single +import org.hisp.dhis.android.core.arch.api.fields.internal.Fields +import org.hisp.dhis.android.core.arch.api.filters.internal.Filter +import org.hisp.dhis.android.core.arch.api.filters.internal.Where +import org.hisp.dhis.android.core.arch.api.filters.internal.Which +import org.hisp.dhis.android.core.arch.api.payload.internal.Payload +import org.hisp.dhis.android.core.visualization.Visualization +import retrofit2.http.GET +import retrofit2.http.Query + +internal interface VisualizationService { + + @GET("visualizations") + fun getVisualizations( + @Query("fields") @Which fields: Fields, + @Query("filter") @Where uids: Filter, + @Query("filter") accessDataReadFilter: String, + @Query("paging") paging: Boolean + ): Single> +} From e09207ec790ed22ebeb97c0751e034efcff97d01 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:32:10 +0200 Subject: [PATCH 146/308] [androsdk-1383] Add visualization module --- .../java/org/hisp/dhis/android/core/D2.java | 5 ++ .../core/arch/d2/internal/D2DIComponent.java | 3 + .../arch/d2/internal/D2InternalModules.java | 4 ++ .../core/arch/d2/internal/D2Modules.java | 4 ++ .../core/visualization/VisualizationModule.kt | 32 ++++++++++ .../internal/VisualizationHandler.kt | 8 +-- .../internal/VisualizationInternalModule.kt | 39 ++++++++++++ .../internal/VisualizationModuleImpl.kt | 41 ++++++++++++ .../VisualizationPackageDIModule.java | 63 +++++++++++++++++++ 9 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationModule.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/D2.java b/core/src/main/java/org/hisp/dhis/android/core/D2.java index 7aecbb32ed..c2c04f096e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/D2.java +++ b/core/src/main/java/org/hisp/dhis/android/core/D2.java @@ -61,6 +61,7 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityModule; import org.hisp.dhis.android.core.user.UserModule; import org.hisp.dhis.android.core.validation.ValidationModule; +import org.hisp.dhis.android.core.visualization.VisualizationModule; import org.hisp.dhis.android.core.wipe.internal.WipeModule; import retrofit2.Retrofit; @@ -199,6 +200,10 @@ public ValidationModule validationModule() { return modules.validation; } + public VisualizationModule visualizationModule() { + return modules.visualization; + } + public WipeModule wipeModule() { return this.d2DIComponent.wipeModule(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java index 9bdb2fd1f3..3b72e895d2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java @@ -93,6 +93,7 @@ import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterPackageDIModule; import org.hisp.dhis.android.core.user.internal.UserPackageDIModule; import org.hisp.dhis.android.core.validation.internal.ValidationPackageDIModule; +import org.hisp.dhis.android.core.visualization.internal.VisualizationPackageDIModule; import org.hisp.dhis.android.core.wipe.internal.WipeDIModule; import org.hisp.dhis.android.core.wipe.internal.WipeModule; @@ -145,6 +146,7 @@ SmsDIModule.class, UserPackageDIModule.class, ValidationPackageDIModule.class, + VisualizationPackageDIModule.class, DataValueConflictDIModule.class} ) @@ -222,6 +224,7 @@ interface Builder { Builder trackerImporterPackageDIModule(TrackerImporterPackageDIModule trackerImporterPackageDIModule); Builder userPackageDIModule(UserPackageDIModule userPackageDIModule); Builder validationPackageDIModule(ValidationPackageDIModule validationPackageDIModule); + Builder visualizationPackageDIModule(VisualizationPackageDIModule visualizationPackageDIModule); Builder dataValueConflictDIModule(DataValueConflictDIModule dataValueConflictDIModule); D2DIComponent build(); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2InternalModules.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2InternalModules.java index 364c852736..da102afd99 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2InternalModules.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2InternalModules.java @@ -30,6 +30,7 @@ import org.hisp.dhis.android.core.category.internal.CategoryInternalModule; import org.hisp.dhis.android.core.user.internal.UserInternalModule; +import org.hisp.dhis.android.core.visualization.internal.VisualizationInternalModule; import javax.inject.Inject; @@ -38,12 +39,15 @@ @Reusable public final class D2InternalModules { public final CategoryInternalModule category; + public final VisualizationInternalModule visualization; public final UserInternalModule user; @Inject public D2InternalModules(CategoryInternalModule category, + VisualizationInternalModule visualization, UserInternalModule user) { this.category = category; + this.visualization = visualization; this.user = user; } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java index 41aea5fef5..07905fb9e6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java @@ -53,6 +53,7 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityModule; import org.hisp.dhis.android.core.user.UserModule; import org.hisp.dhis.android.core.validation.ValidationModule; +import org.hisp.dhis.android.core.visualization.VisualizationModule; import javax.inject.Inject; @@ -86,6 +87,7 @@ public final class D2Modules { public final TrackedEntityModule trackedEntity; public final UserModule user; public final ValidationModule validation; + public final VisualizationModule visualization; public final SmsModule sms; @Inject @@ -113,6 +115,7 @@ public D2Modules(AnalyticsModule analytics, TrackedEntityModule trackedEntity, UserModule user, ValidationModule validation, + VisualizationModule visualization, SmsModule sms) { this.analytics = analytics; this.category = category; @@ -138,6 +141,7 @@ public D2Modules(AnalyticsModule analytics, this.trackedEntity = trackedEntity; this.user = user; this.validation = validation; + this.visualization = visualization; this.sms = sms; } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationModule.kt new file mode 100644 index 0000000000..93c6f23ed2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationModule.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +interface VisualizationModule { + fun visualizations(): VisualizationCollectionRepository +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index a4ba551f01..7dccd7f420 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.arch.handlers.internal.IdentifiableHandlerImpl import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler -import org.hisp.dhis.android.core.arch.handlers.internal.ObjectWithoutUidHandlerImpl import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.visualization.CategoryDimension import org.hisp.dhis.android.core.visualization.Visualization @@ -40,10 +40,10 @@ import javax.inject.Inject @Reusable internal class VisualizationHandler @Inject constructor( - store: ObjectWithoutUidStore, + store: IdentifiableObjectStore, private val visualizationCategoryDimensionLinkHandler: LinkHandler -) : ObjectWithoutUidHandlerImpl(store) { +) : IdentifiableHandlerImpl(store) { override fun beforeCollectionHandled( oCollection: Collection diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt new file mode 100644 index 0000000000..2954eb7610 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import androidx.annotation.VisibleForTesting +import dagger.Reusable +import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall +import org.hisp.dhis.android.core.visualization.Visualization +import javax.inject.Inject + +@Reusable +internal class VisualizationInternalModule @Inject internal constructor( + @field:VisibleForTesting val visualizationCall: UidsCall +) \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt new file mode 100644 index 0000000000..d2dfd7c0dd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.visualization.VisualizationCollectionRepository +import org.hisp.dhis.android.core.visualization.VisualizationModule +import javax.inject.Inject + +@Reusable +internal class VisualizationModuleImpl @Inject internal constructor( + private val visualizations: VisualizationCollectionRepository +) : VisualizationModule { + + override fun visualizations(): VisualizationCollectionRepository = visualizations +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java new file mode 100644 index 0000000000..5131612584 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal; + +import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall; +import org.hisp.dhis.android.core.visualization.Visualization; +import org.hisp.dhis.android.core.visualization.VisualizationModule; + +import dagger.Module; +import dagger.Provides; +import dagger.Reusable; +import retrofit2.Retrofit; + +@Module(includes = { + VisualizationEntityDIModule.class, + VisualizationCategoryDimensionEntityDIModule.class +}) +public final class VisualizationPackageDIModule { + + @Provides + @Reusable + UidsCall visualizationCall(VisualizationCall impl) { + return impl; + } + + @Provides + @Reusable + VisualizationService visualizationService(Retrofit retrofit) { + return retrofit.create(VisualizationService.class); + } + + @Provides + @Reusable + VisualizationModule module(VisualizationModuleImpl impl) { + return impl; + } +} \ No newline at end of file From 3c78abab09abda88d713a44d3f7bc378de7b92b3 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:38:29 +0200 Subject: [PATCH 147/308] [androsdk-1383] Add visualization module wiper --- .../internal/VisualizationModuleWiper.kt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt new file mode 100644 index 0000000000..36f56790bb --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo +import org.hisp.dhis.android.core.visualization.VisualizationTableInfo +import org.hisp.dhis.android.core.wipe.internal.ModuleWiper +import org.hisp.dhis.android.core.wipe.internal.TableWiper +import javax.inject.Inject + +@Reusable +class VisualizationModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { + override fun wipeMetadata() { + tableWiper.wipeTables( + VisualizationTableInfo.TABLE_INFO, + VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO + ) + } + + override fun wipeData() { + // No data to wipe + } +} From f90090489118a50e0b0dedebd0bc082c86094015 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:57:18 +0200 Subject: [PATCH 148/308] [androsdk-1383] Fix visualization handler --- .../core/visualization/internal/VisualizationHandler.kt | 2 +- .../dhis/android/core/wipe/internal/D2ModuleWipers.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index 7dccd7f420..d7e2bcb5ca 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -60,7 +60,7 @@ internal class VisualizationHandler @Inject constructor( ) { categoryOption: ObjectWithUid -> VisualizationCategoryDimensionLink.builder() .visualization(o.uid()) - .categoryOption(categoryDimension.category()?.uid()) + .category(categoryDimension.category()?.uid()) .categoryOption(categoryOption.uid()) .build() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java b/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java index 513d9eb9cf..db2d367d91 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java +++ b/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java @@ -55,6 +55,7 @@ import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobModuleWiper; import org.hisp.dhis.android.core.user.internal.UserModuleWiper; import org.hisp.dhis.android.core.validation.internal.ValidationModuleWiper; +import org.hisp.dhis.android.core.visualization.internal.VisualizationModuleWiper; import java.util.Arrays; import java.util.List; @@ -99,7 +100,8 @@ final class D2ModuleWipers { UserModuleWiper user, TrackedEntityModuleWiper trackedEntity, AttributeModuleWiper attribute, - TrackerJobModuleWiper trackerJob) { + TrackerJobModuleWiper trackerJob, + VisualizationModuleWiper visualization) { this.wipers = Arrays.asList( category, @@ -131,6 +133,7 @@ final class D2ModuleWipers { user, trackedEntity, attribute, - trackerJob); + trackerJob, + visualization); } } \ No newline at end of file From 1014a3b19960d08d4751f59a9b25cd798a85324b Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:57:31 +0200 Subject: [PATCH 149/308] [androsdk-1383] Add visualizations.json --- .../visualization/visualizations.json | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 core/src/sharedTest/resources/visualization/visualizations.json diff --git a/core/src/sharedTest/resources/visualization/visualizations.json b/core/src/sharedTest/resources/visualization/visualizations.json new file mode 100644 index 0000000000..1286edbdb0 --- /dev/null +++ b/core/src/sharedTest/resources/visualization/visualizations.json @@ -0,0 +1,206 @@ +{ + "pager": { + "page": 1, + "pageCount": 6, + "total": 271, + "pageSize": 50, + "nextPage": "https://play.dhis2.org/2.36.3/api/visualizations.json?page=2" + }, + "visualizations": [ + { + "id": "PYBH8ZaAQnC", + "name": "Android SDK Visualization sample", + "displayName": "Android SDK Visualization sample", + "description": "Sample visualization for the Android SDK", + "displayDescription": "Sample visualization for the Android SDK", + "displayFormName": "Android SDK Visualization sample", + "lastUpdated": "2021-06-16T14:26:50.195", + "created": "2021-06-16T14:26:50.195", + "type": "PIVOT_TABLE", + "hideTitle": false, + "hideSubtitle": false, + "hideEmptyColumns": false, + "hideEmptyRows": false, + "hideEmptyRowItems": "NONE", + "hideLegend": false, + "showHierarchy": false, + "rowTotals": true, + "rowSubTotals": false, + "colTotals": false, + "colSubTotals": false, + "showDimensionLabels": false, + "percentStackedValues": false, + "noSpaceBetweenColumns": false, + "skipRounding": false, + "displayDensity": "NORMAL", + "digitGroupSeparator": "COMMA", + "relativePeriods": { + "thisYear": false, + "last12Months": true + }, + "categoryDimensions": [ + { + "category": { + "id": "fMZEcRHuamy" + }, + "categoryOptions": [ + { + "id": "qkPbeWaFsnU" + }, + { + "id": "wbrDrL2aYEc" + } + ] + } + ], + "filterDimensions": [ + "ou" + ], + "rowDimensions": [ + "pe" + ], + "columnDimensions": [ + "dx", + "fMZEcRHuamy", + "fkAkrdC7eJF" + ], + "dataDimensionItems": [ + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "Uvn6LCg7dVU" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "cYeuwXTCPkU" + } + } + ], + "organisationUnitLevels": [ + 3 + ], + "userOrganisationUnit": false, + "userOrganisationUnitChildren": false, + "userOrganisationUnitGrandChildren": false, + "organisationUnits": [ + { + "id": "YuQRtpLP10I" + }, + { + "id": "vWbkYPRmKyS" + } + ], + "periods": [ + { + "id": "202102" + }, + { + "id": "202103" + }, + { + "id": "2021S2" + } + ] + }, + { + "id": "FAFa11yFeFe", + "name": "Android SDK Visualization sample 2", + "displayName": "Android SDK Visualization sample 2", + "description": "Sample visualization for the Android SDK 2", + "displayDescription": "Sample visualization for the Android SDK 2", + "displayFormName": "Android SDK Visualization sample 2", + "lastUpdated": "2021-06-16T14:26:50.195", + "created": "2021-06-16T14:26:50.195", + "type": "PIVOT_TABLE", + "hideTitle": false, + "hideSubtitle": false, + "hideEmptyColumns": false, + "hideEmptyRows": false, + "hideEmptyRowItems": "NONE", + "hideLegend": false, + "showHierarchy": false, + "rowTotals": true, + "rowSubTotals": false, + "colTotals": false, + "colSubTotals": false, + "showDimensionLabels": false, + "percentStackedValues": false, + "noSpaceBetweenColumns": false, + "skipRounding": false, + "displayDensity": "NORMAL", + "digitGroupSeparator": "COMMA", + "relativePeriods": { + "today": true, + "last12Months": false + }, + "categoryDimensions": [ + { + "category": { + "id": "fMZEcRHuamy" + }, + "categoryOptions": [ + { + "id": "qkPbeWaFsnU" + }, + { + "id": "wbrDrL2aYEc" + } + ] + } + ], + "filterDimensions": [ + "ou" + ], + "rowDimensions": [ + "pe" + ], + "columnDimensions": [ + "dx", + "fMZEcRHuamy", + "fkAkrdC7eJF" + ], + "dataDimensionItems": [ + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "Uvn6LCg7dVU" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "cYeuwXTCPkU" + } + } + ], + "organisationUnitLevels": [ + 1, + 2 + ], + "userOrganisationUnit": false, + "userOrganisationUnitChildren": false, + "userOrganisationUnitGrandChildren": false, + "organisationUnits": [ + { + "id": "YuQRtpLP10I" + }, + { + "id": "vWbkYPRmKyS" + } + ], + "periods": [ + { + "id": "202102" + }, + { + "id": "202103" + }, + { + "id": "2021S2" + } + ] + } + ] +} \ No newline at end of file From 056f2b7f4ac9be53d5a5869093bc011eedc18abf Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 9 Jul 2021 10:57:54 +0200 Subject: [PATCH 150/308] [androsdk-1383] Add VisualizationEndpointCallShould --- .../VisualizationEndpointCallShould.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.java new file mode 100644 index 0000000000..513e9bc6d5 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal; + +import com.google.common.collect.Lists; + +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyEnqueable; +import org.hisp.dhis.android.core.visualization.Visualization; +import org.junit.Test; + +import java.util.HashSet; +import java.util.List; + +import io.reactivex.Single; + +import static com.google.common.truth.Truth.assertThat; + +public class VisualizationEndpointCallShould extends BaseMockIntegrationTestEmptyEnqueable { + + @Test + public void download_visualization_successfully() { + Single> visualizationsSingle = + objects.d2DIComponent.internalModules().visualization.getVisualizationCall().download(new HashSet<>( + Lists.newArrayList("PYBH8ZaAQnC", "FAFa11yFeFe"))); + + dhis2MockServer.enqueueMockResponse("visualization/visualizations.json"); + + d2.databaseAdapter().setForeignKeyConstraintsEnabled(false); + List visualizations = visualizationsSingle.blockingGet(); + assertThat(visualizations.isEmpty()).isFalse(); + visualizations = d2.visualizationModule().visualizations().blockingGet(); + assertThat(visualizations.isEmpty()).isFalse(); + } +} \ No newline at end of file From 9fdd0e36f4563a814d9fd5780dfad01feb4d3fd3 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 9 Jul 2021 14:49:22 +0200 Subject: [PATCH 151/308] [ANDROSDK-1387] Add relative period evaluation --- .../DataElementEvaluatorIntegrationShould.kt | 56 ++++++++--- .../evaluator/DataElementEvaluatorSamples.kt | 24 ++--- .../evaluator/AnalyticsEvaluatorHelper.kt | 15 ++- .../service/evaluator/DataElementEvaluator.kt | 95 ++++++++++++++----- .../internal/WhereClauseBuilder.java | 4 + 5 files changed, 142 insertions(+), 52 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt index c280f89a3e..431fea0faa 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -38,15 +38,18 @@ import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.eva import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodJune -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodMay -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ2 +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodDec +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodNov +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ4 import org.hisp.dhis.android.core.category.internal.CategoryComboStore import org.hisp.dhis.android.core.category.internal.CategoryOptionComboStoreImpl +import org.hisp.dhis.android.core.common.RelativePeriod import org.hisp.dhis.android.core.dataelement.internal.DataElementStore import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.internal.DataValueStore import org.hisp.dhis.android.core.organisationunit.internal.OrganisationUnitStore +import org.hisp.dhis.android.core.period.internal.CalendarProviderFactory +import org.hisp.dhis.android.core.period.internal.ParentPeriodGeneratorImpl import org.hisp.dhis.android.core.period.internal.PeriodStoreImpl import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyDispatcher import org.hisp.dhis.android.core.utils.runner.D2JunitRunner @@ -58,7 +61,9 @@ import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispatcher() { - private val dataElementEvaluator = DataElementEvaluator(databaseAdapter) + private val periodGenerator = ParentPeriodGeneratorImpl.create(CalendarProviderFactory.createFixed()) + + private val dataElementEvaluator = DataElementEvaluator(databaseAdapter, periodGenerator) // Stores private val dataValueStore = DataValueStore.create(databaseAdapter) @@ -73,9 +78,9 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat orgunitChild1.uid() to MetadataItem.OrganisationUnitItem(orgunitChild1), orgunitChild2.uid() to MetadataItem.OrganisationUnitItem(orgunitChild2), dataElement.uid() to MetadataItem.DataElementItem(dataElement), - periodMay.periodId()!! to MetadataItem.PeriodItem(periodMay), - periodJune.periodId()!! to MetadataItem.PeriodItem(periodJune), - periodQ2.periodId()!! to MetadataItem.PeriodItem(periodQ2) + periodNov.periodId()!! to MetadataItem.PeriodItem(periodNov), + periodDec.periodId()!! to MetadataItem.PeriodItem(periodDec), + periodQ4.periodId()!! to MetadataItem.PeriodItem(periodQ4) ) @Before @@ -91,9 +96,9 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat dataElementStore.insert(dataElement) - periodStore.insert(periodMay) - periodStore.insert(periodJune) - periodStore.insert(periodQ2) + periodStore.insert(periodNov) + periodStore.insert(periodDec) + periodStore.insert(periodQ4) } @After @@ -115,7 +120,7 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat val evaluationItem = AnalyticsServiceEvaluationItem( dimensionItems = listOf( DimensionItem.DataItem.DataElementItem(dataElement.uid()), - DimensionItem.PeriodItem.Absolute(periodJune.periodId()!!) + DimensionItem.PeriodItem.Absolute(periodDec.periodId()!!) ), filters = listOf( DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()) @@ -129,13 +134,13 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat @Test fun should_aggregate_value_in_time() { - createDataValue("2", periodId = periodMay.periodId()!!) - createDataValue("3", periodId = periodJune.periodId()!!) + createDataValue("2", periodId = periodNov.periodId()!!) + createDataValue("3", periodId = periodDec.periodId()!!) val evaluationItem = AnalyticsServiceEvaluationItem( dimensionItems = listOf( DimensionItem.DataItem.DataElementItem(dataElement.uid()), - DimensionItem.PeriodItem.Absolute(periodQ2.periodId()!!) + DimensionItem.PeriodItem.Absolute(periodQ4.periodId()!!) ), filters = listOf( DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()) @@ -147,11 +152,32 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat assertThat(value).isEqualTo("5") } + @Test + fun should_aggregate_relative_periods() { + createDataValue("2", periodId = periodNov.periodId()!!) + createDataValue("3", periodId = periodDec.periodId()!!) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement.uid()) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), + DimensionItem.PeriodItem.Relative(RelativePeriod.LAST_3_MONTHS), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("5") + } + private fun createDataValue( value: String, dataElementUid: String = dataElement.uid(), orgunitUid: String = orgunitParent.uid(), - periodId: String = periodJune.periodId()!! + periodId: String = periodDec.periodId()!! ) { val dataValue = DataValue.builder() .value(value) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt index 1d9057bd8d..f8d52642e8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt @@ -87,25 +87,25 @@ object DataElementEvaluatorSamples { .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) .build() - val periodMay: Period = Period.builder() - .periodId("202105") + val periodNov: Period = Period.builder() + .periodId("201911") .periodType(PeriodType.Monthly) - .startDate(DateUtils.DATE_FORMAT.parse("2021-05-01T00:00:00.000")) - .endDate(DateUtils.DATE_FORMAT.parse("2021-05-31T23:59:59.999")) + .startDate(DateUtils.DATE_FORMAT.parse("2019-11-01T00:00:00.000")) + .endDate(DateUtils.DATE_FORMAT.parse("2019-11-30T23:59:59.999")) .build() - val periodJune: Period = Period.builder() - .periodId("202106") + val periodDec: Period = Period.builder() + .periodId("201912") .periodType(PeriodType.Monthly) - .startDate(DateUtils.DATE_FORMAT.parse("2021-06-01T00:00:00.000")) - .endDate(DateUtils.DATE_FORMAT.parse("2021-06-30T23:59:59.999")) + .startDate(DateUtils.DATE_FORMAT.parse("2019-12-01T00:00:00.000")) + .endDate(DateUtils.DATE_FORMAT.parse("2019-12-31T23:59:59.999")) .build() - val periodQ2: Period = Period.builder() - .periodId("2021Q2") + val periodQ4: Period = Period.builder() + .periodId("2019Q4") .periodType(PeriodType.Quarterly) - .startDate(DateUtils.DATE_FORMAT.parse("2021-04-01T00:00:00.000")) - .endDate(DateUtils.DATE_FORMAT.parse("2021-06-30T23:59:59.999")) + .startDate(DateUtils.DATE_FORMAT.parse("2019-10-01T00:00:00.000")) + .endDate(DateUtils.DATE_FORMAT.parse("2021-12-31T23:59:59.999")) .build() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt index 8a7b19e591..62fcb11ec2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -35,11 +35,20 @@ import org.hisp.dhis.android.core.period.PeriodTableInfo internal object AnalyticsEvaluatorHelper { - fun getPeriodsClause(period: Period): String { + fun getInPeriodClause(period: Period): String { return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + - "WHERE " + - "${PeriodTableInfo.Columns.START_DATE} >= '${DateUtils.DATE_FORMAT.format(period.startDate()!!)}' " + + "WHERE ${getPeriodWhereClause(period)}" + } + + fun getInPeriodsClause(periods: List): String { + return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + + "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + + "WHERE ${periods.joinToString(" OR ") { "(${getPeriodWhereClause(it)})" }}" + } + + private fun getPeriodWhereClause(period: Period): String { + return "${PeriodTableInfo.Columns.START_DATE} >= '${DateUtils.DATE_FORMAT.format(period.startDate()!!)}' " + "AND " + "${PeriodTableInfo.Columns.END_DATE} <= '${DateUtils.DATE_FORMAT.format(period.endDate()!!)}'" } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index a2b93005df..5d288578a4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -28,27 +28,38 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator +import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.datavalue.DataValueTableInfo +import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import javax.inject.Inject internal class DataElementEvaluator @Inject constructor( - private val databaseAdapter: DatabaseAdapter + private val databaseAdapter: DatabaseAdapter, + private val parentPeriodGenerator: ParentPeriodGenerator ) : AnalyticsEvaluator { override fun evaluate( evaluationItem: AnalyticsServiceEvaluationItem, metadata: Map ): String? { - val items = (evaluationItem.dimensionItems + evaluationItem.filters).map { it as DimensionItem } + val items = (evaluationItem.dimensionItems + evaluationItem.filters) + .map { it as DimensionItem } + .groupBy { it.dimension } val whereClause = - items.foldRight(WhereClauseBuilder()) { item, builder -> - appendWhereClause(item, builder, metadata) + items.entries.fold(WhereClauseBuilder()) { builder, entry -> + when (entry.key) { + is Dimension.Data -> appendDataWhereClause(entry.value, builder) + is Dimension.Period -> appendPeriodWhereClause(entry.value, builder, metadata) + is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder, metadata) + is Dimension.Category -> appendCategoryWhereClause(entry.value, builder, metadata) + is Dimension.CategoryOptionGroupSet -> appendCOGSWhereClause(entry.value, builder, metadata) + } } .appendKeyNumberValue(DataValueTableInfo.Columns.DELETED, 0) .build() @@ -64,51 +75,91 @@ internal class DataElementEvaluator @Inject constructor( } } - private fun appendWhereClause( - item: DimensionItem, - builder: WhereClauseBuilder, - metadata: Map + private fun appendDataWhereClause( + items: List, + builder: WhereClauseBuilder ): WhereClauseBuilder { - return when (item) { - is DimensionItem.DataItem -> + val innerClause = items.map { it as DimensionItem.DataItem } + .foldRight(WhereClauseBuilder()) { item, innerBuilder -> when (item) { is DimensionItem.DataItem.DataElementItem -> - builder.appendKeyStringValue(DataValueTableInfo.Columns.DATA_ELEMENT, item.uid) + innerBuilder.appendOrKeyStringValue(DataValueTableInfo.Columns.DATA_ELEMENT, item.uid) else -> TODO() - } + }.build() - is DimensionItem.PeriodItem -> + return builder.appendComplexQuery(innerClause) + } + + private fun appendPeriodWhereClause( + items: List, + builder: WhereClauseBuilder, + metadata: Map + ): WhereClauseBuilder { + val innerClause = items.map { it as DimensionItem.PeriodItem } + .foldRight(WhereClauseBuilder()) { item, innerBuilder -> when (item) { is DimensionItem.PeriodItem.Absolute -> { val periodItem = metadata[item.periodId] as MetadataItem.PeriodItem - builder.appendInSubQuery( + innerBuilder.appendOrInSubQuery( DataValueTableInfo.Columns.PERIOD, - AnalyticsEvaluatorHelper.getPeriodsClause(periodItem.item) + AnalyticsEvaluatorHelper.getInPeriodClause(periodItem.item) + ) + } + is DimensionItem.PeriodItem.Relative -> { + val periods = parentPeriodGenerator.generateRelativePeriods(item.relative) + innerBuilder.appendOrInSubQuery( + DataValueTableInfo.Columns.PERIOD, + AnalyticsEvaluatorHelper.getInPeriodsClause(periods) ) } - is DimensionItem.PeriodItem.Relative -> TODO() } + }.build() + + return builder.appendComplexQuery(innerClause) + } - is DimensionItem.OrganisationUnitItem -> + private fun appendOrgunitWhereClause( + items: List, + builder: WhereClauseBuilder, + metadata: Map + ): WhereClauseBuilder { + val innerClause = items.map { it as DimensionItem.OrganisationUnitItem } + .foldRight(WhereClauseBuilder()) { item, innerBuilder -> when (item) { is DimensionItem.OrganisationUnitItem.Absolute -> - builder.appendInSubQuery( + innerBuilder.appendOrInSubQuery( DataValueTableInfo.Columns.ORGANISATION_UNIT, AnalyticsEvaluatorHelper.getOrgunitClause(item.uid) ) is DimensionItem.OrganisationUnitItem.Level -> - builder.appendInSubQuery( + innerBuilder.appendOrInSubQuery( DataValueTableInfo.Columns.ORGANISATION_UNIT, AnalyticsEvaluatorHelper.getLevelOrgunitClause(item.level) ) is DimensionItem.OrganisationUnitItem.Relative -> TODO() is DimensionItem.OrganisationUnitItem.Group -> TODO() } + }.build() - is DimensionItem.CategoryItem -> TODO() + return builder.appendComplexQuery(innerClause) + } - is DimensionItem.CategoryOptionGroupSetItem -> TODO() - } + private fun appendCategoryWhereClause( + items: List, + builder: WhereClauseBuilder, + metadata: Map + ): WhereClauseBuilder { + // TODO + return builder + } + + private fun appendCOGSWhereClause( + items: List, + builder: WhereClauseBuilder, + metadata: Map + ): WhereClauseBuilder { + // TODO + return builder } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/querybuilders/internal/WhereClauseBuilder.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/querybuilders/internal/WhereClauseBuilder.java index 43289031bd..eea24e094a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/querybuilders/internal/WhereClauseBuilder.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/querybuilders/internal/WhereClauseBuilder.java @@ -129,6 +129,10 @@ public WhereClauseBuilder appendInSubQuery(String column, String subQuery) { return appendKeyValue(column, subQuery, AND, IN, PARENTHESES_END); } + public WhereClauseBuilder appendOrInSubQuery(String column, String subQuery) { + return appendKeyValue(column, subQuery, OR, IN, PARENTHESES_END); + } + public WhereClauseBuilder appendIsNullValue(String column) { return appendKeyValue(column, "", AND, IS_NULL, ""); } From 5d4b42d625b5ae1fb935d9fd614f9407702f6eba Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 12 Jul 2021 15:18:36 +0200 Subject: [PATCH 152/308] [ANDROSDK-1387] Implement aggregation type in DataElement evaluator --- .../DataElementEvaluatorIntegrationShould.kt | 58 ++++++++++++++++--- .../evaluator/DataElementEvaluatorSamples.kt | 14 ++++- .../AnalyticsServiceEvaluatorHelper.kt | 55 +++++++++++++----- .../evaluator/AnalyticsEvaluatorHelper.kt | 18 ++++++ .../service/evaluator/DataElementEvaluator.kt | 53 ++++++++++------- 5 files changed, 154 insertions(+), 44 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt index 431fea0faa..ae14ea220a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -34,7 +34,8 @@ import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceE import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCombo import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionCombo -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement1 +import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement2 import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent @@ -77,7 +78,8 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat orgunitParent.uid() to MetadataItem.OrganisationUnitItem(orgunitParent), orgunitChild1.uid() to MetadataItem.OrganisationUnitItem(orgunitChild1), orgunitChild2.uid() to MetadataItem.OrganisationUnitItem(orgunitChild2), - dataElement.uid() to MetadataItem.DataElementItem(dataElement), + dataElement1.uid() to MetadataItem.DataElementItem(dataElement1), + dataElement2.uid() to MetadataItem.DataElementItem(dataElement2), periodNov.periodId()!! to MetadataItem.PeriodItem(periodNov), periodDec.periodId()!! to MetadataItem.PeriodItem(periodDec), periodQ4.periodId()!! to MetadataItem.PeriodItem(periodQ4) @@ -94,7 +96,8 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat categoryComboStore.insert(categoryCombo) categoryOptionComboStore.insert(categoryOptionCombo) - dataElementStore.insert(dataElement) + dataElementStore.insert(dataElement1) + dataElementStore.insert(dataElement2) periodStore.insert(periodNov) periodStore.insert(periodDec) @@ -119,7 +122,7 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat val evaluationItem = AnalyticsServiceEvaluationItem( dimensionItems = listOf( - DimensionItem.DataItem.DataElementItem(dataElement.uid()), + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), DimensionItem.PeriodItem.Absolute(periodDec.periodId()!!) ), filters = listOf( @@ -139,7 +142,7 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat val evaluationItem = AnalyticsServiceEvaluationItem( dimensionItems = listOf( - DimensionItem.DataItem.DataElementItem(dataElement.uid()), + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), DimensionItem.PeriodItem.Absolute(periodQ4.periodId()!!) ), filters = listOf( @@ -159,7 +162,7 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat val evaluationItem = AnalyticsServiceEvaluationItem( dimensionItems = listOf( - DimensionItem.DataItem.DataElementItem(dataElement.uid()) + DimensionItem.DataItem.DataElementItem(dataElement1.uid()) ), filters = listOf( DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), @@ -173,9 +176,50 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat assertThat(value).isEqualTo("5") } + @Test + fun should_aggregate_data_elements_if_defined_as_filter() { + createDataValue("2", dataElementUid = dataElement1.uid()) + createDataValue("3", dataElementUid = dataElement2.uid()) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()) + ), + filters = listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), + DimensionItem.DataItem.DataElementItem(dataElement2.uid()), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("5") + } + + @Test + fun should_use_data_element_aggregation_type() { + createDataValue("2", orgunitUid = orgunitChild1.uid(), dataElementUid = dataElement2.uid()) + createDataValue("3", orgunitUid = orgunitChild2.uid(), dataElementUid = dataElement2.uid()) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement2.uid()) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("2.5") + } + private fun createDataValue( value: String, - dataElementUid: String = dataElement.uid(), + dataElementUid: String = dataElement1.uid(), orgunitUid: String = orgunitParent.uid(), periodId: String = periodDec.periodId()!! ) { diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt index f8d52642e8..d59b9cb500 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt @@ -31,6 +31,7 @@ import org.hisp.dhis.android.core.arch.helpers.DateUtils import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl import org.hisp.dhis.android.core.category.CategoryCombo import org.hisp.dhis.android.core.category.CategoryOptionCombo +import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.common.ValueType import org.hisp.dhis.android.core.dataelement.DataElement @@ -80,10 +81,19 @@ object DataElementEvaluatorSamples { .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) .build() - val dataElement = DataElement.builder() + val dataElement1 = DataElement.builder() .uid(generator.generate()) - .displayName("Data element") + .displayName("Data element 1") .valueType(ValueType.NUMBER) + .aggregationType(AggregationType.SUM.name) + .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) + .build() + + val dataElement2 = DataElement.builder() + .uid(generator.generate()) + .displayName("Data element 2") + .valueType(ValueType.INTEGER) + .aggregationType(AggregationType.AVERAGE.name) .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt index e2cdbf79fa..77464e06ad 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt @@ -33,31 +33,56 @@ import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.AnalyticsEvaluator import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator +import java.lang.RuntimeException import javax.inject.Inject internal class AnalyticsServiceEvaluatorHelper @Inject constructor( private val dataElementEvaluator: DataElementEvaluator ) { - fun evaluate(evaluationItem: AnalyticsServiceEvaluationItem, - metadata: Map): DimensionalValue { - val dataItem = evaluationItem.dimensionItems.find { it is DimensionItem.DataItem } - - if (dataItem == null) { - TODO() - } - - val evaluator: AnalyticsEvaluator = - when (dataItem as DimensionItem.DataItem) { - is DimensionItem.DataItem.DataElementItem -> dataElementEvaluator - is DimensionItem.DataItem.DataElementOperandItem -> TODO() - is DimensionItem.DataItem.ProgramIndicatorItem -> TODO() - is DimensionItem.DataItem.IndicatorItem -> TODO() - } + fun evaluate( + evaluationItem: AnalyticsServiceEvaluationItem, + metadata: Map + ): DimensionalValue { + val evaluator = getEvaluator(evaluationItem) return DimensionalValue( dimensions = evaluationItem.dimensionItems.map { (it as DimensionItem).id }, value = evaluator.evaluate(evaluationItem, metadata) ) } + + private fun getEvaluator(evaluationItem: AnalyticsServiceEvaluationItem): AnalyticsEvaluator { + val dimensionDataItems = evaluationItem.dimensionItems.filterIsInstance() + + return when (dimensionDataItems.size) { + 0 -> getEvaluatorFromFilters(evaluationItem.filters) + 1 -> getEvaluatorFromDataDimension(dimensionDataItems.first()) + else -> throw RuntimeException("Invalid arguments: more than one data item as dimension.") + } + } + + private fun getEvaluatorFromFilters(filters: List): AnalyticsEvaluator { + val filterDataItems = filters.filterIsInstance() + + val allAreDataElements = filterDataItems.all { + it is DimensionItem.DataItem.DataElementItem || it is DimensionItem.DataItem.DataElementOperandItem + } + + return when { + filterDataItems.isEmpty() -> throw RuntimeException("Invalid arguments: no data dimension is specified.") + filterDataItems.size == 1 -> getEvaluatorFromDataDimension(filterDataItems.first()) + allAreDataElements -> dataElementEvaluator + else -> throw RuntimeException("Invalid arguments: Only a single indicator can be specified as filter.") + } + } + + private fun getEvaluatorFromDataDimension(item: DimensionItem.DataItem): AnalyticsEvaluator { + return when (item) { + is DimensionItem.DataItem.DataElementItem -> dataElementEvaluator + is DimensionItem.DataItem.DataElementOperandItem -> dataElementEvaluator + is DimensionItem.DataItem.ProgramIndicatorItem -> TODO() + is DimensionItem.DataItem.IndicatorItem -> TODO() + } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt index 62fcb11ec2..25b8d61faa 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -29,12 +29,19 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator import org.hisp.dhis.android.core.arch.helpers.DateUtils +import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo import org.hisp.dhis.android.core.period.Period import org.hisp.dhis.android.core.period.PeriodTableInfo internal object AnalyticsEvaluatorHelper { + const val Sum = "SUM" + const val Avg = "AVG" + const val Count = "COUNT" + const val Max = "MAX" + const val Min = "Min" + fun getInPeriodClause(period: Period): String { return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + @@ -66,4 +73,15 @@ internal object AnalyticsEvaluatorHelper { "WHERE " + "${OrganisationUnitTableInfo.Columns.LEVEL} = $level" } + + fun getDataElementAggregator(aggregationType: String?): String { + return when (aggregationType?.let { AggregationType.valueOf(it) } ?: AggregationType.SUM) { + AggregationType.SUM -> Sum + AggregationType.AVERAGE -> Avg + AggregationType.COUNT -> Count + AggregationType.MAX -> Max + AggregationType.MIN -> Min + else -> Sum + } + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index 5d288578a4..6ebccb92ee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -34,8 +34,10 @@ import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.datavalue.DataValueTableInfo import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator +import java.lang.RuntimeException import javax.inject.Inject internal class DataElementEvaluator @Inject constructor( @@ -56,16 +58,18 @@ internal class DataElementEvaluator @Inject constructor( when (entry.key) { is Dimension.Data -> appendDataWhereClause(entry.value, builder) is Dimension.Period -> appendPeriodWhereClause(entry.value, builder, metadata) - is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder, metadata) - is Dimension.Category -> appendCategoryWhereClause(entry.value, builder, metadata) - is Dimension.CategoryOptionGroupSet -> appendCOGSWhereClause(entry.value, builder, metadata) + is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder) + is Dimension.Category -> TODO() + is Dimension.CategoryOptionGroupSet -> TODO() } } .appendKeyNumberValue(DataValueTableInfo.Columns.DELETED, 0) .build() + val aggregator = getAggregator(evaluationItem, metadata) + val sqlQuery = - "SELECT SUM(${DataValueTableInfo.Columns.VALUE}) " + + "SELECT ${aggregator}(${DataValueTableInfo.Columns.VALUE}) " + "FROM ${DataValueTableInfo.TABLE_INFO.name()} " + "WHERE $whereClause" @@ -121,8 +125,7 @@ internal class DataElementEvaluator @Inject constructor( private fun appendOrgunitWhereClause( items: List, - builder: WhereClauseBuilder, - metadata: Map + builder: WhereClauseBuilder ): WhereClauseBuilder { val innerClause = items.map { it as DimensionItem.OrganisationUnitItem } .foldRight(WhereClauseBuilder()) { item, innerBuilder -> @@ -145,21 +148,31 @@ internal class DataElementEvaluator @Inject constructor( return builder.appendComplexQuery(innerClause) } - private fun appendCategoryWhereClause( - items: List, - builder: WhereClauseBuilder, + private fun getAggregator( + evaluationItem: AnalyticsServiceEvaluationItem, metadata: Map - ): WhereClauseBuilder { - // TODO - return builder - } + ): String { + val dimensionDataItem = evaluationItem.dimensionItems.filterIsInstance() + + val dataItemList = when (dimensionDataItem.size) { + 0 -> evaluationItem.filters.filterIsInstance() + 1 -> dimensionDataItem + else -> throw RuntimeException("Invalid arguments: more than one data item as dimension.") + } + + return when (dataItemList.size) { + 0 -> throw RuntimeException("Invalid arguments: no data dimension is specified.") + 1 -> { + val item = metadata[dataItemList.first().id] + val aggregationType = when (item) { + is MetadataItem.DataElementItem -> item.item.aggregationType() + is MetadataItem.DataElementOperandItem -> item.item.dataElement()?.uid() + else -> throw RuntimeException("Invalid arguments: dimension is not dataelement or operand.") + } + AnalyticsEvaluatorHelper.getDataElementAggregator(aggregationType) + } + else -> AnalyticsEvaluatorHelper.getDataElementAggregator(AggregationType.SUM.name) + } - private fun appendCOGSWhereClause( - items: List, - builder: WhereClauseBuilder, - metadata: Map - ): WhereClauseBuilder { - // TODO - return builder } } \ No newline at end of file From 1cf990b8e59b578779f344a769d86c4aeadca71a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 12 Jul 2021 16:40:46 +0200 Subject: [PATCH 153/308] [androsdk-1383] Update the Dhis2MockServer --- .../core/mockwebserver/Dhis2MockServer.java | 4 ++++ .../visualization/visualizations.json | 21 +++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java b/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java index 781d641650..3888dcaebc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java @@ -86,6 +86,7 @@ public class Dhis2MockServer { private static final String CATEGORY_COMBOS_JSON = "category/category_combos.json"; private static final String CATEGORIES_JSON = "category/categories.json"; private static final String CATEGORY_OPTIONS_JSON = "category/category_options.json"; + private static final String VISUALIZATIONS_JSON = "visualization/visualizations.json"; private static final String ORGANISATION_UNIT_LEVELS_JSON = "organisationunit/organisation_unit_levels.json"; private static final String CONSTANTS_JSON = "constant/constants.json"; private static final String USER_JSON = "user/user.json"; @@ -229,6 +230,8 @@ public MockResponse dispatch(RecordedRequest request) { return createMockResponse(CATEGORIES_JSON); } else if (path.startsWith("/api/categoryOptions?")) { return createMockResponse(CATEGORY_OPTIONS_JSON); + } else if (path.startsWith("/api/visualizations?")) { + return createMockResponse(VISUALIZATIONS_JSON); } else if (path.startsWith("/api/organisationUnits?")) { return createMockResponse(ORGANISATION_UNITS_JSON); } else if (path.startsWith("/api/organisationUnitLevels?")) { @@ -306,6 +309,7 @@ public void enqueueMetadataResponses() { enqueueMockResponse(CATEGORY_COMBOS_JSON); enqueueMockResponse(CATEGORIES_JSON); enqueueMockResponse(CATEGORY_OPTIONS_JSON); + enqueueMockResponse(VISUALIZATIONS_JSON); } @NonNull diff --git a/core/src/sharedTest/resources/visualization/visualizations.json b/core/src/sharedTest/resources/visualization/visualizations.json index 1286edbdb0..91a5f27899 100644 --- a/core/src/sharedTest/resources/visualization/visualizations.json +++ b/core/src/sharedTest/resources/visualization/visualizations.json @@ -21,7 +21,7 @@ "hideSubtitle": false, "hideEmptyColumns": false, "hideEmptyRows": false, - "hideEmptyRowItems": "NONE", + "hideEmptyRowItems": "AFTER_LAST", "hideLegend": false, "showHierarchy": false, "rowTotals": true, @@ -41,14 +41,17 @@ "categoryDimensions": [ { "category": { - "id": "fMZEcRHuamy" + "id": "KfdsGBcoiCa" }, "categoryOptions": [ { - "id": "qkPbeWaFsnU" + "id": "TNYQzTHdoxL" + }, + { + "id": "TXGfLxZlInA" }, { - "id": "wbrDrL2aYEc" + "id": "uZUnebiT5DI" } ] } @@ -113,8 +116,8 @@ "displayFormName": "Android SDK Visualization sample 2", "lastUpdated": "2021-06-16T14:26:50.195", "created": "2021-06-16T14:26:50.195", - "type": "PIVOT_TABLE", - "hideTitle": false, + "type": "COLUMN", + "hideTitle": true, "hideSubtitle": false, "hideEmptyColumns": false, "hideEmptyRows": false, @@ -138,14 +141,14 @@ "categoryDimensions": [ { "category": { - "id": "fMZEcRHuamy" + "id": "cX5k9anHEHd" }, "categoryOptions": [ { - "id": "qkPbeWaFsnU" + "id": "apsOixVZlf1" }, { - "id": "wbrDrL2aYEc" + "id": "jRbMi0aBjYn" } ] } From 1af78b55b8e880ac024a363fcb30653b49066fd4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 12 Jul 2021 16:41:24 +0200 Subject: [PATCH 154/308] [androsdk-1383] Add a VisualizationModuleDownloader --- .../core/domain/metadata/MetadataCall.kt | 10 +++- .../internal/VisualizationModuleDownloader.kt | 46 +++++++++++++++++++ .../domain/metadata/MetadataCallShould.kt | 12 +++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt index 3fe9d8572d..05246fb97e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt @@ -31,7 +31,6 @@ import dagger.Reusable import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.RxAPICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager @@ -60,6 +59,9 @@ import org.hisp.dhis.android.core.systeminfo.SystemInfo import org.hisp.dhis.android.core.systeminfo.internal.SystemInfoModuleDownloader import org.hisp.dhis.android.core.user.User import org.hisp.dhis.android.core.user.internal.UserModuleDownloader +import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.internal.VisualizationModuleDownloader +import javax.inject.Inject @Suppress("LongParameterList") @Reusable @@ -72,6 +74,7 @@ class MetadataCall @Inject internal constructor( private val programDownloader: ProgramModuleDownloader, private val organisationUnitModuleDownloader: OrganisationUnitModuleDownloader, private val dataSetDownloader: DataSetModuleDownloader, + private val visualizationDownloader: VisualizationModuleDownloader, private val constantModuleDownloader: ConstantModuleDownloader, private val smsModule: SmsModule, private val databaseAdapter: DatabaseAdapter, @@ -135,6 +138,11 @@ class MetadataCall @Inject internal constructor( }, categoryDownloader.downloadMetadata().toSingle { progressManager.increaseProgress(Category::class.java, false) + }, + visualizationDownloader.downloadMetadata( + setOf("visualization_uid") + ).map { + progressManager.increaseProgress(Visualization::class.java, false) } ).toObservable() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt new file mode 100644 index 0000000000..bcbb341009 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Reusable +import io.reactivex.Single +import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall +import org.hisp.dhis.android.core.arch.modules.internal.MetadataModuleByUidDownloader +import org.hisp.dhis.android.core.visualization.Visualization +import javax.inject.Inject + +@Reusable +class VisualizationModuleDownloader @Inject internal constructor( + private val visualizationCall: UidsCall +) : + MetadataModuleByUidDownloader> { + + override fun downloadMetadata(visualizationUids: Set): Single> { + return visualizationCall.download(visualizationUids) + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt b/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt index 79db4ace54..796ac438e0 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt @@ -51,6 +51,7 @@ import org.hisp.dhis.android.core.sms.domain.interactor.ConfigCase import org.hisp.dhis.android.core.systeminfo.internal.SystemInfoModuleDownloader import org.hisp.dhis.android.core.user.User import org.hisp.dhis.android.core.user.internal.UserModuleDownloader +import org.hisp.dhis.android.core.visualization.internal.VisualizationModuleDownloader import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -69,6 +70,7 @@ class MetadataCallShould : BaseCallShould() { private val programDownloader: ProgramModuleDownloader = mock() private val organisationUnitDownloader: OrganisationUnitModuleDownloader = mock() private val dataSetDownloader: DataSetModuleDownloader = mock() + private val visualizationDownloader: VisualizationModuleDownloader = mock() private val constantDownloader: ConstantModuleDownloader = mock() private val smsModule: SmsModule = mock() private val configCase: ConfigCase = mock() @@ -98,6 +100,9 @@ class MetadataCallShould : BaseCallShould() { whenever(dataSetDownloader.downloadMetadata(any())).thenReturn( Single.just(emptyList()) ) + whenever(visualizationDownloader.downloadMetadata(any())).thenReturn( + Single.just(emptyList()) + ) whenever(constantDownloader.downloadMetadata()).thenReturn(Single.just(emptyList())) whenever(categoryDownloader.downloadMetadata()).thenReturn(Completable.complete()) whenever(smsModule.configCase()).thenReturn(configCase) @@ -121,6 +126,7 @@ class MetadataCallShould : BaseCallShould() { programDownloader, organisationUnitDownloader, dataSetDownloader, + visualizationDownloader, constantDownloader, smsModule, databaseAdapter, @@ -165,6 +171,12 @@ class MetadataCallShould : BaseCallShould() { downloadAndAssertError() } + @Test + fun fail_when_visualization_download_call_fail() { + whenever(visualizationDownloader.downloadMetadata(any())).thenReturn(Single.error(d2Error)) + downloadAndAssertError() + } + @Test fun fail_when_program_call_fail() { whenever(programDownloader.downloadMetadata(any())).thenReturn(Single.error(d2Error)) From cb0094cdc271b1b2b271ffc7edbc0b0b3a146055 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 12 Jul 2021 16:42:21 +0200 Subject: [PATCH 155/308] [androsdk-1383] Add the VisualizationCollectionRepository test --- ...ectionRepositoryMockIntegrationShould.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java new file mode 100644 index 0000000000..e4a65f548c --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004-2021, 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.visualization; + +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; +import org.hisp.dhis.android.core.visualization.HideEmptyItemStrategy; +import org.hisp.dhis.android.core.visualization.Visualization; +import org.hisp.dhis.android.core.visualization.VisualizationType; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +import static com.google.common.truth.Truth.assertThat; + +@RunWith(D2JunitRunner.class) +public class VisualizationCollectionRepositoryMockIntegrationShould extends BaseMockIntegrationTestFullDispatcher { + + @Test + public void find_all() { + List visualizations = d2.visualizationModule().visualizations().blockingGet(); + assertThat(visualizations.size()).isEqualTo(2); + } + + @Test + public void find_uids() { + List visualizationUids = d2.visualizationModule().visualizations() + .blockingGetUids(); + assertThat(visualizationUids.size()).isEqualTo(2); + assertThat(visualizationUids.contains("PYBH8ZaAQnC")).isTrue(); + assertThat(visualizationUids.contains("FAFa11yFeFe")).isTrue(); + } + + @Test + public void find_by_description() { + List visualizations = d2.visualizationModule().visualizations() + .byDescription().eq("Sample visualization for the Android SDK") + .blockingGet(); + assertThat(visualizations.size()).isEqualTo(1); + assertThat(visualizations.get(0).uid()).isEqualTo("PYBH8ZaAQnC"); + } + + @Test + public void find_by_display_description() { + List visualizations = d2.visualizationModule().visualizations() + .byDisplayDescription().eq("Sample visualization for the Android SDK") + .blockingGet(); + assertThat(visualizations.size()).isEqualTo(1); + assertThat(visualizations.get(0).uid()).isEqualTo("PYBH8ZaAQnC"); + } + + @Test + public void find_by_display_form_name() { + List visualizations = d2.visualizationModule().visualizations() + .byDisplayFormName().eq("Android SDK Visualization sample") + .blockingGet(); + assertThat(visualizations.size()).isEqualTo(1); + assertThat(visualizations.get(0).uid()).isEqualTo("PYBH8ZaAQnC"); + } + + @Test + public void find_by_visualization_type() { + List visualizations = d2.visualizationModule().visualizations() + .byType().eq(VisualizationType.COLUMN) + .blockingGet(); + assertThat(visualizations.size()).isEqualTo(1); + assertThat(visualizations.get(0).uid()).isEqualTo("FAFa11yFeFe"); + } + + @Test + public void find_by_hide_title() { + List visualizations = d2.visualizationModule().visualizations() + .byHideTitle().isFalse() + .blockingGet(); + assertThat(visualizations.size()).isEqualTo(1); + } + + @Test + public void find_by_hide_empty_row_items() { + List visualizations = d2.visualizationModule().visualizations() + .byHideEmptyRowItems().eq(HideEmptyItemStrategy.AFTER_LAST) + .blockingGet(); + assertThat(visualizations.size()).isEqualTo(1); + } + + @Test + public void include_category_dimensions_as_children() { + Visualization visualization = d2.visualizationModule().visualizations() + .withCategoryDimensions().one().blockingGet(); + assertThat(visualization.categoryDimensions().get(0).category().uid()).isEqualTo("KfdsGBcoiCa"); + assertThat(visualization.categoryDimensions().get(0).categoryOptions().get(0).uid()).isEqualTo("TNYQzTHdoxL"); + assertThat(visualization.categoryDimensions().get(0).categoryOptions().get(1).uid()).isEqualTo("TXGfLxZlInA"); + assertThat(visualization.categoryDimensions().get(0).categoryOptions().get(2).uid()).isEqualTo("uZUnebiT5DI"); + } +} \ No newline at end of file From a9117b306b6e307e9eae493ec2e429ca4422bddf Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 12 Jul 2021 17:01:22 +0200 Subject: [PATCH 156/308] [androsdk-1383] Add the VisualizationPublicAccessShould --- .../VisualizationPublicAccessShould.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 core/src/test/java/org/hisp/dhis/android/testapp/visualization/VisualizationPublicAccessShould.java diff --git a/core/src/test/java/org/hisp/dhis/android/testapp/visualization/VisualizationPublicAccessShould.java b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/VisualizationPublicAccessShould.java new file mode 100644 index 0000000000..95ef136e7c --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/VisualizationPublicAccessShould.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.visualization; + +import org.hisp.dhis.android.core.visualization.Visualization; +import org.hisp.dhis.android.testapp.arch.BasePublicAccessShould; +import org.mockito.Mock; + +public class VisualizationPublicAccessShould extends BasePublicAccessShould { + + @Mock + private Visualization object; + + @Override + public Visualization object() { + return object; + } + + @Override + public void has_public_create_method() { + Visualization.create(null); + } + + @Override + public void has_public_builder_method() { + Visualization.builder(); + } + + @Override + public void has_public_to_builder_method() { + object().toBuilder(); + } +} \ No newline at end of file From 1e8e839a1c6180c66a506b850d45bfd816fb0163 Mon Sep 17 00:00:00 2001 From: andresmr Date: Fri, 9 Jul 2021 12:18:08 +0200 Subject: [PATCH 157/308] [ANDROSDK-1384] Store AnalyticsDhisVisualization in database --- ...DhisVisualizationStoreIntegrationShould.kt | 49 ++++++++++ core/src/main/assets/migrations/105.sql | 1 + .../assets/snapshots/{104.sql => 105.sql} | 1 + .../internal/BaseDatabaseOpenHelper.java | 2 +- .../AnalyticsDhisVisualizationTableInfo.kt | 70 +++++++++++++ ...nalyticsDhisVisualizationSettingHandler.kt | 48 +++++++++ .../AnalyticsDhisVisualizationStore.kt | 64 ++++++++++++ .../settings/internal/AnalyticsSettingCall.kt | 10 ++ .../AnalyticsSettingEntityDIModule.kt | 27 +++++- .../settings/internal/SettingsAppHelper.kt | 80 ++++++++++++++- .../data/settings/AnalyticsSettingsSamples.kt | 25 ++++- .../settings/analytics_settings_v2.json | 79 +++++++++++++++ ...gShould.kt => AnalyticsSettingV1Should.kt} | 2 +- .../core/settings/AnalyticsSettingV2Should.kt | 97 +++++++++++++++++++ .../internal/AnalyticsSettingCallShould.kt | 17 +++- 15 files changed, 563 insertions(+), 9 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStoreIntegrationShould.kt create mode 100644 core/src/main/assets/migrations/105.sql rename core/src/main/assets/snapshots/{104.sql => 105.sql} (99%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationSettingHandler.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStore.kt create mode 100644 core/src/sharedTest/resources/settings/analytics_settings_v2.json rename core/src/test/java/org/hisp/dhis/android/core/settings/{AnalyticsSettingShould.kt => AnalyticsSettingV1Should.kt} (98%) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStoreIntegrationShould.kt new file mode 100644 index 0000000000..ccac7f9772 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStoreIntegrationShould.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings.internal + +import org.hisp.dhis.android.core.data.database.ObjectStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.data.settings.AnalyticsSettingsSamples +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationTableInfo +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class AnalyticsDhisVisualizationStoreIntegrationShould : + ObjectStoreAbstractIntegrationShould( + AnalyticsDhisVisualizationStore.create(TestDatabaseAdapterFactory.get()), + AnalyticsDhisVisualizationTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() + ) { + override fun buildObject(): AnalyticsDhisVisualization { + return AnalyticsSettingsSamples.analyticsDhisVisualization + } +} diff --git a/core/src/main/assets/migrations/105.sql b/core/src/main/assets/migrations/105.sql new file mode 100644 index 0000000000..373c2d1d43 --- /dev/null +++ b/core/src/main/assets/migrations/105.sql @@ -0,0 +1 @@ +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); diff --git a/core/src/main/assets/snapshots/104.sql b/core/src/main/assets/snapshots/105.sql similarity index 99% rename from core/src/main/assets/snapshots/104.sql rename to core/src/main/assets/snapshots/105.sql index a2dc05807f..f38f1de9ab 100644 --- a/core/src/main/assets/snapshots/104.sql +++ b/core/src/main/assets/snapshots/105.sql @@ -111,3 +111,4 @@ CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMEN CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index 5aafddb5ee..75dd2ca255 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 104; + static final int VERSION = 105; private final AssetManager assetManager; private final int targetVersion; diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt new file mode 100644 index 0000000000..f20383e452 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns +import org.hisp.dhis.android.core.common.IdentifiableColumns + +object AnalyticsDhisVisualizationTableInfo { + + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "AnalyticsDhisVisualization" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : CoreColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + UID, + SCOPE_UID, + SCOPE, + GROUP_UID, + GROUP_NAME, + TIME_STAMP + ) + } + + companion object { + const val UID = IdentifiableColumns.UID + const val SCOPE_UID = "scopeUid" + const val SCOPE = "scope" + const val GROUP_UID = "groupUid" + const val GROUP_NAME = "groupName" + const val TIME_STAMP = "timestamp" + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationSettingHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationSettingHandler.kt new file mode 100644 index 0000000000..3b1d5772ef --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationSettingHandler.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings.internal + +import dagger.Reusable +import javax.inject.Inject +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.handlers.internal.ObjectWithoutUidHandlerImpl +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization + +@Reusable +internal class AnalyticsDhisVisualizationSettingHandler @Inject constructor( + store: ObjectWithoutUidStore +) : ObjectWithoutUidHandlerImpl(store) { + + override fun beforeCollectionHandled( + oCollection: Collection + ): Collection { + store.delete() + return oCollection + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStore.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStore.kt new file mode 100644 index 0000000000..a0a85e96a8 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsDhisVisualizationStore.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004-2021, 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.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.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 +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithoutUidStore +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationTableInfo + +@Suppress("MagicNumber") +internal object AnalyticsDhisVisualizationStore { + + private val BINDER = StatementBinder { o: AnalyticsDhisVisualization, w: StatementWrapper -> + w.bind(1, o.uid()) + w.bind(2, o.scopeUid()) + w.bind(3, o.scope()) + w.bind(4, o.groupUid()) + w.bind(5, o.groupName()) + w.bind(6, o.timestamp()) + } + + private val WHERE_UPDATE_BINDER = WhereStatementBinder { _: AnalyticsDhisVisualization, _: StatementWrapper -> + } + + private val WHERE_DELETE_BINDER = WhereStatementBinder { _: AnalyticsDhisVisualization, _: StatementWrapper -> } + + fun create(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { + return objectWithoutUidStore( + databaseAdapter, AnalyticsDhisVisualizationTableInfo.TABLE_INFO, BINDER, + WHERE_UPDATE_BINDER, WHERE_DELETE_BINDER + ) { cursor: Cursor -> AnalyticsDhisVisualization.create(cursor) } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt index f550727852..338832993e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt @@ -35,12 +35,14 @@ import org.hisp.dhis.android.core.arch.api.executors.internal.RxAPICallExecutor import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.maintenance.D2Error import org.hisp.dhis.android.core.maintenance.D2ErrorCode +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization import org.hisp.dhis.android.core.settings.AnalyticsSettings import org.hisp.dhis.android.core.settings.AnalyticsTeiSetting @Reusable internal class AnalyticsSettingCall @Inject constructor( private val analyticsTeiSettingHandler: Handler, + private val analyticsDhisVisualizationsSettingHandler: Handler, private val settingAppService: SettingAppService, private val apiCallExecutor: RxAPICallExecutor, private val appVersionManager: SettingsAppInfoManager @@ -68,5 +70,13 @@ internal class AnalyticsSettingCall @Inject constructor( override fun process(item: AnalyticsSettings?) { val analyticsTeiSettingList = item?.tei() ?: emptyList() analyticsTeiSettingHandler.handleMany(analyticsTeiSettingList) + + val analyticsDhisVisualizations: List = item?. let { + SettingsAppHelper.getAnalyticsDhisVisualizations(it) + } ?: emptyList() + + item?.dhisVisualizations()?.let { + analyticsDhisVisualizationsSettingHandler.handleMany(analyticsDhisVisualizations) + } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt index 64470910a1..1120297dd4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt @@ -37,7 +37,12 @@ import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandlerImpl import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender -import org.hisp.dhis.android.core.settings.* +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization +import org.hisp.dhis.android.core.settings.AnalyticsTeiAttribute +import org.hisp.dhis.android.core.settings.AnalyticsTeiDataElement +import org.hisp.dhis.android.core.settings.AnalyticsTeiIndicator +import org.hisp.dhis.android.core.settings.AnalyticsTeiSetting +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionData @Module @Suppress("TooManyFunctions") @@ -49,6 +54,14 @@ internal class AnalyticsSettingEntityDIModule { return AnalyticsTeiSettingStore.create(databaseAdapter) } + @Provides + @Reusable + fun analyticsDhisVisualizationStore( + databaseAdapter: DatabaseAdapter + ): ObjectWithoutUidStore { + return AnalyticsDhisVisualizationStore.create(databaseAdapter) + } + @Provides @Reusable fun analyticsTeiDataElementStore(databaseAdapter: DatabaseAdapter): LinkStore { @@ -79,6 +92,14 @@ internal class AnalyticsSettingEntityDIModule { return impl } + @Provides + @Reusable + fun analyticsDhisVisualizationsHandler( + impl: AnalyticsDhisVisualizationSettingHandler + ): Handler { + return impl + } + @Provides @Reusable fun analyticsTeiDataElementHandler( @@ -115,6 +136,6 @@ internal class AnalyticsSettingEntityDIModule { @Reusable fun teiChildrenAppenders(dataChildrenAppender: AnalyticsTeiDataChildrenAppender): Map> { - return mapOf(AnalyticsTeiDataChildrenAppender.KEY to dataChildrenAppender) - } + return mapOf(AnalyticsTeiDataChildrenAppender.KEY to dataChildrenAppender) + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt index a254a5dcdd..634b831c0f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt @@ -27,7 +27,31 @@ */ package org.hisp.dhis.android.core.settings.internal -import org.hisp.dhis.android.core.settings.* +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationScope +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationsGroup +import org.hisp.dhis.android.core.settings.AnalyticsSettings +import org.hisp.dhis.android.core.settings.AnalyticsTeiAttribute +import org.hisp.dhis.android.core.settings.AnalyticsTeiData +import org.hisp.dhis.android.core.settings.AnalyticsTeiDataElement +import org.hisp.dhis.android.core.settings.AnalyticsTeiIndicator +import org.hisp.dhis.android.core.settings.AnalyticsTeiSetting +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionData +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionItem +import org.hisp.dhis.android.core.settings.AppearanceSettings +import org.hisp.dhis.android.core.settings.ChartType +import org.hisp.dhis.android.core.settings.CompletionSpinner +import org.hisp.dhis.android.core.settings.DataSetFilter +import org.hisp.dhis.android.core.settings.DataSetFilters +import org.hisp.dhis.android.core.settings.DataSetSetting +import org.hisp.dhis.android.core.settings.DataSetSettings +import org.hisp.dhis.android.core.settings.FilterSetting +import org.hisp.dhis.android.core.settings.HomeFilter +import org.hisp.dhis.android.core.settings.ProgramFilter +import org.hisp.dhis.android.core.settings.ProgramFilters +import org.hisp.dhis.android.core.settings.ProgramSetting +import org.hisp.dhis.android.core.settings.ProgramSettings +import org.hisp.dhis.android.core.settings.WHONutritionComponent internal object SettingsAppHelper { @@ -119,6 +143,60 @@ internal object SettingsAppHelper { return list } + fun getAnalyticsDhisVisualizations(analyticsSettings: AnalyticsSettings): List { + val result = mutableListOf() + + analyticsSettings.dhisVisualizations()?.let { visualizationsSetting -> + + getHomeVisualizations(visualizationsSetting.home())?.let { result.addAll(it) } + + getProgramVisualizations(visualizationsSetting.program())?.let { result.addAll(it) } + + getDataSetVisualizations(visualizationsSetting.dataSet())?.let { result.addAll(it) } + } + + return result + } + + private fun getHomeVisualizations(analyticsDhisVisualizationsGroups: List?) = + analyticsDhisVisualizationsGroups?.flatMap { group -> + group.visualizations().map { visualization -> + visualization.toBuilder() + .groupUid(group.id()) + .groupName(group.name()) + .scope(AnalyticsDhisVisualizationScope.HOME) + .build() + } + } + + private fun getProgramVisualizations(programVisualizations: Map>?) = + programVisualizations?.flatMap { entry -> + entry.value.flatMap { group -> + group.visualizations().map { visualization -> + visualization.toBuilder() + .groupUid(group.id()) + .groupName(group.name()) + .scope(AnalyticsDhisVisualizationScope.PROGRAM) + .scopeUid(entry.key) + .build() + } + } + } + + private fun getDataSetVisualizations(dataSetVisualizations: Map>?) = + dataSetVisualizations?.flatMap { entry -> + entry.value.flatMap { group -> + group.visualizations().map { visualization -> + visualization.toBuilder() + .groupUid(group.id()) + .groupName(group.name()) + .scope(AnalyticsDhisVisualizationScope.DATA_SET) + .scopeUid(entry.key) + .build() + } + } + } + @JvmStatic fun buildAnalyticsTeiSettings( teiSettings: List, diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt index 4ff3793de1..a3091e18a0 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt @@ -28,7 +28,20 @@ package org.hisp.dhis.android.core.data.settings import org.hisp.dhis.android.core.period.PeriodType -import org.hisp.dhis.android.core.settings.* +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationScope +import org.hisp.dhis.android.core.settings.AnalyticsTeiAttribute +import org.hisp.dhis.android.core.settings.AnalyticsTeiData +import org.hisp.dhis.android.core.settings.AnalyticsTeiDataElement +import org.hisp.dhis.android.core.settings.AnalyticsTeiIndicator +import org.hisp.dhis.android.core.settings.AnalyticsTeiSetting +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionData +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionGender +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionGenderValues +import org.hisp.dhis.android.core.settings.AnalyticsTeiWHONutritionItem +import org.hisp.dhis.android.core.settings.ChartType +import org.hisp.dhis.android.core.settings.WHONutritionChartType +import org.hisp.dhis.android.core.settings.WHONutritionComponent object AnalyticsSettingsSamples { @@ -89,4 +102,14 @@ object AnalyticsSettingsSamples { .x(AnalyticsTeiWHONutritionItem.builder().build()) .y(AnalyticsTeiWHONutritionItem.builder().build()) .build() + + val analyticsDhisVisualization: AnalyticsDhisVisualization = + AnalyticsDhisVisualization.builder() + .id(1L) + .groupName("Otro grupo") + .groupUid("123456") + .scope(AnalyticsDhisVisualizationScope.HOME) + .timestamp("2021-07-01T02:55:16.8770") + .uid("KgC9TdlpjZC") + .build() } diff --git a/core/src/sharedTest/resources/settings/analytics_settings_v2.json b/core/src/sharedTest/resources/settings/analytics_settings_v2.json new file mode 100644 index 0000000000..e1b14c918f --- /dev/null +++ b/core/src/sharedTest/resources/settings/analytics_settings_v2.json @@ -0,0 +1,79 @@ +{ + "tei": [ + { + "uid": "Lryd0j1jhho", + "data": { + "attributes": [ + "OvY4VVhSDeJ" + ] + }, + "name": "Lab monitoring weekly weight", + "type": "LINE", + "period": "Weekly", + "program": "ur1Edk5Oe2n", + "shortName": "line_weekly_kg", + "programStage": "EPEcjy3FWmI" + } + ], + "lastUpdated": "2021-06-02T04:30:16.877Z", + "dhisVisualizations": { + "home": [ + { + "id": "12345678910", + "name": "Ejemplo", + "visualizations": [ + { + "id": "TXcKIg4LuA3", + "timestamp": "2021-07-01T03:01:16.8770" + }, + { + "id": "eykdwnDx8ie", + "timestamp": "2021-07-01T03:02:16.8770" + } + ] + }, + { + "id": "12345678911", + "name": "Otro ejemplo", + "visualizations": [ + { + "id": "KgC9TdlpjZC", + "timestamp": "2021-07-01T03:04:16.8770" + } + ] + } + ], + "dataSet": { + "BfMAe6Itzgt": [ + { + "id": "0000000001", + "name": "default", + "visualizations": [ + { + "id": "TXcKIg4LuA3", + "timestamp": "2021-07-01T02:55:16.8770" + } + ] + } + ] + }, + "program": { + "IpHINAT79UW": [ + { + "id": "0000000001", + "name": "default", + "visualizations": [ + { + "id": "eykdwnDx8ie", + "timestamp": "2021-07-01T02:55:16.8770" + }, + { + "id": "KgC9TdlpjZC", + "timestamp": "2021-07-01T02:55:16.8770" + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingShould.kt b/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV1Should.kt similarity index 98% rename from core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingShould.kt rename to core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV1Should.kt index d6812b8e2b..50130d45cb 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV1Should.kt @@ -36,7 +36,7 @@ import org.hisp.dhis.android.core.period.PeriodType import org.junit.Assert.fail import org.junit.Test -class AnalyticsSettingShould : BaseObjectShould("settings/analytics_settings.json"), ObjectShould { +class AnalyticsSettingV1Should : BaseObjectShould("settings/analytics_settings.json"), ObjectShould { @Test @Throws(IOException::class, ParseException::class) diff --git a/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt b/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt new file mode 100644 index 0000000000..3d480f4bbb --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings + +import com.google.common.truth.Truth +import java.io.IOException +import java.text.ParseException +import org.hisp.dhis.android.core.common.BaseObjectShould +import org.hisp.dhis.android.core.common.ObjectShould +import org.hisp.dhis.android.core.period.PeriodType +import org.junit.Assert +import org.junit.Test + +class AnalyticsSettingV2Should : BaseObjectShould("settings/analytics_settings_v2.json"), ObjectShould { + + @Test + @Throws(IOException::class, ParseException::class) + override fun map_from_json_string() { + val analyticsSettings = objectMapper.readValue(jsonStream, AnalyticsSettings::class.java) + + Truth.assertThat(analyticsSettings.tei().size).isEqualTo(1) + + analyticsSettings.tei().forEach { tei -> + when (tei.uid()) { + "Lryd0j1jhho" -> { + Truth.assertThat(tei.name()).isEqualTo("Lab monitoring weekly weight") + Truth.assertThat(tei.shortName()).isEqualTo("line_weekly_kg") + Truth.assertThat(tei.program()).isEqualTo("ur1Edk5Oe2n") + Truth.assertThat(tei.programStage()).isEqualTo("EPEcjy3FWmI") + Truth.assertThat(tei.period()).isEquivalentAccordingToCompareTo(PeriodType.Weekly) + Truth.assertThat(tei.type()).isEquivalentAccordingToCompareTo(ChartType.LINE) + } + else -> Assert.fail("Unexpected tei uid") + } + } + + Truth.assertThat(analyticsSettings.dhisVisualizations().home().size).isEqualTo(2) + analyticsSettings.dhisVisualizations().home().forEach { group -> + when (group.id()) { + "12345678910" -> { + Truth.assertThat(group.name()).isEqualTo("Ejemplo") + Truth.assertThat(group.visualizations().size).isEqualTo(2) + } + "12345678911" -> { + Truth.assertThat(group.name()).isEqualTo("Otro ejemplo") + Truth.assertThat(group.visualizations().size).isEqualTo(1) + } + } + } + + Truth.assertThat(analyticsSettings.dhisVisualizations().dataSet().size).isEqualTo(1) + analyticsSettings.dhisVisualizations().dataSet().forEach { map -> + when (map.key) { + "BfMAe6Itzgt" -> { + Truth.assertThat(map.value.size).isEqualTo(1) + Truth.assertThat(map.value[0].visualizations().size).isEqualTo(1) + } + } + } + + Truth.assertThat(analyticsSettings.dhisVisualizations().program().size).isEqualTo(1) + analyticsSettings.dhisVisualizations().program().forEach { map -> + when (map.key) { + "IpHINAT79UW" -> { + Truth.assertThat(map.value.size).isEqualTo(1) + Truth.assertThat(map.value[0].visualizations().size).isEqualTo(2) + } + } + } + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCallShould.kt b/core/src/test/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCallShould.kt index 3990837840..b9957af871 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCallShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCallShould.kt @@ -27,11 +27,17 @@ */ package org.hisp.dhis.android.core.settings.internal -import com.nhaarman.mockitokotlin2.* +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.doReturn +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions +import com.nhaarman.mockitokotlin2.whenever import io.reactivex.Single import org.hisp.dhis.android.core.arch.api.executors.internal.RxAPICallExecutor import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.data.maintenance.D2ErrorSamples +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization import org.hisp.dhis.android.core.settings.AnalyticsSettings import org.hisp.dhis.android.core.settings.AnalyticsTeiSetting import org.junit.Before @@ -42,6 +48,7 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class AnalyticsSettingCallShould { private val handler: Handler = mock() + private val analyticsDhisVisualizationsSettingHandler: Handler = mock() private val service: SettingAppService = mock() private val analyticsSettingSingle: Single = mock() private val apiCallExecutor: RxAPICallExecutor = mock() @@ -53,7 +60,13 @@ class AnalyticsSettingCallShould { fun setUp() { whenever(appVersionManager.getDataStoreVersion()) doReturn Single.just(SettingsAppDataStoreVersion.V1_1) whenever(service.analyticsSettings(any())) doReturn analyticsSettingSingle - analyticsSettingCall = AnalyticsSettingCall(handler, service, apiCallExecutor, appVersionManager) + analyticsSettingCall = AnalyticsSettingCall( + handler, + analyticsDhisVisualizationsSettingHandler, + service, + apiCallExecutor, + appVersionManager + ) } @Test From fb961c7fa2682cb43dbe4392d6e3dd2dc7408787 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 13 Jul 2021 08:28:08 +0200 Subject: [PATCH 158/308] [ANDROSDK-1384] DhisVisualizations repository --- ...VisualizationsSettingObjectRepository.java | 176 ++++++++++++++++++ .../AnalyticsSettingObjectRepository.java | 17 +- .../AnalyticsSettingEntityDIModule.kt | 4 +- .../settings/internal/SettingsAppHelper.kt | 1 + 4 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java new file mode 100644 index 0000000000..12dcf196a8 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2004-2021, 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.core.settings; + +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; +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.AnalyticsSettingCall; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.inject.Inject; + +import dagger.Reusable; + +@Reusable +public class AnalyticsDhisVisualizationsSettingObjectRepository + extends ReadOnlyAnyObjectWithDownloadRepositoryImpl + implements ReadOnlyWithDownloadObjectRepository { + + private final ObjectWithoutUidStore analyticsDhisVisualizationStore; + + @Inject + public AnalyticsDhisVisualizationsSettingObjectRepository( + ObjectWithoutUidStore analyticsDhisVisualizationStore, + AnalyticsSettingCall analyticsSettingCall) { + super(analyticsSettingCall); + this.analyticsDhisVisualizationStore = analyticsDhisVisualizationStore; + } + + @Override + public AnalyticsDhisVisualizationsSetting blockingGet() { + List analyticsDhisVisualizations = analyticsDhisVisualizationStore.selectAll(); + + if (analyticsDhisVisualizations.isEmpty()) { + return null; + } + + AnalyticsDhisVisualizationsSetting.Builder analyticsDhisVisualizationsSettingBuilder = + AnalyticsDhisVisualizationsSetting.builder(); + List home = new ArrayList<>(); + Map> program = new HashMap<>(); + Map> dataSet = new HashMap<>(); + + for (AnalyticsDhisVisualization analyticsDhisVisualization : analyticsDhisVisualizations) { + AnalyticsDhisVisualizationsGroup group; + switch (Objects.requireNonNull(analyticsDhisVisualization.scope())) { + case HOME: + group = getGroup(analyticsDhisVisualization.groupUid(), home); + + if (group == null) { + group = createGroup(analyticsDhisVisualization); + home.add(group); + } else { + AnalyticsDhisVisualizationsGroup updatedGroup = updateGroup(group, analyticsDhisVisualization); + home.remove(group); + home.add(updatedGroup); + } + break; + case PROGRAM: + group = getGroup( + analyticsDhisVisualization.groupUid(), + program.get(analyticsDhisVisualization.scopeUid()) + ); + + if (group == null) { + group = createGroup(analyticsDhisVisualization); + program.put( + analyticsDhisVisualization.scopeUid(), + Collections.singletonList(group) + ); + } else { + AnalyticsDhisVisualizationsGroup updatedGroup = updateGroup(group, analyticsDhisVisualization); + Objects.requireNonNull(program.get(analyticsDhisVisualization.scopeUid())).remove(group); + Objects.requireNonNull(program.get(analyticsDhisVisualization.scopeUid())).add(updatedGroup); + } + + break; + case DATA_SET: + group = getGroup( + analyticsDhisVisualization.groupUid(), + dataSet.get(analyticsDhisVisualization.scopeUid()) + ); + + if (group == null) { + group = createGroup(analyticsDhisVisualization); + dataSet.put( + analyticsDhisVisualization.scopeUid(), + Collections.singletonList(group) + ); + } else { + AnalyticsDhisVisualizationsGroup updatedGroup = updateGroup(group, analyticsDhisVisualization); + Objects.requireNonNull(dataSet.get(analyticsDhisVisualization.scopeUid())).remove(group); + Objects.requireNonNull(dataSet.get(analyticsDhisVisualization.scopeUid())).add(updatedGroup); + } + break; + default: + break; + } + } + + return analyticsDhisVisualizationsSettingBuilder + .home(home) + .program(program) + .dataSet(dataSet) + .build(); + } + + private AnalyticsDhisVisualizationsGroup getGroup( + String groupUid, + List groupList + ) { + if (groupList != null) { + for (AnalyticsDhisVisualizationsGroup group : groupList) { + if (group.id().equals(groupUid)) { + return group; + } + } + } + + return null; + } + + private AnalyticsDhisVisualizationsGroup createGroup(AnalyticsDhisVisualization analyticsDhisVisualization) { + return AnalyticsDhisVisualizationsGroup + .builder() + .id(analyticsDhisVisualization.groupUid()) + .name(analyticsDhisVisualization.groupName()) + .visualizations(Collections.singletonList(analyticsDhisVisualization)) + .build(); + } + + private AnalyticsDhisVisualizationsGroup updateGroup( + AnalyticsDhisVisualizationsGroup oldGroup, + AnalyticsDhisVisualization analyticsDhisVisualization + ) { + List updatedVisualizations = + new ArrayList<>(oldGroup.visualizations()); + updatedVisualizations.add(analyticsDhisVisualization); + return oldGroup + .toBuilder() + .visualizations(updatedVisualizations) + .build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettingObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettingObjectRepository.java index 45d4878319..a8eace8eb8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettingObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsSettingObjectRepository.java @@ -45,22 +45,31 @@ public class AnalyticsSettingObjectRepository private final AnalyticsTeiSettingCollectionRepository analyticsTeiSettingRepository; + private final AnalyticsDhisVisualizationsSettingObjectRepository analyticsDhisVisualizationsSettingObjectRepository; + @Inject - AnalyticsSettingObjectRepository(AnalyticsTeiSettingCollectionRepository analyticsTeiSettingRepository, - AnalyticsSettingCall analyticsSettingCall) { + AnalyticsSettingObjectRepository( + AnalyticsTeiSettingCollectionRepository analyticsTeiSettingRepository, + AnalyticsSettingCall analyticsSettingCall, + AnalyticsDhisVisualizationsSettingObjectRepository analyticsDhisVisualizationsSettingObjectRepository + ) { super(analyticsSettingCall); this.analyticsTeiSettingRepository = analyticsTeiSettingRepository; + this.analyticsDhisVisualizationsSettingObjectRepository = analyticsDhisVisualizationsSettingObjectRepository; } @Override public AnalyticsSettings blockingGet() { List analyticsTeiSettings = analyticsTeiSettingRepository.blockingGet(); + AnalyticsDhisVisualizationsSetting analyticsDhisVisualizationsSetting = + analyticsDhisVisualizationsSettingObjectRepository.blockingGet(); if (analyticsTeiSettings.isEmpty()) { return null; } else { return AnalyticsSettings.builder() .tei(analyticsTeiSettings) + .dhisVisualizations(analyticsDhisVisualizationsSetting) .build(); } } @@ -68,4 +77,8 @@ public AnalyticsSettings blockingGet() { public AnalyticsTeiSettingCollectionRepository teis() { return analyticsTeiSettingRepository; } + + public AnalyticsDhisVisualizationsSettingObjectRepository visualizationsSettings() { + return analyticsDhisVisualizationsSettingObjectRepository; + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt index 1120297dd4..c2ea345bad 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingEntityDIModule.kt @@ -136,6 +136,6 @@ internal class AnalyticsSettingEntityDIModule { @Reusable fun teiChildrenAppenders(dataChildrenAppender: AnalyticsTeiDataChildrenAppender): Map> { - return mapOf(AnalyticsTeiDataChildrenAppender.KEY to dataChildrenAppender) - } + return mapOf(AnalyticsTeiDataChildrenAppender.KEY to dataChildrenAppender) + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt index 634b831c0f..5dddd3c79f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingsAppHelper.kt @@ -53,6 +53,7 @@ import org.hisp.dhis.android.core.settings.ProgramSetting import org.hisp.dhis.android.core.settings.ProgramSettings import org.hisp.dhis.android.core.settings.WHONutritionComponent +@Suppress("TooManyFunctions") internal object SettingsAppHelper { fun getDataSetSettingList(dataSetSettings: DataSetSettings): List { From 11c38d45e2cee609c2202a415be86a41dc017242 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 13 Jul 2021 10:49:32 +0200 Subject: [PATCH 159/308] [ANDROSDK-1387] Implement filter by categoryOption --- .../DataElementEvaluatorIntegrationShould.kt | 88 ++++++++++++++++--- .../evaluator/DataElementEvaluatorSamples.kt | 28 +++++- .../evaluator/AnalyticsEvaluatorHelper.kt | 22 +++++ .../service/evaluator/DataElementEvaluator.kt | 17 +++- .../internal/IdentifiableObjectStore.kt | 2 +- .../core/arch/db/stores/internal/LinkStore.kt | 2 +- ...java => CategoryCategoryComboLinkStore.kt} | 42 ++++----- ...ava => CategoryCategoryOptionLinkStore.kt} | 45 +++++----- ...yComboStore.java => CategoryComboStore.kt} | 56 ++++++------ ...goryOptionComboCategoryOptionLinkStore.kt} | 41 +++++---- ...Store.java => CategoryOptionComboStore.kt} | 16 ++-- ...l.java => CategoryOptionComboStoreImpl.kt} | 77 ++++++++-------- ...ptionStore.java => CategoryOptionStore.kt} | 51 +++++------ .../{CategoryStore.java => CategoryStore.kt} | 46 +++++----- .../android/core/systeminfo/DHISVersion.java | 8 +- 15 files changed, 326 insertions(+), 215 deletions(-) rename core/src/androidTest/java/org/hisp/dhis/android/core/analytics/{eventlinelist => }/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt (68%) rename core/src/androidTest/java/org/hisp/dhis/android/core/analytics/{eventlinelist => }/aggregated/service/evaluator/DataElementEvaluatorSamples.kt (83%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryCategoryComboLinkStore.java => CategoryCategoryComboLinkStore.kt} (70%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryCategoryOptionLinkStore.java => CategoryCategoryOptionLinkStore.kt} (69%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryComboStore.java => CategoryComboStore.kt} (69%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryOptionComboCategoryOptionLinkStore.java => CategoryOptionComboCategoryOptionLinkStore.kt} (68%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryOptionComboStore.java => CategoryOptionComboStore.kt} (82%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryOptionComboStoreImpl.java => CategoryOptionComboStoreImpl.kt} (54%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryOptionStore.java => CategoryOptionStore.kt} (68%) rename core/src/main/java/org/hisp/dhis/android/core/category/internal/{CategoryStore.java => CategoryStore.kt} (69%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt similarity index 68% rename from core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt rename to core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt index ae14ea220a..8aaa619a03 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -25,25 +25,28 @@ * (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.analytics.eventlinelist.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator import com.google.common.truth.Truth.assertThat import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCombo -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionCombo -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement1 -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement2 -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodDec -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodNov -import org.hisp.dhis.android.core.analytics.eventlinelist.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ4 -import org.hisp.dhis.android.core.category.internal.CategoryComboStore -import org.hisp.dhis.android.core.category.internal.CategoryOptionComboStoreImpl +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.category +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCategoryComboLink +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCategoryOptionLink +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCombo +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOption +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionCombo +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionComboCategoryOptionLink +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement1 +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement2 +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodDec +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodNov +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ4 +import org.hisp.dhis.android.core.category.internal.* import org.hisp.dhis.android.core.common.RelativePeriod import org.hisp.dhis.android.core.dataelement.internal.DataElementStore import org.hisp.dhis.android.core.datavalue.DataValue @@ -68,8 +71,15 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat // Stores private val dataValueStore = DataValueStore.create(databaseAdapter) + private val categoryStore = CategoryStore.create(databaseAdapter) + private val categoryOptionStore = CategoryOptionStore.create(databaseAdapter) + private val categoryCategoryOptionStore = CategoryCategoryOptionLinkStore.create(databaseAdapter) private val categoryComboStore = CategoryComboStore.create(databaseAdapter) private val categoryOptionComboStore = CategoryOptionComboStoreImpl.create(databaseAdapter) + private val categoryCategoryComboLinkStore = CategoryCategoryComboLinkStore.create(databaseAdapter) + private val categoryOptionComboCategoryOptionLinkStore = CategoryOptionComboCategoryOptionLinkStore.create( + databaseAdapter + ) private val dataElementStore = DataElementStore.create(databaseAdapter) private val organisationUnitStore = OrganisationUnitStore.create(databaseAdapter) private val periodStore = PeriodStoreImpl.create(databaseAdapter) @@ -93,8 +103,13 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat organisationUnitStore.insert(orgunitChild1) organisationUnitStore.insert(orgunitChild2) + categoryStore.insert(category) + categoryOptionStore.insert(categoryOption) + categoryCategoryOptionStore.insert(categoryCategoryOptionLink) categoryComboStore.insert(categoryCombo) categoryOptionComboStore.insert(categoryOptionCombo) + categoryCategoryComboLinkStore.insert(categoryCategoryComboLink) + categoryOptionComboCategoryOptionLinkStore.insert(categoryOptionComboCategoryOptionLink) dataElementStore.insert(dataElement1) dataElementStore.insert(dataElement2) @@ -107,8 +122,13 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat @After fun tearDown() { organisationUnitStore.delete() + categoryStore.delete() + categoryOptionStore.delete() + categoryCategoryOptionStore.delete() categoryComboStore.delete() categoryOptionComboStore.delete() + categoryCategoryComboLinkStore.delete() + categoryOptionComboCategoryOptionLinkStore.delete() dataElementStore.delete() periodStore.delete() dataValueStore.delete() @@ -217,6 +237,46 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat assertThat(value).isEqualTo("2.5") } + @Test + fun should_disaggregate_by_category_option() { + createDataValue("2") + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), + DimensionItem.CategoryItem(category.uid(), categoryOption.uid()) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("2") + } + + @Test + fun should_ignore_missing_category_option() { + createDataValue("2") + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), + DimensionItem.CategoryItem(category.uid(), categoryOption = "non-existing-co") + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isNull() + } + private fun createDataValue( value: String, dataElementUid: String = dataElement1.uid(), diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt similarity index 83% rename from core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt rename to core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt index d59b9cb500..a230d6912f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/eventlinelist/aggregated/service/evaluator/DataElementEvaluatorSamples.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt @@ -25,12 +25,11 @@ * (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.analytics.eventlinelist.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator import org.hisp.dhis.android.core.arch.helpers.DateUtils import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl -import org.hisp.dhis.android.core.category.CategoryCombo -import org.hisp.dhis.android.core.category.CategoryOptionCombo +import org.hisp.dhis.android.core.category.* import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.common.ValueType @@ -72,6 +71,19 @@ object DataElementEvaluatorSamples { .build() } + val category: Category = Category.builder() + .uid(generator.generate()) + .build() + + val categoryOption: CategoryOption = CategoryOption.builder() + .uid(generator.generate()) + .build() + + val categoryCategoryOptionLink: CategoryCategoryOptionLink = CategoryCategoryOptionLink.builder() + .category(category.uid()) + .categoryOption(categoryOption.uid()) + .build() + val categoryCombo: CategoryCombo = CategoryCombo.builder() .uid(generator.generate()) .build() @@ -81,6 +93,16 @@ object DataElementEvaluatorSamples { .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) .build() + val categoryCategoryComboLink: CategoryCategoryComboLink = CategoryCategoryComboLink.builder() + .category(category.uid()) + .categoryCombo(categoryCombo.uid()) + .build() + + val categoryOptionComboCategoryOptionLink = CategoryOptionComboCategoryOptionLink.builder() + .categoryOption(categoryOption.uid()) + .categoryOptionCombo(categoryOptionCombo.uid()) + .build() + val dataElement1 = DataElement.builder() .uid(generator.generate()) .displayName("Data element 1") diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt index 25b8d61faa..314fb5ac4f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -29,6 +29,9 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator import org.hisp.dhis.android.core.arch.helpers.DateUtils +import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo as cToCcInfo +import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLinkTableInfo as cocToCoInfo +import org.hisp.dhis.android.core.category.CategoryOptionComboTableInfo as cocInfo import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo import org.hisp.dhis.android.core.period.Period @@ -74,6 +77,25 @@ internal object AnalyticsEvaluatorHelper { "${OrganisationUnitTableInfo.Columns.LEVEL} = $level" } + fun getCategoryOptionClause(categoryUid: String, categoryOptionUid: String): String { + return "SELECT ${cocInfo.Columns.UID} " + + "FROM ${cocInfo.TABLE_INFO.name()} " + + "WHERE " + + "${cocInfo.Columns.UID} IN " + + "(" + + "SELECT ${cocToCoInfo.Columns.CATEGORY_OPTION_COMBO} " + + "FROM ${cocToCoInfo.TABLE_INFO.name()} " + + "WHERE ${cocToCoInfo.Columns.CATEGORY_OPTION} = '${categoryOptionUid}'" + + ") " + + "AND " + + "${cocInfo.Columns.CATEGORY_COMBO} IN " + + "(" + + "SELECT ${cToCcInfo.Columns.CATEGORY_COMBO} " + + "FROM ${cToCcInfo.TABLE_INFO.name()} " + + "WHERE ${cToCcInfo.Columns.CATEGORY} = '${categoryUid}'" + + ") " + } + fun getDataElementAggregator(aggregationType: String?): String { return when (aggregationType?.let { AggregationType.valueOf(it) } ?: AggregationType.SUM) { AggregationType.SUM -> Sum diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index 6ebccb92ee..48f1565d75 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -59,7 +59,7 @@ internal class DataElementEvaluator @Inject constructor( is Dimension.Data -> appendDataWhereClause(entry.value, builder) is Dimension.Period -> appendPeriodWhereClause(entry.value, builder, metadata) is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder) - is Dimension.Category -> TODO() + is Dimension.Category -> appendCategoryWhereClause(entry.value, builder) is Dimension.CategoryOptionGroupSet -> TODO() } } @@ -148,6 +148,21 @@ internal class DataElementEvaluator @Inject constructor( return builder.appendComplexQuery(innerClause) } + private fun appendCategoryWhereClause( + items: List, + builder: WhereClauseBuilder + ): WhereClauseBuilder { + val innerClause = items.map { it as DimensionItem.CategoryItem } + .foldRight(WhereClauseBuilder()) { item, innerBuilder -> + innerBuilder.appendOrInSubQuery( + DataValueTableInfo.Columns.CATEGORY_OPTION_COMBO, + AnalyticsEvaluatorHelper.getCategoryOptionClause(item.uid, item.categoryOption) + ) + }.build() + + return builder.appendComplexQuery(innerClause) + } + private fun getAggregator( evaluationItem: AnalyticsServiceEvaluationItem, metadata: Map diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt index 50fea8e8ee..b8195823c0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt @@ -29,7 +29,7 @@ package org.hisp.dhis.android.core.arch.db.stores.internal import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.ObjectWithUidInterface -internal interface IdentifiableObjectStore : ObjectStore { +interface IdentifiableObjectStore : ObjectStore { @Throws(RuntimeException::class) fun delete(uid: String) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt index 9392f619a6..2856fa6fec 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt @@ -29,7 +29,7 @@ package org.hisp.dhis.android.core.arch.db.stores.internal import org.hisp.dhis.android.core.common.CoreObject -internal interface LinkStore : ObjectStore { +interface LinkStore : ObjectStore { @Throws(RuntimeException::class) fun deleteLinksForMasterUid(masterUid: String) fun deleteAllLinks(): Int diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt similarity index 70% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt index 6f82b69244..2abfce19c3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt @@ -25,30 +25,30 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +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.internal.LinkStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.linkStore +import org.hisp.dhis.android.core.category.CategoryCategoryComboLink +import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo +internal object CategoryCategoryComboLinkStore { -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; -import org.hisp.dhis.android.core.category.CategoryCategoryComboLink; -import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo; - -final class CategoryCategoryComboLinkStore { - - private static final StatementBinder BINDER = (o, w) -> { - w.bind(1, o.category()); - w.bind(2, o.categoryCombo()); - w.bind(3, o.sortOrder()); - }; - - private CategoryCategoryComboLinkStore() {} + private val BINDER = StatementBinder { o: CategoryCategoryComboLink, w: StatementWrapper -> + w.bind(1, o.category()) + w.bind(2, o.categoryCombo()) + w.bind(3, o.sortOrder()) + } - public static LinkStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.linkStore(databaseAdapter, CategoryCategoryComboLinkTableInfo.TABLE_INFO, - CategoryCategoryComboLinkTableInfo.Columns.CATEGORY_COMBO, BINDER, - CategoryCategoryComboLink::create); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): LinkStore { + return linkStore( + databaseAdapter, CategoryCategoryComboLinkTableInfo.TABLE_INFO, + CategoryCategoryComboLinkTableInfo.Columns.CATEGORY_COMBO, BINDER + ) { cursor: Cursor -> CategoryCategoryComboLink.create(cursor) } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt similarity index 69% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt index 690df1b9e6..74cb567a5b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt @@ -25,31 +25,32 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +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.internal.LinkStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.linkStore +import org.hisp.dhis.android.core.category.CategoryCategoryOptionLink +import org.hisp.dhis.android.core.category.CategoryCategoryOptionLinkTableInfo -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; -import org.hisp.dhis.android.core.category.CategoryCategoryOptionLink; -import org.hisp.dhis.android.core.category.CategoryCategoryOptionLinkTableInfo; +internal object CategoryCategoryOptionLinkStore { -final class CategoryCategoryOptionLinkStore { - - private static final StatementBinder BINDER = (o, w) -> { - w.bind(1, o.category()); - w.bind(2, o.categoryOption()); - w.bind(3, o.sortOrder()); - }; - - private CategoryCategoryOptionLinkStore() {} + private val BINDER = StatementBinder { o: CategoryCategoryOptionLink, w: StatementWrapper -> + w.bind(1, o.category()) + w.bind(2, o.categoryOption()) + w.bind(3, o.sortOrder()) + } - public static LinkStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.linkStore(databaseAdapter, - CategoryCategoryOptionLinkTableInfo.TABLE_INFO, - CategoryCategoryOptionLinkTableInfo.Columns.CATEGORY, - BINDER, - CategoryCategoryOptionLink::create); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): LinkStore { + return linkStore( + databaseAdapter, + CategoryCategoryOptionLinkTableInfo.TABLE_INFO, + CategoryCategoryOptionLinkTableInfo.Columns.CATEGORY, + BINDER + ) { cursor: Cursor -> CategoryCategoryOptionLink.create(cursor) } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt similarity index 69% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt index 6f88f7c6b7..beed0254b6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt @@ -25,35 +25,33 @@ * (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.category.internal; - - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder; -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.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; -import org.hisp.dhis.android.core.category.CategoryCombo; -import org.hisp.dhis.android.core.category.CategoryComboTableInfo; - -import androidx.annotation.NonNull; - -public final class CategoryComboStore { - - private CategoryComboStore() {} - - private static StatementBinder BINDER = new IdentifiableStatementBinder() { - @Override - public void bindToStatement(@NonNull CategoryCombo o, @NonNull StatementWrapper w) { - super.bindToStatement(o, w); - w.bind(7, o.isDefault()); +package org.hisp.dhis.android.core.category.internal + +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder +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.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithUidStore +import org.hisp.dhis.android.core.category.CategoryCombo +import org.hisp.dhis.android.core.category.CategoryComboTableInfo + +internal object CategoryComboStore { + + private val BINDER: StatementBinder = object : IdentifiableStatementBinder() { + override fun bindToStatement(o: CategoryCombo, w: StatementWrapper) { + super.bindToStatement(o, w) + w.bind(7, o.isDefault) } - }; + } - public static IdentifiableObjectStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.objectWithUidStore(databaseAdapter, CategoryComboTableInfo.TABLE_INFO, BINDER, - CategoryCombo::create); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return objectWithUidStore( + databaseAdapter, + CategoryComboTableInfo.TABLE_INFO, + BINDER + ) { cursor: Cursor -> CategoryCombo.create(cursor) } } -} +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt similarity index 68% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt index 5293c0f323..f906caae9b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt @@ -25,30 +25,29 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +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.internal.LinkStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.linkStore +import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLink +import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLinkTableInfo +internal object CategoryOptionComboCategoryOptionLinkStore { -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; -import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLink; -import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLinkTableInfo; - -final class CategoryOptionComboCategoryOptionLinkStore { - - private static final StatementBinder BINDER = (o, w) -> { - w.bind(1, o.categoryOptionCombo()); - w.bind(2, o.categoryOption()); - }; - - private CategoryOptionComboCategoryOptionLinkStore() {} + private val BINDER = StatementBinder { o: CategoryOptionComboCategoryOptionLink, w: StatementWrapper -> + w.bind(1, o.categoryOptionCombo()) + w.bind(2, o.categoryOption()) + } - public static LinkStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.linkStore(databaseAdapter, CategoryOptionComboCategoryOptionLinkTableInfo.TABLE_INFO, - CategoryOptionComboCategoryOptionLinkTableInfo.Columns.CATEGORY_OPTION_COMBO, BINDER, - CategoryOptionComboCategoryOptionLink::create - ); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): LinkStore { + return linkStore( + databaseAdapter, CategoryOptionComboCategoryOptionLinkTableInfo.TABLE_INFO, + CategoryOptionComboCategoryOptionLinkTableInfo.Columns.CATEGORY_OPTION_COMBO, BINDER + ) { cursor: Cursor -> CategoryOptionComboCategoryOptionLink.create(cursor) } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt similarity index 82% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt index a135007191..abaf309706 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt @@ -25,15 +25,11 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.category.CategoryOptionCombo - -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.category.CategoryOptionCombo; - -import java.util.List; - -public interface CategoryOptionComboStore extends IdentifiableObjectStore { - List getForCategoryCombo(String categoryComboUid); -} +internal interface CategoryOptionComboStore : IdentifiableObjectStore { + fun getForCategoryCombo(categoryComboUid: String): List +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt similarity index 54% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt index 67d2335be0..3cc81e9cfe 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt @@ -25,52 +25,49 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder +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.internal.IdentifiableObjectStoreImpl +import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidOrNull +import org.hisp.dhis.android.core.category.CategoryOptionCombo +import org.hisp.dhis.android.core.category.CategoryOptionComboTableInfo -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder; -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.internal.IdentifiableObjectStoreImpl; -import org.hisp.dhis.android.core.arch.helpers.UidsHelper; -import org.hisp.dhis.android.core.category.CategoryOptionCombo; -import org.hisp.dhis.android.core.category.CategoryOptionComboTableInfo; +internal class CategoryOptionComboStoreImpl private constructor( + databaseAdapter: DatabaseAdapter, + statementBuilder: SQLStatementBuilderImpl +) : IdentifiableObjectStoreImpl( + databaseAdapter, + statementBuilder, + BINDER, + { cursor: Cursor -> CategoryOptionCombo.create(cursor) }), CategoryOptionComboStore { -import java.util.List; - -import androidx.annotation.NonNull; - -public final class CategoryOptionComboStoreImpl extends IdentifiableObjectStoreImpl - implements CategoryOptionComboStore { - - private CategoryOptionComboStoreImpl(DatabaseAdapter databaseAdapter, - SQLStatementBuilderImpl statementBuilder) { - super(databaseAdapter, statementBuilder, BINDER, CategoryOptionCombo::create); + override fun getForCategoryCombo(categoryComboUid: String): List { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(CategoryOptionComboTableInfo.Columns.CATEGORY_COMBO, categoryComboUid) + .build() + return selectWhere(whereClause) } - @Override - public List getForCategoryCombo(String categoryComboUid) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(CategoryOptionComboTableInfo.Columns.CATEGORY_COMBO, categoryComboUid) - .build(); - return selectWhere(whereClause); - } - - private static StatementBinder BINDER - = new IdentifiableStatementBinder() { + companion object { + private val BINDER: StatementBinder = + object : IdentifiableStatementBinder() { + override fun bindToStatement(o: CategoryOptionCombo, w: StatementWrapper) { + super.bindToStatement(o, w) + w.bind(7, getUidOrNull(o.categoryCombo())) + } + } - @Override - public void bindToStatement(@NonNull CategoryOptionCombo o, @NonNull StatementWrapper w) { - super.bindToStatement(o, w); - w.bind(7, UidsHelper.getUidOrNull(o.categoryCombo())); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): CategoryOptionComboStore { + val statementBuilder = SQLStatementBuilderImpl(CategoryOptionComboTableInfo.TABLE_INFO) + return CategoryOptionComboStoreImpl(databaseAdapter, statementBuilder) } - }; - - public static CategoryOptionComboStore create(DatabaseAdapter databaseAdapter) { - SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl(CategoryOptionComboTableInfo.TABLE_INFO); - return new CategoryOptionComboStoreImpl(databaseAdapter, statementBuilder); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt similarity index 68% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt index 2bba23c6e4..b9f78338fe 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt @@ -25,37 +25,34 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.NameableStatementBinder +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.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithUidStore +import org.hisp.dhis.android.core.category.CategoryOption +import org.hisp.dhis.android.core.category.CategoryOptionTableInfo -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.NameableStatementBinder; -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.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; -import org.hisp.dhis.android.core.category.CategoryOption; -import org.hisp.dhis.android.core.category.CategoryOptionTableInfo; +internal object CategoryOptionStore { -import androidx.annotation.NonNull; - -final class CategoryOptionStore { - - private CategoryOptionStore() { - } - - private static StatementBinder BINDER = new NameableStatementBinder() { - @Override - public void bindToStatement(@NonNull CategoryOption o, @NonNull StatementWrapper w) { - super.bindToStatement(o, w); - w.bind(11, o.startDate()); - w.bind(12, o.endDate()); - w.bind(13, o.access().data().write()); + private val BINDER: StatementBinder = object : NameableStatementBinder() { + override fun bindToStatement(o: CategoryOption, w: StatementWrapper) { + super.bindToStatement(o, w) + w.bind(11, o.startDate()) + w.bind(12, o.endDate()) + w.bind(13, o.access().data().write()) } - }; + } - public static IdentifiableObjectStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.objectWithUidStore(databaseAdapter, - CategoryOptionTableInfo.TABLE_INFO, BINDER, CategoryOption::create); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return objectWithUidStore( + databaseAdapter, + CategoryOptionTableInfo.TABLE_INFO, BINDER + ) { cursor: Cursor -> CategoryOption.create(cursor) } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.java b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt similarity index 69% rename from core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.java rename to core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt index 52bf03af27..de449c16fa 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt @@ -25,33 +25,33 @@ * (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.category.internal -package org.hisp.dhis.android.core.category.internal; +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder +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.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithUidStore +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.category.CategoryTableInfo -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.IdentifiableStatementBinder; -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.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory; -import org.hisp.dhis.android.core.category.Category; -import org.hisp.dhis.android.core.category.CategoryTableInfo; +internal object CategoryStore { -import androidx.annotation.NonNull; - -final class CategoryStore { - - private CategoryStore() {} - - private static StatementBinder BINDER = new IdentifiableStatementBinder() { - @Override - public void bindToStatement(@NonNull Category o, @NonNull StatementWrapper w) { - super.bindToStatement(o, w); - w.bind(7, o.dataDimensionType()); + private val BINDER: StatementBinder = object : IdentifiableStatementBinder() { + override fun bindToStatement(o: Category, w: StatementWrapper) { + super.bindToStatement(o, w) + w.bind(7, o.dataDimensionType()) } - }; + } - public static IdentifiableObjectStore create(DatabaseAdapter databaseAdapter) { - return StoreFactory.objectWithUidStore(databaseAdapter, CategoryTableInfo.TABLE_INFO, BINDER, Category::create); + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return objectWithUidStore( + databaseAdapter, + CategoryTableInfo.TABLE_INFO, + BINDER + ) { cursor: Cursor -> Category.create(cursor) } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java index bbf13f961f..a12794dbbb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java @@ -36,7 +36,8 @@ public enum DHISVersion { V2_33, V2_34, V2_35, - V2_36; + V2_36, + V2_37; private static final String V2_29_STR = "2.29"; private static final String V2_30_STR = "2.30"; @@ -46,6 +47,7 @@ public enum DHISVersion { private static final String V2_34_STR = "2.34"; private static final String V2_35_STR = "2.35"; private static final String V2_36_STR = "2.36"; + private static final String V2_37_STR = "2.37"; public static DHISVersion getValue(String versionStr) { if (versionStr.startsWith(V2_29_STR)) { @@ -64,6 +66,8 @@ public static DHISVersion getValue(String versionStr) { return V2_35; } else if (versionStr.startsWith(V2_36_STR)) { return V2_36; + } else if (versionStr.startsWith(V2_37_STR)) { + return V2_37; } else { return null; } @@ -74,6 +78,6 @@ public static boolean isAllowedVersion(String versionStr) { } public static String[] allowedVersionsAsStr() { - return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, V2_36_STR}; + return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, V2_36_STR, V2_37_STR}; } } \ No newline at end of file From 83e36604582a0aa429c4a5305990a4acce41e1fe Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 13 Jul 2021 11:37:04 +0200 Subject: [PATCH 160/308] [ANDROSDK-1387] Implement dataElementOperand evaluation --- .../DataElementEvaluatorIntegrationShould.kt | 21 +++++++++++++++++++ .../evaluator/DataElementEvaluatorSamples.kt | 7 +++++++ .../analytics/aggregated/AnalyticsModel.kt | 4 +++- .../service/AnalyticsServiceMetadataHelper.kt | 2 +- .../service/evaluator/DataElementEvaluator.kt | 15 ++++++++++++- .../internal/IdentifiableObjectStore.kt | 2 +- .../core/arch/db/stores/internal/LinkStore.kt | 2 +- 7 files changed, 48 insertions(+), 5 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt index 8aaa619a03..732d65f071 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -40,6 +40,7 @@ import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataEle import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionComboCategoryOptionLink import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement1 import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement2 +import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElementOperand import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent @@ -90,6 +91,7 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat orgunitChild2.uid() to MetadataItem.OrganisationUnitItem(orgunitChild2), dataElement1.uid() to MetadataItem.DataElementItem(dataElement1), dataElement2.uid() to MetadataItem.DataElementItem(dataElement2), + dataElementOperand.uid()!! to MetadataItem.DataElementOperandItem(dataElementOperand), periodNov.periodId()!! to MetadataItem.PeriodItem(periodNov), periodDec.periodId()!! to MetadataItem.PeriodItem(periodDec), periodQ4.periodId()!! to MetadataItem.PeriodItem(periodQ4) @@ -277,6 +279,25 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat assertThat(value).isNull() } + @Test + fun should_evaluate_data_element_operand() { + createDataValue("2") + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementOperandItem(dataElement1.uid(), categoryOptionCombo.uid()) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("2") + } + private fun createDataValue( value: String, dataElementUid: String = dataElement1.uid(), diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt index a230d6912f..15a3367e96 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.common.ValueType import org.hisp.dhis.android.core.dataelement.DataElement +import org.hisp.dhis.android.core.dataelement.DataElementOperand import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.period.Period import org.hisp.dhis.android.core.period.PeriodType @@ -119,6 +120,12 @@ object DataElementEvaluatorSamples { .categoryCombo(ObjectWithUid.fromIdentifiable(categoryCombo)) .build() + val dataElementOperand = DataElementOperand.builder() + .uid("${dataElement1.uid()}.${categoryOptionCombo.uid()}") + .dataElement(ObjectWithUid.create(dataElement1.uid())) + .categoryOptionCombo(ObjectWithUid.create(categoryOptionCombo.uid())) + .build() + val periodNov: Period = Period.builder() .periodId("201911") .periodType(PeriodType.Monthly) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index b6da3f4470..857559d352 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -73,7 +73,9 @@ sealed class Dimension { sealed class DimensionItem(val dimension: Dimension, val id: String) { sealed class DataItem(id: String) : DimensionItem(Dimension.Data, id), AbsoluteDimensionItem { data class DataElementItem(val uid: String) : DataItem(uid) - data class DataElementOperandItem(val uid: String, val categoryOptionCombo: String) : DataItem(uid) + data class DataElementOperandItem(val dataElement: String, val categoryOptionCombo: String) : + DataItem("$dataElement.$categoryOptionCombo") + data class IndicatorItem(val uid: String) : DataItem(uid) data class ProgramIndicatorItem(val uid: String) : DataItem(uid) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt index c7c6518028..f855960770 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -83,7 +83,7 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( is DimensionItem.DataItem.DataElementItem -> dataElementStore.selectByUid(item.uid)!! .let { dataElement -> MetadataItem.DataElementItem(dataElement) } // TODO Build a meaningful name for DataElementOperand - is DimensionItem.DataItem.DataElementOperandItem -> dataElementOperandStore.selectByUid(item.uid)!! + is DimensionItem.DataItem.DataElementOperandItem -> dataElementOperandStore.selectByUid(item.id)!! .let { dataElementOperand -> MetadataItem.DataElementOperandItem(dataElementOperand) } is DimensionItem.DataItem.IndicatorItem -> indicatorStore.selectByUid(item.uid)!! .let { indicator -> MetadataItem.IndicatorItem(indicator) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index 48f1565d75..6b39ac087d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -88,6 +88,16 @@ internal class DataElementEvaluator @Inject constructor( when (item) { is DimensionItem.DataItem.DataElementItem -> innerBuilder.appendOrKeyStringValue(DataValueTableInfo.Columns.DATA_ELEMENT, item.uid) + is DimensionItem.DataItem.DataElementOperandItem -> { + val operandClause = WhereClauseBuilder() + .appendKeyStringValue(DataValueTableInfo.Columns.DATA_ELEMENT, item.dataElement) + .appendKeyStringValue( + DataValueTableInfo.Columns.CATEGORY_OPTION_COMBO, + item.categoryOptionCombo + ) + .build() + innerBuilder.appendOrComplexQuery(operandClause) + } else -> TODO() } }.build() @@ -181,7 +191,10 @@ internal class DataElementEvaluator @Inject constructor( val item = metadata[dataItemList.first().id] val aggregationType = when (item) { is MetadataItem.DataElementItem -> item.item.aggregationType() - is MetadataItem.DataElementOperandItem -> item.item.dataElement()?.uid() + is MetadataItem.DataElementOperandItem -> + metadata[item.item.dataElement()?.uid()]?.let { + (it as MetadataItem.DataElementItem).item.aggregationType() + } else -> throw RuntimeException("Invalid arguments: dimension is not dataelement or operand.") } AnalyticsEvaluatorHelper.getDataElementAggregator(aggregationType) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt index b8195823c0..50fea8e8ee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt @@ -29,7 +29,7 @@ package org.hisp.dhis.android.core.arch.db.stores.internal import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.ObjectWithUidInterface -interface IdentifiableObjectStore : ObjectStore { +internal interface IdentifiableObjectStore : ObjectStore { @Throws(RuntimeException::class) fun delete(uid: String) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt index 2856fa6fec..9392f619a6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/LinkStore.kt @@ -29,7 +29,7 @@ package org.hisp.dhis.android.core.arch.db.stores.internal import org.hisp.dhis.android.core.common.CoreObject -interface LinkStore : ObjectStore { +internal interface LinkStore : ObjectStore { @Throws(RuntimeException::class) fun deleteLinksForMasterUid(masterUid: String) fun deleteAllLinks(): Int From 008b97baded6b509793024fc87d1f56df9315f28 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 13 Jul 2021 14:00:42 +0200 Subject: [PATCH 161/308] [ANDROSDK-1387] Implement relative orgunit evaluation --- .../DataElementEvaluatorIntegrationShould.kt | 51 ++++++++++- ...eObjectStoreAbstractIntegrationShould.java | 10 +++ .../aggregated/AggregatedEntityDIModule.kt | 7 ++ .../analytics/aggregated/AnalyticsModel.kt | 5 +- .../AnalyticsOrganisationUnitHelper.kt | 86 +++++++++++++++++++ .../aggregated/service/AnalyticsService.kt | 6 +- ....kt => AnalyticsServiceDimensionHelper.kt} | 25 ++---- .../service/AnalyticsServiceMetadataHelper.kt | 7 +- .../evaluator/AnalyticsEvaluatorHelper.kt | 9 ++ .../service/evaluator/DataElementEvaluator.kt | 18 +++- .../internal/IdentifiableObjectStore.kt | 3 + .../internal/IdentifiableObjectStoreImpl.kt | 6 ++ ... AnalyticsServiceDimensionHelperShould.kt} | 12 ++- .../AnalyticsServiceMetadataHelperShould.kt | 2 + 14 files changed, 212 insertions(+), 35 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/{AnalyticsServiceHelper.kt => AnalyticsServiceDimensionHelper.kt} (83%) rename core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/{AnalyticsServiceHelperShould.kt => AnalyticsServiceDimensionHelperShould.kt} (94%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt index 732d65f071..d663c3fce6 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -48,6 +48,7 @@ import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataEle import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodNov import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ4 import org.hisp.dhis.android.core.category.internal.* +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit import org.hisp.dhis.android.core.common.RelativePeriod import org.hisp.dhis.android.core.dataelement.internal.DataElementStore import org.hisp.dhis.android.core.datavalue.DataValue @@ -94,7 +95,15 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat dataElementOperand.uid()!! to MetadataItem.DataElementOperandItem(dataElementOperand), periodNov.periodId()!! to MetadataItem.PeriodItem(periodNov), periodDec.periodId()!! to MetadataItem.PeriodItem(periodDec), - periodQ4.periodId()!! to MetadataItem.PeriodItem(periodQ4) + periodQ4.periodId()!! to MetadataItem.PeriodItem(periodQ4), + RelativeOrganisationUnit.USER_ORGUNIT.name to MetadataItem.OrganisationUnitRelativeItem( + RelativeOrganisationUnit.USER_ORGUNIT, + listOf(orgunitParent) + ), + RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN.name to MetadataItem.OrganisationUnitRelativeItem( + RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN, + listOf(orgunitChild1, orgunitChild2) + ) ) @Before @@ -298,6 +307,46 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat assertThat(value).isEqualTo("2") } + @Test + fun should_evaluate_relative_user_orgunit() { + createDataValue("2", orgunitUid = orgunitChild1.uid()) + createDataValue("3", orgunitUid = orgunitChild2.uid()) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Relative(RelativeOrganisationUnit.USER_ORGUNIT), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("5") + } + + @Test + fun should_aggregate_relative_user_children_as_filter() { + createDataValue("2", orgunitUid = orgunitChild1.uid()) + createDataValue("3", orgunitUid = orgunitChild2.uid()) + + val evaluationItem = AnalyticsServiceEvaluationItem( + dimensionItems = listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()) + ), + filters = listOf( + DimensionItem.OrganisationUnitItem.Relative(RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN), + DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) + ) + ) + + val value = dataElementEvaluator.evaluate(evaluationItem, metadata) + + assertThat(value).isEqualTo("5") + } + private fun createDataValue( value: String, dataElementUid: String = dataElement1.uid(), diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/IdentifiableObjectStoreAbstractIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/IdentifiableObjectStoreAbstractIntegrationShould.java index f215023702..5d7483cbb2 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/IdentifiableObjectStoreAbstractIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/data/database/IdentifiableObjectStoreAbstractIntegrationShould.java @@ -38,6 +38,8 @@ import org.junit.Test; import java.io.IOException; +import java.util.Collections; +import java.util.List; import static com.google.common.truth.Truth.assertThat; @@ -67,6 +69,14 @@ public void insert_and_select_by_uid() { assertEqualsIgnoreId(objectFromDb); } + @Test + public void insert_and_select_by_uid_list() { + store.insert(object); + List listFromDb = store.selectByUids(Collections.singletonList(object.uid())); + assertThat(listFromDb.size()).isEqualTo(1); + assertEqualsIgnoreId(listFromDb.get(0)); + } + @Test public void select_inserted_object_uid() { store.insert(object); diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index 7406b97c1c..74639c0829 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -47,4 +47,11 @@ internal class AggregatedEntityDIModule { fun visualizations(impl: MockVisualizationsRepository): VisualizationsRepository { return impl } + + @Provides + @Reusable + fun emptyAnalyticsParams(): AnalyticsRepositoryParams { + return AnalyticsRepositoryParams(listOf(), listOf()) + } + } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index 857559d352..3ef6a060ab 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -56,7 +56,10 @@ sealed class MetadataItem(val id: String, val displayName: String) { class OrganisationUnitItem(val item: OrganisationUnit) : MetadataItem(item.uid(), item.displayName()!!) class OrganisationUnitLevelItem(val item: OrganisationUnitLevel) : MetadataItem(item.uid(), item.displayName()!!) class OrganisationUnitGroupItem(val item: OrganisationUnitGroup) : MetadataItem(item.uid(), item.displayName()!!) - class OrganisationUnitRelativeItem(val item: RelativeOrganisationUnit) : MetadataItem(item.name, item.name) + class OrganisationUnitRelativeItem( + val item: RelativeOrganisationUnit, + val organisationUnits: List + ) : MetadataItem(item.name, item.name) class PeriodItem(val item: Period) : MetadataItem(item.periodId()!!, item.periodId()!!) class RelativePeriodItem(val item: RelativePeriod) : MetadataItem(item.name, item.name) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt new file mode 100644 index 0000000000..dd153da392 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo +import org.hisp.dhis.android.core.user.internal.UserOrganisationUnitLinkStore +import javax.inject.Inject + +internal class AnalyticsOrganisationUnitHelper @Inject constructor( + private val userOrganisationUnitStore: UserOrganisationUnitLinkStore, + private val organisationUnitStore: IdentifiableObjectStore +) { + + fun getRelativeOrganisationUnits(relative: RelativeOrganisationUnit): List { + val orgunitUids = getRelativeOrganisationUnitUids(relative) + + return organisationUnitStore.selectByUids(orgunitUids) + } + + fun getRelativeOrganisationUnitUids(relative: RelativeOrganisationUnit): List { + val userOrganisationUnits = userOrganisationUnitStore.queryRootCaptureOrganisationUnitUids() + + return when (relative) { + RelativeOrganisationUnit.USER_ORGUNIT -> + userOrganisationUnits + RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN -> + queryChildrenOrganisationUnitUids(userOrganisationUnits) + RelativeOrganisationUnit.USER_ORGUNIT_GRANDCHILDREN -> + queryGrandChildrenOrganisationUnitUids(userOrganisationUnits) + } + } + + fun getOrganisationUnitUidsByLevel(level: Int): List { + val whereClause = WhereClauseBuilder() + .appendKeyNumberValue(OrganisationUnitTableInfo.Columns.LEVEL, level) + .build() + + return organisationUnitStore.selectUidsWhere(whereClause) + } + + private fun queryChildrenOrganisationUnitUids(parentUids: List): List { + return getChildrenOrganisationUnitUids(parentUids) + } + + private fun queryGrandChildrenOrganisationUnitUids(parentUids: List): List { + return getChildrenOrganisationUnitUids(queryChildrenOrganisationUnitUids(parentUids)) + } + + private fun getChildrenOrganisationUnitUids(parentUids: List): List { + val childrenClause = WhereClauseBuilder() + .appendInKeyStringValues(OrganisationUnitTableInfo.Columns.PARENT, parentUids) + .build() + + return organisationUnitStore.selectUidsWhere(childrenClause) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt index c47c65b1c6..5d9afb3a79 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt @@ -34,7 +34,7 @@ import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse import javax.inject.Inject internal class AnalyticsService @Inject constructor( - private val analyticsServiceHelper: AnalyticsServiceHelper, + private val analyticsServiceDimensionHelper: AnalyticsServiceDimensionHelper, private val analyticsServiceMetadataHelper: AnalyticsServiceMetadataHelper, private val analyticsServiceEvaluatorHelper: AnalyticsServiceEvaluatorHelper ) { @@ -48,8 +48,8 @@ internal class AnalyticsService @Inject constructor( throw RuntimeException("At least one data dimension must be specified") } - val dimensions = analyticsServiceHelper.getDimensions(params) - val evaluationItems = analyticsServiceHelper.getEvaluationItems(params, dimensions) + val dimensions = analyticsServiceDimensionHelper.getDimensions(params) + val evaluationItems = analyticsServiceDimensionHelper.getEvaluationItems(params, dimensions) val metadata = analyticsServiceMetadataHelper.getMetadata(evaluationItems) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt similarity index 83% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt index 057ba915b3..35b1c58e8c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt @@ -32,16 +32,12 @@ import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore -import org.hisp.dhis.android.core.organisationunit.OrganisationUnit -import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import javax.inject.Inject -internal class AnalyticsServiceHelper @Inject constructor( +internal class AnalyticsServiceDimensionHelper @Inject constructor( private val periodGenerator: ParentPeriodGenerator, - private val organisationUnitStore: IdentifiableObjectStore + private val analyticsOrganisationUnitHelper: AnalyticsOrganisationUnitHelper ) { fun getDimensions(params: AnalyticsRepositoryParams): Set { @@ -85,10 +81,13 @@ internal class AnalyticsServiceHelper @Inject constructor( is DimensionItem.OrganisationUnitItem -> when(item) { is DimensionItem.OrganisationUnitItem.Absolute -> listOf(item) - is DimensionItem.OrganisationUnitItem.Relative -> TODO() + is DimensionItem.OrganisationUnitItem.Relative -> + analyticsOrganisationUnitHelper.getRelativeOrganisationUnitUids(item.relative).map { + DimensionItem.OrganisationUnitItem.Absolute(it) + } is DimensionItem.OrganisationUnitItem.Level -> - queryOrgunitsByLevel(item.level).map { orgunitUid -> - DimensionItem.OrganisationUnitItem.Absolute(orgunitUid) + analyticsOrganisationUnitHelper.getOrganisationUnitUidsByLevel(item.level).map { + DimensionItem.OrganisationUnitItem.Absolute(it) } is DimensionItem.OrganisationUnitItem.Group -> TODO() } @@ -96,12 +95,4 @@ internal class AnalyticsServiceHelper @Inject constructor( is DimensionItem.CategoryOptionGroupSetItem -> listOf(item) } } - - private fun queryOrgunitsByLevel(level: Int): List { - val whereClause = WhereClauseBuilder() - .appendKeyNumberValue(OrganisationUnitTableInfo.Columns.LEVEL, level) - .build() - - return organisationUnitStore.selectUidsWhere(whereClause) - } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt index f855960770..da79a48d5b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -55,6 +55,7 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( private val organisationUnitGroupStore: IdentifiableObjectStore, private val organisationUnitLevelStore: IdentifiableObjectStore, private val programIndicatorStore: IdentifiableObjectStore, + private val analyticsOrganisationUnitHelper: AnalyticsOrganisationUnitHelper, private val periodHelper: PeriodHelper ) { @@ -103,8 +104,10 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( when (item) { is DimensionItem.OrganisationUnitItem.Absolute -> organisationUnitStore.selectByUid(item.uid)!! .let { organisationUnit -> MetadataItem.OrganisationUnitItem(organisationUnit) } - is DimensionItem.OrganisationUnitItem.Relative -> - MetadataItem.OrganisationUnitRelativeItem(item.relative) + is DimensionItem.OrganisationUnitItem.Relative -> { + val orgunitUids = analyticsOrganisationUnitHelper.getRelativeOrganisationUnits(item.relative) + MetadataItem.OrganisationUnitRelativeItem(item.relative, orgunitUids) + } is DimensionItem.OrganisationUnitItem.Level -> { val levelClauseBuilder = WhereClauseBuilder() .appendKeyNumberValue(OrganisationUnitLevelTableInfo.Columns.LEVEL, item.level) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt index 314fb5ac4f..36fc2d4fa7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -33,6 +33,8 @@ import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo as import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLinkTableInfo as cocToCoInfo import org.hisp.dhis.android.core.category.CategoryOptionComboTableInfo as cocInfo import org.hisp.dhis.android.core.common.AggregationType +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit +import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo import org.hisp.dhis.android.core.period.Period import org.hisp.dhis.android.core.period.PeriodTableInfo @@ -77,6 +79,13 @@ internal object AnalyticsEvaluatorHelper { "${OrganisationUnitTableInfo.Columns.LEVEL} = $level" } + fun getOrgunitListClause(orgunitUids: List): String { + return "SELECT ${OrganisationUnitTableInfo.Columns.UID} " + + "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + + "WHERE " + + orgunitUids.joinToString(" OR ") { "${OrganisationUnitTableInfo.Columns.PATH} LIKE '%$it%'" } + } + fun getCategoryOptionClause(categoryUid: String, categoryOptionUid: String): String { return "SELECT ${cocInfo.Columns.UID} " + "FROM ${cocInfo.TABLE_INFO.name()} " + diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index 6b39ac087d..1bf247e086 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -58,7 +58,7 @@ internal class DataElementEvaluator @Inject constructor( when (entry.key) { is Dimension.Data -> appendDataWhereClause(entry.value, builder) is Dimension.Period -> appendPeriodWhereClause(entry.value, builder, metadata) - is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder) + is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder, metadata) is Dimension.Category -> appendCategoryWhereClause(entry.value, builder) is Dimension.CategoryOptionGroupSet -> TODO() } @@ -98,7 +98,8 @@ internal class DataElementEvaluator @Inject constructor( .build() innerBuilder.appendOrComplexQuery(operandClause) } - else -> TODO() + else -> throw RuntimeException("Invalid arguments: unexpected dataItem ${item.javaClass.name} " + + "in DataElement Evaluator.") } }.build() @@ -135,7 +136,8 @@ internal class DataElementEvaluator @Inject constructor( private fun appendOrgunitWhereClause( items: List, - builder: WhereClauseBuilder + builder: WhereClauseBuilder, + metadata: Map ): WhereClauseBuilder { val innerClause = items.map { it as DimensionItem.OrganisationUnitItem } .foldRight(WhereClauseBuilder()) { item, innerBuilder -> @@ -150,7 +152,15 @@ internal class DataElementEvaluator @Inject constructor( DataValueTableInfo.Columns.ORGANISATION_UNIT, AnalyticsEvaluatorHelper.getLevelOrgunitClause(item.level) ) - is DimensionItem.OrganisationUnitItem.Relative -> TODO() + is DimensionItem.OrganisationUnitItem.Relative -> { + val metadataItem = metadata[item.id] as MetadataItem.OrganisationUnitRelativeItem + val orgunits = metadataItem.organisationUnits.map { it.uid() } + + innerBuilder.appendOrInSubQuery( + DataValueTableInfo.Columns.ORGANISATION_UNIT, + AnalyticsEvaluatorHelper.getOrgunitListClause(orgunits) + ) + } is DimensionItem.OrganisationUnitItem.Group -> TODO() } }.build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt index 50fea8e8ee..b1204aeceb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStore.kt @@ -53,4 +53,7 @@ internal interface IdentifiableObjectStore : ObjectS @Throws(RuntimeException::class) fun selectByUid(uid: String): O? + + @Throws(RuntimeException::class) + fun selectByUids(uid: List): List } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStoreImpl.kt index 9ce506345d..405b938905 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/stores/internal/IdentifiableObjectStoreImpl.kt @@ -35,6 +35,7 @@ import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapp import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper import org.hisp.dhis.android.core.common.CoreObject +import org.hisp.dhis.android.core.common.IdentifiableColumns.UID import org.hisp.dhis.android.core.common.ObjectWithUidInterface @Suppress("TooManyFunctions") @@ -145,6 +146,11 @@ internal open class IdentifiableObjectStoreImpl( return mapObjectFromCursor(cursor) } + @Throws(RuntimeException::class) + override fun selectByUids(uid: List): List { + return selectWhere("$UID IN (${uid.joinToString(",") { "'$it'" }})") + } + private fun mapObjectFromCursor(cursor: Cursor): O? { cursor.use { c -> if (c.count > 0) { diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt similarity index 94% rename from core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt rename to core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt index 16fd48834c..4ca2651150 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt @@ -37,23 +37,21 @@ import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore -import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.period.Period -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s @RunWith(JUnit4::class) -class AnalyticsServiceHelperShould { +class AnalyticsServiceDimensionHelperShould { private val periodGenerator: ParentPeriodGenerator = mock() - private val organisationUnitStore: IdentifiableObjectStore = mock() + private val organisationUnitHelper: AnalyticsOrganisationUnitHelper = mock() - private val helper = AnalyticsServiceHelper(periodGenerator, organisationUnitStore) + private val helper = AnalyticsServiceDimensionHelper(periodGenerator, organisationUnitHelper) @Test fun `Should extract unique dimension values`() { @@ -168,7 +166,7 @@ class AnalyticsServiceHelperShould { @Test fun `Should evaluate orgunits by level`() { - whenever(organisationUnitStore.selectUidsWhere(any())).thenReturn(listOf("orgunit1", "orgunit2", "orgunit3")) + whenever(organisationUnitHelper.getOrganisationUnitUidsByLevel(any())).thenReturn(listOf("orgunit1", "orgunit2", "orgunit3")) val params = AnalyticsRepositoryParams( dimensions = listOf( diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt index 2aac37b35c..31e2f98885 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt @@ -60,6 +60,7 @@ class AnalyticsServiceMetadataHelperShould { private val organisationUnitGroupStore: IdentifiableObjectStore = mock() private val organisationUnitLevelStore: IdentifiableObjectStore = mock() private val programIndicatorStore: IdentifiableObjectStore = mock() + private val analyticsOrganisationUnitHelper: AnalyticsOrganisationUnitHelper = mock() private val periodHelper: PeriodHelper = mock() private val helper = AnalyticsServiceMetadataHelper( @@ -72,6 +73,7 @@ class AnalyticsServiceMetadataHelperShould { organisationUnitGroupStore, organisationUnitLevelStore, programIndicatorStore, + analyticsOrganisationUnitHelper, periodHelper ) From 37a9776327ac30276c185c6e43c95722622aa654 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 13 Jul 2021 14:40:03 +0200 Subject: [PATCH 162/308] [ANDROSDK-1387] Ktlint, pmd --- .../evaluator/DataElementEvaluatorSamples.kt | 7 +- .../aggregated/AggregatedEntityDIModule.kt | 1 - .../analytics/aggregated/AnalyticsModel.kt | 3 +- .../aggregated/AnalyticsRepositoryImpl.kt | 4 +- .../aggregated/AnalyticsRepositoryParams.kt | 2 +- .../aggregated/service/AnalyticsException.kt | 33 +++++++++ .../AnalyticsOrganisationUnitHelper.kt | 2 +- .../aggregated/service/AnalyticsService.kt | 6 +- .../AnalyticsServiceDimensionHelper.kt | 8 +-- .../service/AnalyticsServiceEvaluationItem.kt | 2 +- .../AnalyticsServiceEvaluatorHelper.kt | 15 ++-- .../service/AnalyticsServiceMetadataHelper.kt | 72 ++++++++++++------- .../service/evaluator/AnalyticsEvaluator.kt | 9 +-- .../evaluator/AnalyticsEvaluatorHelper.kt | 64 ++++++++--------- .../service/evaluator/DataElementEvaluator.kt | 31 ++++---- .../CategoryCategoryComboLinkStore.kt | 3 +- .../CategoryCategoryOptionLinkStore.kt | 3 +- .../category/internal/CategoryComboStore.kt | 3 +- ...egoryOptionComboCategoryOptionLinkStore.kt | 3 +- .../internal/CategoryOptionComboStore.kt | 2 +- .../internal/CategoryOptionComboStoreImpl.kt | 7 +- .../category/internal/CategoryOptionStore.kt | 3 +- .../core/category/internal/CategoryStore.kt | 3 +- .../android/core/systeminfo/DHISVersion.java | 8 +-- .../AnalyticsServiceDimensionHelperShould.kt | 41 ++++++----- .../service/AnalyticsServiceHelperSamples.kt | 3 +- .../AnalyticsServiceMetadataHelperShould.kt | 4 +- 27 files changed, 205 insertions(+), 137 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt index 15a3367e96..d912841128 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt @@ -48,7 +48,7 @@ object DataElementEvaluatorSamples { OrganisationUnit.builder() .uid(uid) .displayName("Child 1") - .path("/${uid}") + .path("/$uid") .build() } @@ -58,7 +58,7 @@ object DataElementEvaluatorSamples { .uid(uid) .displayName("Child 1") .parent(ObjectWithUid.create(orgunitParent.uid())) - .path("/${orgunitParent.uid()}/${uid}") + .path("/${orgunitParent.uid()}/$uid") .build() } @@ -68,7 +68,7 @@ object DataElementEvaluatorSamples { .uid(uid) .displayName("Child 2") .parent(ObjectWithUid.create(orgunitParent.uid())) - .path("/${orgunitParent.uid()}/${uid}") + .path("/${orgunitParent.uid()}/$uid") .build() } @@ -146,5 +146,4 @@ object DataElementEvaluatorSamples { .startDate(DateUtils.DATE_FORMAT.parse("2019-10-01T00:00:00.000")) .endDate(DateUtils.DATE_FORMAT.parse("2021-12-31T23:59:59.999")) .build() - } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index 74639c0829..7c9ad8b85e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -53,5 +53,4 @@ internal class AggregatedEntityDIModule { fun emptyAnalyticsParams(): AnalyticsRepositoryParams { return AnalyticsRepositoryParams(listOf(), listOf()) } - } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index 3ef6a060ab..6569fa0d92 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -100,11 +100,10 @@ sealed class DimensionItem(val dimension: Dimension, val id: String) { val categoryOption: String ) : DimensionItem(Dimension.Category(uid), categoryOption), AbsoluteDimensionItem - class CategoryOptionGroupSetItem( val uid: String, val categoryOptionGroup: String ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid), categoryOptionGroup), AbsoluteDimensionItem } -internal interface AbsoluteDimensionItem \ No newline at end of file +internal interface AbsoluteDimensionItem diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt index 6e7eaffa4c..51debf51ae 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt @@ -29,8 +29,8 @@ package org.hisp.dhis.android.core.analytics.aggregated import io.reactivex.Single -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsService import javax.inject.Inject +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsService internal class AnalyticsRepositoryImpl @Inject constructor( private val params: AnalyticsRepositoryParams, @@ -49,7 +49,7 @@ internal class AnalyticsRepositoryImpl @Inject constructor( return Single.fromCallable { blockingEvaluate() } } - override fun blockingEvaluate(): DimensionalResponse { + override fun blockingEvaluate(): DimensionalResponse { return analyticsService.evaluate(params) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt index 0ef40210fa..dac86921ea 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt @@ -31,4 +31,4 @@ package org.hisp.dhis.android.core.analytics.aggregated internal data class AnalyticsRepositoryParams( val dimensions: List, val filters: List -) \ No newline at end of file +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt new file mode 100644 index 0000000000..c027166485 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +sealed class AnalyticsException(message: String) : Throwable(message) { + class InvalidArguments(message: String) : AnalyticsException(message) +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt index dd153da392..1fe19a2015 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt @@ -28,13 +28,13 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.common.RelativeOrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo import org.hisp.dhis.android.core.user.internal.UserOrganisationUnitLinkStore -import javax.inject.Inject internal class AnalyticsOrganisationUnitHelper @Inject constructor( private val userOrganisationUnitStore: UserOrganisationUnitLinkStore, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt index 5d9afb3a79..97e60749e3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse -import javax.inject.Inject internal class AnalyticsService @Inject constructor( private val analyticsServiceDimensionHelper: AnalyticsServiceDimensionHelper, @@ -41,11 +41,11 @@ internal class AnalyticsService @Inject constructor( fun evaluate(params: AnalyticsRepositoryParams): DimensionalResponse { if (params.dimensions.isEmpty()) { - throw RuntimeException("At least one dimension must be specified") + throw AnalyticsException.InvalidArguments("At least one dimension must be specified") } if ((params.dimensions + params.filters).none { it.dimension == Dimension.Data }) { - throw RuntimeException("At least one data dimension must be specified") + throw AnalyticsException.InvalidArguments("At least one data dimension must be specified") } val dimensions = analyticsServiceDimensionHelper.getDimensions(params) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt index 35b1c58e8c..349918fb7d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt @@ -28,12 +28,12 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator -import javax.inject.Inject internal class AnalyticsServiceDimensionHelper @Inject constructor( private val periodGenerator: ParentPeriodGenerator, @@ -68,10 +68,10 @@ internal class AnalyticsServiceDimensionHelper @Inject constructor( } private fun toAbsoluteDimensionItems(item: DimensionItem): List { - return when(item) { + return when (item) { is DimensionItem.DataItem -> listOf(item) is DimensionItem.PeriodItem -> - when(item) { + when (item) { is DimensionItem.PeriodItem.Absolute -> listOf(item) is DimensionItem.PeriodItem.Relative -> periodGenerator.generateRelativePeriods(item.relative).map { period -> @@ -79,7 +79,7 @@ internal class AnalyticsServiceDimensionHelper @Inject constructor( } } is DimensionItem.OrganisationUnitItem -> - when(item) { + when (item) { is DimensionItem.OrganisationUnitItem.Absolute -> listOf(item) is DimensionItem.OrganisationUnitItem.Relative -> analyticsOrganisationUnitHelper.getRelativeOrganisationUnitUids(item.relative).map { diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt index 50448cbbdc..0a272622f6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt @@ -34,4 +34,4 @@ import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem internal data class AnalyticsServiceEvaluationItem( val dimensionItems: List, val filters: List -) \ No newline at end of file +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt index 77464e06ad..55fa90eaa9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt @@ -28,13 +28,12 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.AnalyticsEvaluator import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator -import java.lang.RuntimeException -import javax.inject.Inject internal class AnalyticsServiceEvaluatorHelper @Inject constructor( private val dataElementEvaluator: DataElementEvaluator @@ -58,7 +57,8 @@ internal class AnalyticsServiceEvaluatorHelper @Inject constructor( return when (dimensionDataItems.size) { 0 -> getEvaluatorFromFilters(evaluationItem.filters) 1 -> getEvaluatorFromDataDimension(dimensionDataItems.first()) - else -> throw RuntimeException("Invalid arguments: more than one data item as dimension.") + else -> + throw AnalyticsException.InvalidArguments("Invalid arguments: more than one data item as dimension.") } } @@ -70,10 +70,15 @@ internal class AnalyticsServiceEvaluatorHelper @Inject constructor( } return when { - filterDataItems.isEmpty() -> throw RuntimeException("Invalid arguments: no data dimension is specified.") + filterDataItems.isEmpty() -> + throw AnalyticsException.InvalidArguments("Invalid arguments: no data dimension is specified.") filterDataItems.size == 1 -> getEvaluatorFromDataDimension(filterDataItems.first()) allAreDataElements -> dataElementEvaluator - else -> throw RuntimeException("Invalid arguments: Only a single indicator can be specified as filter.") + else -> + throw AnalyticsException.InvalidArguments( + "Invalid arguments: Only a single indicator " + + "can be specified as filter." + ) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt index da79a48d5b..d6b0428a6f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -43,8 +44,8 @@ import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevelTableInfo import org.hisp.dhis.android.core.period.internal.PeriodHelper import org.hisp.dhis.android.core.program.ProgramIndicator -import javax.inject.Inject +@Suppress("LongParameterList") internal class AnalyticsServiceMetadataHelper @Inject constructor( private val categoryStore: IdentifiableObjectStore, private val categoryOptionStore: IdentifiableObjectStore, @@ -63,47 +64,62 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( val metadata: MutableMap = mutableMapOf() evaluationItems.forEach { evaluationItem -> - (evaluationItem.dimensionItems + evaluationItem.filters) - .map { it as DimensionItem } - .forEach { item -> - if (!metadata.containsKey(item.id)) { - getMetadataItems(item).forEach { metadataItem -> - metadata += metadataItem.id to metadataItem - } - } - } + metadata += getMetadata(evaluationItem) } return metadata } + private fun getMetadata(evaluationItem: AnalyticsServiceEvaluationItem): Map { + val metadata: MutableMap = mutableMapOf() + + (evaluationItem.dimensionItems + evaluationItem.filters) + .map { it as DimensionItem } + .forEach { item -> + if (!metadata.containsKey(item.id)) { + val metadataItems = getMetadataItems(item).map { it.id to it }.toMap() + metadata += metadataItems + } + } + + return metadata + } + private fun getMetadataItems(item: DimensionItem): List { return when (item) { is DimensionItem.DataItem -> listOf( when (item) { - is DimensionItem.DataItem.DataElementItem -> dataElementStore.selectByUid(item.uid)!! - .let { dataElement -> MetadataItem.DataElementItem(dataElement) } + is DimensionItem.DataItem.DataElementItem -> + dataElementStore.selectByUid(item.uid)!! + .let { dataElement -> MetadataItem.DataElementItem(dataElement) } // TODO Build a meaningful name for DataElementOperand - is DimensionItem.DataItem.DataElementOperandItem -> dataElementOperandStore.selectByUid(item.id)!! - .let { dataElementOperand -> MetadataItem.DataElementOperandItem(dataElementOperand) } - is DimensionItem.DataItem.IndicatorItem -> indicatorStore.selectByUid(item.uid)!! - .let { indicator -> MetadataItem.IndicatorItem(indicator) } - is DimensionItem.DataItem.ProgramIndicatorItem -> programIndicatorStore.selectByUid(item.uid)!! - .let { programIndicator -> MetadataItem.ProgramIndicatorItem(programIndicator) } - }) + is DimensionItem.DataItem.DataElementOperandItem -> + dataElementOperandStore.selectByUid(item.id)!! + .let { dataElementOperand -> MetadataItem.DataElementOperandItem(dataElementOperand) } + is DimensionItem.DataItem.IndicatorItem -> + indicatorStore.selectByUid(item.uid)!! + .let { indicator -> MetadataItem.IndicatorItem(indicator) } + is DimensionItem.DataItem.ProgramIndicatorItem -> + programIndicatorStore.selectByUid(item.uid)!! + .let { programIndicator -> MetadataItem.ProgramIndicatorItem(programIndicator) } + } + ) is DimensionItem.PeriodItem -> listOf( when (item) { - is DimensionItem.PeriodItem.Absolute -> periodHelper.blockingGetPeriodForPeriodId(item.periodId) - .let { period -> MetadataItem.PeriodItem(period) } + is DimensionItem.PeriodItem.Absolute -> + periodHelper.blockingGetPeriodForPeriodId(item.periodId) + .let { period -> MetadataItem.PeriodItem(period) } is DimensionItem.PeriodItem.Relative -> MetadataItem.RelativePeriodItem(item.relative) - }) + } + ) is DimensionItem.OrganisationUnitItem -> listOf( when (item) { - is DimensionItem.OrganisationUnitItem.Absolute -> organisationUnitStore.selectByUid(item.uid)!! - .let { organisationUnit -> MetadataItem.OrganisationUnitItem(organisationUnit) } + is DimensionItem.OrganisationUnitItem.Absolute -> + organisationUnitStore.selectByUid(item.uid)!! + .let { organisationUnit -> MetadataItem.OrganisationUnitItem(organisationUnit) } is DimensionItem.OrganisationUnitItem.Relative -> { val orgunitUids = analyticsOrganisationUnitHelper.getRelativeOrganisationUnits(item.relative) MetadataItem.OrganisationUnitRelativeItem(item.relative, orgunitUids) @@ -115,9 +131,11 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( organisationUnitLevelStore.selectOneWhere(levelClauseBuilder)!! .let { level -> MetadataItem.OrganisationUnitLevelItem(level) } } - is DimensionItem.OrganisationUnitItem.Group -> organisationUnitGroupStore.selectByUid(item.uid)!! - .let { organisationUnitGroup -> MetadataItem.OrganisationUnitGroupItem(organisationUnitGroup) } - }) + is DimensionItem.OrganisationUnitItem.Group -> + organisationUnitGroupStore.selectByUid(item.uid)!! + .let { group -> MetadataItem.OrganisationUnitGroupItem(group) } + } + ) is DimensionItem.CategoryItem -> listOf( categoryStore.selectByUid(item.uid)!! diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt index faa7b16a8e..4982699aab 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt @@ -30,10 +30,11 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem -import javax.inject.Inject internal interface AnalyticsEvaluator { - fun evaluate(evaluationItem: AnalyticsServiceEvaluationItem, - metadata: Map): String? -} \ No newline at end of file + fun evaluate( + evaluationItem: AnalyticsServiceEvaluationItem, + metadata: Map + ): String? +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt index 36fc2d4fa7..62ef083ba8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -33,8 +33,6 @@ import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo as import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLinkTableInfo as cocToCoInfo import org.hisp.dhis.android.core.category.CategoryOptionComboTableInfo as cocInfo import org.hisp.dhis.android.core.common.AggregationType -import org.hisp.dhis.android.core.common.RelativeOrganisationUnit -import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo import org.hisp.dhis.android.core.period.Period import org.hisp.dhis.android.core.period.PeriodTableInfo @@ -49,60 +47,60 @@ internal object AnalyticsEvaluatorHelper { fun getInPeriodClause(period: Period): String { return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + - "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + - "WHERE ${getPeriodWhereClause(period)}" + "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + + "WHERE ${getPeriodWhereClause(period)}" } fun getInPeriodsClause(periods: List): String { return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + - "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + - "WHERE ${periods.joinToString(" OR ") { "(${getPeriodWhereClause(it)})" }}" + "FROM ${PeriodTableInfo.TABLE_INFO.name()} " + + "WHERE ${periods.joinToString(" OR ") { "(${getPeriodWhereClause(it)})" }}" } private fun getPeriodWhereClause(period: Period): String { return "${PeriodTableInfo.Columns.START_DATE} >= '${DateUtils.DATE_FORMAT.format(period.startDate()!!)}' " + - "AND " + - "${PeriodTableInfo.Columns.END_DATE} <= '${DateUtils.DATE_FORMAT.format(period.endDate()!!)}'" + "AND " + + "${PeriodTableInfo.Columns.END_DATE} <= '${DateUtils.DATE_FORMAT.format(period.endDate()!!)}'" } fun getOrgunitClause(orgunitUid: String): String { return "SELECT ${OrganisationUnitTableInfo.Columns.UID} " + - "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + - "WHERE " + - "${OrganisationUnitTableInfo.Columns.PATH} LIKE '%$orgunitUid%'" + "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + + "WHERE " + + "${OrganisationUnitTableInfo.Columns.PATH} LIKE '%$orgunitUid%'" } fun getLevelOrgunitClause(level: Int): String { return "SELECT ${OrganisationUnitTableInfo.Columns.UID} " + - "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + - "WHERE " + - "${OrganisationUnitTableInfo.Columns.LEVEL} = $level" + "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + + "WHERE " + + "${OrganisationUnitTableInfo.Columns.LEVEL} = $level" } fun getOrgunitListClause(orgunitUids: List): String { return "SELECT ${OrganisationUnitTableInfo.Columns.UID} " + - "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + - "WHERE " + - orgunitUids.joinToString(" OR ") { "${OrganisationUnitTableInfo.Columns.PATH} LIKE '%$it%'" } + "FROM ${OrganisationUnitTableInfo.TABLE_INFO.name()} " + + "WHERE " + + orgunitUids.joinToString(" OR ") { "${OrganisationUnitTableInfo.Columns.PATH} LIKE '%$it%'" } } fun getCategoryOptionClause(categoryUid: String, categoryOptionUid: String): String { return "SELECT ${cocInfo.Columns.UID} " + - "FROM ${cocInfo.TABLE_INFO.name()} " + - "WHERE " + - "${cocInfo.Columns.UID} IN " + - "(" + - "SELECT ${cocToCoInfo.Columns.CATEGORY_OPTION_COMBO} " + - "FROM ${cocToCoInfo.TABLE_INFO.name()} " + - "WHERE ${cocToCoInfo.Columns.CATEGORY_OPTION} = '${categoryOptionUid}'" + - ") " + - "AND " + - "${cocInfo.Columns.CATEGORY_COMBO} IN " + - "(" + - "SELECT ${cToCcInfo.Columns.CATEGORY_COMBO} " + - "FROM ${cToCcInfo.TABLE_INFO.name()} " + - "WHERE ${cToCcInfo.Columns.CATEGORY} = '${categoryUid}'" + - ") " + "FROM ${cocInfo.TABLE_INFO.name()} " + + "WHERE " + + "${cocInfo.Columns.UID} IN " + + "(" + + "SELECT ${cocToCoInfo.Columns.CATEGORY_OPTION_COMBO} " + + "FROM ${cocToCoInfo.TABLE_INFO.name()} " + + "WHERE ${cocToCoInfo.Columns.CATEGORY_OPTION} = '$categoryOptionUid'" + + ") " + + "AND " + + "${cocInfo.Columns.CATEGORY_COMBO} IN " + + "(" + + "SELECT ${cToCcInfo.Columns.CATEGORY_COMBO} " + + "FROM ${cToCcInfo.TABLE_INFO.name()} " + + "WHERE ${cToCcInfo.Columns.CATEGORY} = '$categoryUid'" + + ") " } fun getDataElementAggregator(aggregationType: String?): String { @@ -115,4 +113,4 @@ internal object AnalyticsEvaluatorHelper { else -> Sum } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index 1bf247e086..d20edf4a92 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -28,17 +28,17 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsException import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.datavalue.DataValueTableInfo import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator -import java.lang.RuntimeException -import javax.inject.Inject internal class DataElementEvaluator @Inject constructor( private val databaseAdapter: DatabaseAdapter, @@ -69,9 +69,9 @@ internal class DataElementEvaluator @Inject constructor( val aggregator = getAggregator(evaluationItem, metadata) val sqlQuery = - "SELECT ${aggregator}(${DataValueTableInfo.Columns.VALUE}) " + - "FROM ${DataValueTableInfo.TABLE_INFO.name()} " + - "WHERE $whereClause" + "SELECT $aggregator(${DataValueTableInfo.Columns.VALUE}) " + + "FROM ${DataValueTableInfo.TABLE_INFO.name()} " + + "WHERE $whereClause" return databaseAdapter.rawQuery(sqlQuery)?.use { c -> c.moveToFirst() @@ -98,8 +98,11 @@ internal class DataElementEvaluator @Inject constructor( .build() innerBuilder.appendOrComplexQuery(operandClause) } - else -> throw RuntimeException("Invalid arguments: unexpected dataItem ${item.javaClass.name} " + - "in DataElement Evaluator.") + else -> + throw AnalyticsException.InvalidArguments( + "Invalid arguments: unexpected " + + "dataItem ${item.javaClass.name} in DataElement Evaluator." + ) } }.build() @@ -183,6 +186,7 @@ internal class DataElementEvaluator @Inject constructor( return builder.appendComplexQuery(innerClause) } + @Suppress("ThrowsCount") private fun getAggregator( evaluationItem: AnalyticsServiceEvaluationItem, metadata: Map @@ -192,11 +196,12 @@ internal class DataElementEvaluator @Inject constructor( val dataItemList = when (dimensionDataItem.size) { 0 -> evaluationItem.filters.filterIsInstance() 1 -> dimensionDataItem - else -> throw RuntimeException("Invalid arguments: more than one data item as dimension.") + else -> + throw AnalyticsException.InvalidArguments("Invalid arguments: more than one data item as dimension.") } return when (dataItemList.size) { - 0 -> throw RuntimeException("Invalid arguments: no data dimension is specified.") + 0 -> throw AnalyticsException.InvalidArguments("Invalid arguments: no data dimension is specified.") 1 -> { val item = metadata[dataItemList.first().id] val aggregationType = when (item) { @@ -205,12 +210,14 @@ internal class DataElementEvaluator @Inject constructor( metadata[item.item.dataElement()?.uid()]?.let { (it as MetadataItem.DataElementItem).item.aggregationType() } - else -> throw RuntimeException("Invalid arguments: dimension is not dataelement or operand.") + else -> throw AnalyticsException.InvalidArguments( + "Invalid arguments: dimension is not " + + "dataelement or operand." + ) } AnalyticsEvaluatorHelper.getDataElementAggregator(aggregationType) } else -> AnalyticsEvaluatorHelper.getDataElementAggregator(AggregationType.SUM.name) } - } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt index 2abfce19c3..bd2ce04a1d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryComboLinkStore.kt @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.linkStore import org.hisp.dhis.android.core.category.CategoryCategoryComboLink import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo +@Suppress("MagicNumber") internal object CategoryCategoryComboLinkStore { private val BINDER = StatementBinder { o: CategoryCategoryComboLink, w: StatementWrapper -> @@ -51,4 +52,4 @@ internal object CategoryCategoryComboLinkStore { CategoryCategoryComboLinkTableInfo.Columns.CATEGORY_COMBO, BINDER ) { cursor: Cursor -> CategoryCategoryComboLink.create(cursor) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt index 74cb567a5b..4e52ddd066 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryCategoryOptionLinkStore.kt @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.linkStore import org.hisp.dhis.android.core.category.CategoryCategoryOptionLink import org.hisp.dhis.android.core.category.CategoryCategoryOptionLinkTableInfo +@Suppress("MagicNumber") internal object CategoryCategoryOptionLinkStore { private val BINDER = StatementBinder { o: CategoryCategoryOptionLink, w: StatementWrapper -> @@ -53,4 +54,4 @@ internal object CategoryCategoryOptionLinkStore { BINDER ) { cursor: Cursor -> CategoryCategoryOptionLink.create(cursor) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt index beed0254b6..b3de0c50a2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryComboStore.kt @@ -37,6 +37,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWit import org.hisp.dhis.android.core.category.CategoryCombo import org.hisp.dhis.android.core.category.CategoryComboTableInfo +@Suppress("MagicNumber") internal object CategoryComboStore { private val BINDER: StatementBinder = object : IdentifiableStatementBinder() { @@ -54,4 +55,4 @@ internal object CategoryComboStore { BINDER ) { cursor: Cursor -> CategoryCombo.create(cursor) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt index f906caae9b..341b619a1a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboCategoryOptionLinkStore.kt @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.linkStore import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLink import org.hisp.dhis.android.core.category.CategoryOptionComboCategoryOptionLinkTableInfo +@Suppress("MagicNumber") internal object CategoryOptionComboCategoryOptionLinkStore { private val BINDER = StatementBinder { o: CategoryOptionComboCategoryOptionLink, w: StatementWrapper -> @@ -50,4 +51,4 @@ internal object CategoryOptionComboCategoryOptionLinkStore { CategoryOptionComboCategoryOptionLinkTableInfo.Columns.CATEGORY_OPTION_COMBO, BINDER ) { cursor: Cursor -> CategoryOptionComboCategoryOptionLink.create(cursor) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt index abaf309706..abd44ccb67 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStore.kt @@ -32,4 +32,4 @@ import org.hisp.dhis.android.core.category.CategoryOptionCombo internal interface CategoryOptionComboStore : IdentifiableObjectStore { fun getForCategoryCombo(categoryComboUid: String): List -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt index 3cc81e9cfe..a62516061f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionComboStoreImpl.kt @@ -39,6 +39,7 @@ import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidOrNull import org.hisp.dhis.android.core.category.CategoryOptionCombo import org.hisp.dhis.android.core.category.CategoryOptionComboTableInfo +@Suppress("MagicNumber") internal class CategoryOptionComboStoreImpl private constructor( databaseAdapter: DatabaseAdapter, statementBuilder: SQLStatementBuilderImpl @@ -46,7 +47,9 @@ internal class CategoryOptionComboStoreImpl private constructor( databaseAdapter, statementBuilder, BINDER, - { cursor: Cursor -> CategoryOptionCombo.create(cursor) }), CategoryOptionComboStore { + { cursor: Cursor -> CategoryOptionCombo.create(cursor) } +), + CategoryOptionComboStore { override fun getForCategoryCombo(categoryComboUid: String): List { val whereClause = WhereClauseBuilder() @@ -70,4 +73,4 @@ internal class CategoryOptionComboStoreImpl private constructor( return CategoryOptionComboStoreImpl(databaseAdapter, statementBuilder) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt index b9f78338fe..3dbdf5b82f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryOptionStore.kt @@ -37,6 +37,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWit import org.hisp.dhis.android.core.category.CategoryOption import org.hisp.dhis.android.core.category.CategoryOptionTableInfo +@Suppress("MagicNumber") internal object CategoryOptionStore { private val BINDER: StatementBinder = object : NameableStatementBinder() { @@ -55,4 +56,4 @@ internal object CategoryOptionStore { CategoryOptionTableInfo.TABLE_INFO, BINDER ) { cursor: Cursor -> CategoryOption.create(cursor) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt index de449c16fa..b4f48dc5c0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/category/internal/CategoryStore.kt @@ -37,6 +37,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWit import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.category.CategoryTableInfo +@Suppress("MagicNumber") internal object CategoryStore { private val BINDER: StatementBinder = object : IdentifiableStatementBinder() { @@ -54,4 +55,4 @@ internal object CategoryStore { BINDER ) { cursor: Cursor -> Category.create(cursor) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java index a12794dbbb..bbf13f961f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java @@ -36,8 +36,7 @@ public enum DHISVersion { V2_33, V2_34, V2_35, - V2_36, - V2_37; + V2_36; private static final String V2_29_STR = "2.29"; private static final String V2_30_STR = "2.30"; @@ -47,7 +46,6 @@ public enum DHISVersion { private static final String V2_34_STR = "2.34"; private static final String V2_35_STR = "2.35"; private static final String V2_36_STR = "2.36"; - private static final String V2_37_STR = "2.37"; public static DHISVersion getValue(String versionStr) { if (versionStr.startsWith(V2_29_STR)) { @@ -66,8 +64,6 @@ public static DHISVersion getValue(String versionStr) { return V2_35; } else if (versionStr.startsWith(V2_36_STR)) { return V2_36; - } else if (versionStr.startsWith(V2_37_STR)) { - return V2_37; } else { return null; } @@ -78,6 +74,6 @@ public static boolean isAllowedVersion(String versionStr) { } public static String[] allowedVersionsAsStr() { - return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, V2_36_STR, V2_37_STR}; + return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, V2_36_STR}; } } \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt index 4ca2651150..db8026d102 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt @@ -37,12 +37,12 @@ import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s import org.hisp.dhis.android.core.period.Period import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s @RunWith(JUnit4::class) class AnalyticsServiceDimensionHelperShould { @@ -99,20 +99,22 @@ class AnalyticsServiceDimensionHelperShould { ), filters = listOf() ) - val dimensions = setOf(Dimension.Period, Dimension.Data, Dimension.OrganisationUnit, - Dimension.Category(s.categoryItem1_1.uid)) + val dimensions = setOf( + Dimension.Period, Dimension.Data, Dimension.OrganisationUnit, + Dimension.Category(s.categoryItem1_1.uid) + ) val items = helper.getEvaluationItems(params, dimensions) assertThat(items).containsExactly( - item(s.periodAbsolute1, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_1 ), - item(s.periodAbsolute1, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_2 ), - item(s.periodAbsolute1, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_1 ), - item(s.periodAbsolute1, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_2 ), - item(s.periodAbsolute2, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_1 ), - item(s.periodAbsolute2, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_2 ), - item(s.periodAbsolute2, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_1 ), - item(s.periodAbsolute2, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_2 ) + item(s.periodAbsolute1, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_1), + item(s.periodAbsolute1, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_2), + item(s.periodAbsolute1, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_1), + item(s.periodAbsolute1, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_2), + item(s.periodAbsolute2, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_1), + item(s.periodAbsolute2, s.dataElementItem1, s.orgunitAbsolute, s.categoryItem1_2), + item(s.periodAbsolute2, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_1), + item(s.periodAbsolute2, s.indicatorItem, s.orgunitAbsolute, s.categoryItem1_2) ) } @@ -139,11 +141,13 @@ class AnalyticsServiceDimensionHelperShould { @Test fun `Should evaluate relative periods`() { whenever(periodGenerator.generateRelativePeriods(s.periodLast3Days.relative)) - .thenReturn(listOf( - Period.builder().periodId("20210701").build(), - Period.builder().periodId("20210702").build(), - Period.builder().periodId("20210703").build() - )) + .thenReturn( + listOf( + Period.builder().periodId("20210701").build(), + Period.builder().periodId("20210702").build(), + Period.builder().periodId("20210703").build() + ) + ) val params = AnalyticsRepositoryParams( dimensions = listOf( @@ -166,7 +170,8 @@ class AnalyticsServiceDimensionHelperShould { @Test fun `Should evaluate orgunits by level`() { - whenever(organisationUnitHelper.getOrganisationUnitUidsByLevel(any())).thenReturn(listOf("orgunit1", "orgunit2", "orgunit3")) + whenever(organisationUnitHelper.getOrganisationUnitUidsByLevel(any())) + .thenReturn(listOf("orgunit1", "orgunit2", "orgunit3")) val params = AnalyticsRepositoryParams( dimensions = listOf( @@ -193,4 +198,4 @@ class AnalyticsServiceDimensionHelperShould { filters = listOf() ) } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt index 065314a060..bdbd037e54 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt @@ -53,5 +53,4 @@ object AnalyticsServiceHelperSamples { val categoryOptionGroupSetItem1_1 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog11") val categoryOptionGroupSetItem1_2 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog12") val categoryOptionGroupSetItem2_1 = DimensionItem.CategoryOptionGroupSetItem("cogs2", "cog21") - -} \ No newline at end of file +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt index 31e2f98885..c83297f399 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt @@ -32,6 +32,7 @@ import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.category.CategoryOption @@ -46,7 +47,6 @@ import org.hisp.dhis.android.core.program.ProgramIndicator import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s @RunWith(JUnit4::class) class AnalyticsServiceMetadataHelperShould { @@ -98,4 +98,4 @@ class AnalyticsServiceMetadataHelperShould { s.categoryItem1_2.categoryOption ) } -} \ No newline at end of file +} From 52eb0c2f002191306725182e521efe562592c098 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 13 Jul 2021 15:02:47 +0200 Subject: [PATCH 163/308] [ANDROSDK-1387] Include relative periods in metadata --- .../DataElementEvaluatorIntegrationShould.kt | 16 ++++++++++------ .../core/analytics/aggregated/AnalyticsModel.kt | 9 +-------- .../service/AnalyticsServiceDimensionHelper.kt | 3 +-- .../service/AnalyticsServiceMetadataHelper.kt | 13 +++++++------ .../service/evaluator/DataElementEvaluator.kt | 11 ++++------- .../AnalyticsServiceDimensionHelperShould.kt | 6 ++---- .../service/AnalyticsServiceHelperSamples.kt | 4 ---- 7 files changed, 25 insertions(+), 37 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt index d663c3fce6..a481d4682a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -54,8 +54,6 @@ import org.hisp.dhis.android.core.dataelement.internal.DataElementStore import org.hisp.dhis.android.core.datavalue.DataValue import org.hisp.dhis.android.core.datavalue.internal.DataValueStore import org.hisp.dhis.android.core.organisationunit.internal.OrganisationUnitStore -import org.hisp.dhis.android.core.period.internal.CalendarProviderFactory -import org.hisp.dhis.android.core.period.internal.ParentPeriodGeneratorImpl import org.hisp.dhis.android.core.period.internal.PeriodStoreImpl import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyDispatcher import org.hisp.dhis.android.core.utils.runner.D2JunitRunner @@ -67,9 +65,7 @@ import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispatcher() { - private val periodGenerator = ParentPeriodGeneratorImpl.create(CalendarProviderFactory.createFixed()) - - private val dataElementEvaluator = DataElementEvaluator(databaseAdapter, periodGenerator) + private val dataElementEvaluator = DataElementEvaluator(databaseAdapter) // Stores private val dataValueStore = DataValueStore.create(databaseAdapter) @@ -103,6 +99,14 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN.name to MetadataItem.OrganisationUnitRelativeItem( RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN, listOf(orgunitChild1, orgunitChild2) + ), + RelativePeriod.THIS_MONTH.name to MetadataItem.RelativePeriodItem( + RelativePeriod.THIS_MONTH, + listOf(periodDec) + ), + RelativePeriod.LAST_MONTH.name to MetadataItem.RelativePeriodItem( + RelativePeriod.LAST_MONTH, + listOf(periodNov) ) ) @@ -197,7 +201,7 @@ class DataElementEvaluatorIntegrationShould : BaseMockIntegrationTestEmptyDispat ), filters = listOf( DimensionItem.OrganisationUnitItem.Absolute(orgunitParent.uid()), - DimensionItem.PeriodItem.Relative(RelativePeriod.LAST_3_MONTHS), + DimensionItem.PeriodItem.Relative(RelativePeriod.LAST_MONTH), DimensionItem.PeriodItem.Relative(RelativePeriod.THIS_MONTH) ) ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt index 6569fa0d92..1c344a5118 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsModel.kt @@ -51,7 +51,6 @@ sealed class MetadataItem(val id: String, val displayName: String) { class CategoryOptionItem(val item: CategoryOption) : MetadataItem(item.uid(), item.displayName()!!) class CategoryOptionGroupSetItem(uid: String, displayName: String) : MetadataItem(uid, displayName) - class CategoryOptionGroupItem(uid: String, displayName: String) : MetadataItem(uid, displayName) class OrganisationUnitItem(val item: OrganisationUnit) : MetadataItem(item.uid(), item.displayName()!!) class OrganisationUnitLevelItem(val item: OrganisationUnitLevel) : MetadataItem(item.uid(), item.displayName()!!) @@ -62,7 +61,7 @@ sealed class MetadataItem(val id: String, val displayName: String) { ) : MetadataItem(item.name, item.name) class PeriodItem(val item: Period) : MetadataItem(item.periodId()!!, item.periodId()!!) - class RelativePeriodItem(val item: RelativePeriod) : MetadataItem(item.name, item.name) + class RelativePeriodItem(val item: RelativePeriod, val periods: List) : MetadataItem(item.name, item.name) } sealed class Dimension { @@ -70,7 +69,6 @@ sealed class Dimension { object Period : Dimension() object OrganisationUnit : Dimension() data class Category(val uid: String) : Dimension() - data class CategoryOptionGroupSet(val uid: String) : Dimension() } sealed class DimensionItem(val dimension: Dimension, val id: String) { @@ -99,11 +97,6 @@ sealed class DimensionItem(val dimension: Dimension, val id: String) { val uid: String, val categoryOption: String ) : DimensionItem(Dimension.Category(uid), categoryOption), AbsoluteDimensionItem - - class CategoryOptionGroupSetItem( - val uid: String, - val categoryOptionGroup: String - ) : DimensionItem(Dimension.CategoryOptionGroupSet(uid), categoryOptionGroup), AbsoluteDimensionItem } internal interface AbsoluteDimensionItem diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt index 349918fb7d..1cc8c145f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt @@ -28,12 +28,12 @@ package org.hisp.dhis.android.core.analytics.aggregated.service -import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator +import javax.inject.Inject internal class AnalyticsServiceDimensionHelper @Inject constructor( private val periodGenerator: ParentPeriodGenerator, @@ -92,7 +92,6 @@ internal class AnalyticsServiceDimensionHelper @Inject constructor( is DimensionItem.OrganisationUnitItem.Group -> TODO() } is DimensionItem.CategoryItem -> listOf(item) - is DimensionItem.CategoryOptionGroupSetItem -> listOf(item) } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt index d6b0428a6f..d686a30e7b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.analytics.aggregated.service -import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -42,8 +41,10 @@ import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitGroup import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevelTableInfo +import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import org.hisp.dhis.android.core.period.internal.PeriodHelper import org.hisp.dhis.android.core.program.ProgramIndicator +import javax.inject.Inject @Suppress("LongParameterList") internal class AnalyticsServiceMetadataHelper @Inject constructor( @@ -57,6 +58,7 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( private val organisationUnitLevelStore: IdentifiableObjectStore, private val programIndicatorStore: IdentifiableObjectStore, private val analyticsOrganisationUnitHelper: AnalyticsOrganisationUnitHelper, + private val parentPeriodGenerator: ParentPeriodGenerator, private val periodHelper: PeriodHelper ) { @@ -110,8 +112,10 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( is DimensionItem.PeriodItem.Absolute -> periodHelper.blockingGetPeriodForPeriodId(item.periodId) .let { period -> MetadataItem.PeriodItem(period) } - is DimensionItem.PeriodItem.Relative -> - MetadataItem.RelativePeriodItem(item.relative) + is DimensionItem.PeriodItem.Relative -> { + val periods = parentPeriodGenerator.generateRelativePeriods(item.relative) + MetadataItem.RelativePeriodItem(item.relative, periods) + } } ) @@ -143,9 +147,6 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( categoryOptionStore.selectByUid(item.categoryOption)!! .let { categoryOption -> MetadataItem.CategoryOptionItem(categoryOption) } ) - - // TODO - is DimensionItem.CategoryOptionGroupSetItem -> listOf() } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index d20edf4a92..3c5cfaa26e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator -import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem @@ -38,11 +37,10 @@ import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.datavalue.DataValueTableInfo -import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator +import javax.inject.Inject internal class DataElementEvaluator @Inject constructor( - private val databaseAdapter: DatabaseAdapter, - private val parentPeriodGenerator: ParentPeriodGenerator + private val databaseAdapter: DatabaseAdapter ) : AnalyticsEvaluator { override fun evaluate( @@ -60,7 +58,6 @@ internal class DataElementEvaluator @Inject constructor( is Dimension.Period -> appendPeriodWhereClause(entry.value, builder, metadata) is Dimension.OrganisationUnit -> appendOrgunitWhereClause(entry.value, builder, metadata) is Dimension.Category -> appendCategoryWhereClause(entry.value, builder) - is Dimension.CategoryOptionGroupSet -> TODO() } } .appendKeyNumberValue(DataValueTableInfo.Columns.DELETED, 0) @@ -125,10 +122,10 @@ internal class DataElementEvaluator @Inject constructor( ) } is DimensionItem.PeriodItem.Relative -> { - val periods = parentPeriodGenerator.generateRelativePeriods(item.relative) + val relativeItem = metadata[item.id] as MetadataItem.RelativePeriodItem innerBuilder.appendOrInSubQuery( DataValueTableInfo.Columns.PERIOD, - AnalyticsEvaluatorHelper.getInPeriodsClause(periods) + AnalyticsEvaluatorHelper.getInPeriodsClause(relativeItem.periods) ) } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt index db8026d102..8c3aa949ee 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt @@ -67,8 +67,7 @@ class AnalyticsServiceDimensionHelperShould { s.categoryItem1_1, s.orgunitAbsolute, s.categoryItem1_2, - s.categoryItem2_1, - s.categoryOptionGroupSetItem1_1 + s.categoryItem2_1 ), filters = listOf() ) @@ -80,8 +79,7 @@ class AnalyticsServiceDimensionHelperShould { Dimension.Period, Dimension.OrganisationUnit, Dimension.Category(s.categoryItem1_1.uid), - Dimension.Category(s.categoryItem2_1.uid), - Dimension.CategoryOptionGroupSet(s.categoryOptionGroupSetItem1_1.uid) + Dimension.Category(s.categoryItem2_1.uid) ) } diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt index bdbd037e54..e4285a1466 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt @@ -49,8 +49,4 @@ object AnalyticsServiceHelperSamples { val categoryItem1_1 = DimensionItem.CategoryItem(AggregatedSamples.cc1.uid(), AggregatedSamples.co11.uid()) val categoryItem1_2 = DimensionItem.CategoryItem(AggregatedSamples.cc1.uid(), AggregatedSamples.co12.uid()) val categoryItem2_1 = DimensionItem.CategoryItem(AggregatedSamples.cc2.uid(), AggregatedSamples.co21.uid()) - - val categoryOptionGroupSetItem1_1 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog11") - val categoryOptionGroupSetItem1_2 = DimensionItem.CategoryOptionGroupSetItem("cogs1", "cog12") - val categoryOptionGroupSetItem2_1 = DimensionItem.CategoryOptionGroupSetItem("cogs2", "cog21") } From bbc164ec73e647005a152a0ff6f58bbc2600c37d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 13 Jul 2021 15:17:13 +0200 Subject: [PATCH 164/308] [ANDROSDK-1387] Checkstyle --- .../aggregated/service/AnalyticsServiceDimensionHelper.kt | 2 +- .../aggregated/service/AnalyticsServiceMetadataHelper.kt | 2 +- .../aggregated/service/evaluator/DataElementEvaluator.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt index 1cc8c145f1..1caa76faf1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt @@ -28,12 +28,12 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator -import javax.inject.Inject internal class AnalyticsServiceDimensionHelper @Inject constructor( private val periodGenerator: ParentPeriodGenerator, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt index d686a30e7b..79d502f913 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.service +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -44,7 +45,6 @@ import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevelTableInf import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import org.hisp.dhis.android.core.period.internal.PeriodHelper import org.hisp.dhis.android.core.program.ProgramIndicator -import javax.inject.Inject @Suppress("LongParameterList") internal class AnalyticsServiceMetadataHelper @Inject constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt index 3c5cfaa26e..62f279a85e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem @@ -37,7 +38,6 @@ import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.AggregationType import org.hisp.dhis.android.core.datavalue.DataValueTableInfo -import javax.inject.Inject internal class DataElementEvaluator @Inject constructor( private val databaseAdapter: DatabaseAdapter From 56f57c827e8426cf229d97d70ccdaec9031b07b2 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 13 Jul 2021 13:22:41 +0200 Subject: [PATCH 165/308] [ANDROSDK-1384] DhisVisualizations repository tests --- ...ObjectRepositoryMockIntegrationShould.java | 55 +++++++++++++++++ ...ObjectRepositoryMockIntegrationShould.java | 17 ++++-- .../core/mockwebserver/Dhis2MockServer.java | 2 +- ...VisualizationsSettingObjectRepository.java | 12 ++-- .../settings/internal/SettingModuleWiper.java | 2 + .../settings/analytics_settings_v2.json | 59 ++++++++++++++++--- .../core/settings/AnalyticsSettingV2Should.kt | 16 +++-- 7 files changed, 138 insertions(+), 25 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsDhisVisualizationsSettingObjectRepositoryMockIntegrationShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsDhisVisualizationsSettingObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsDhisVisualizationsSettingObjectRepositoryMockIntegrationShould.java new file mode 100644 index 0000000000..33bdd601fb --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsDhisVisualizationsSettingObjectRepositoryMockIntegrationShould.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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 org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationsSetting; +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 AnalyticsDhisVisualizationsSettingObjectRepositoryMockIntegrationShould + extends BaseMockIntegrationTestFullDispatcher { + + @Test + public void find_analytics_settings() { + AnalyticsDhisVisualizationsSetting analyticsDhisVisualizationsSetting = d2 + .settingModule() + .analyticsSetting() + .visualizationsSettings() + .blockingGet(); + + assertThat(analyticsDhisVisualizationsSetting.home().size()).isEqualTo(2); + assertThat(analyticsDhisVisualizationsSetting.program().size()).isEqualTo(1); + assertThat(analyticsDhisVisualizationsSetting.dataSet().size()).isEqualTo(1); + } +} diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java index 769f258410..372f217b30 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/AnalyticsSettingsObjectRepositoryMockIntegrationShould.java @@ -1,19 +1,19 @@ /* * Copyright (c) 2004-2021, 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 @@ -28,6 +28,7 @@ package org.hisp.dhis.android.testapp.settings; +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationsGroup; import org.hisp.dhis.android.core.settings.AnalyticsSettings; import org.hisp.dhis.android.core.settings.AnalyticsTeiSetting; import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; @@ -56,7 +57,7 @@ public void find_analytics_settings() { assertThat(teiSetting.data().indicators().size()).isEqualTo(1); assertThat(teiSetting.data().attributes().size()).isEqualTo(1); assertThat(teiSetting.whoNutritionData()).isNull(); - } else if("yEdtdG7ql9K".equals(teiSetting.uid())) { + } else if ("yEdtdG7ql9K".equals(teiSetting.uid())) { assertThat(teiSetting.data()).isNull(); assertThat(teiSetting.whoNutritionData().x().dataElements().size()).isEqualTo(1); assertThat(teiSetting.whoNutritionData().x().indicators().size()).isEqualTo(0); @@ -64,5 +65,13 @@ public void find_analytics_settings() { assertThat(teiSetting.whoNutritionData().y().indicators().size()).isEqualTo(1); } } + + for (AnalyticsDhisVisualizationsGroup analyticsDhisVisualizationsGroup : analyticsSettings.dhisVisualizations().home()) { + if (analyticsDhisVisualizationsGroup.id().equals("12345678910")) { + assertThat(analyticsDhisVisualizationsGroup.visualizations().size()).isEqualTo(2); + } else if (analyticsDhisVisualizationsGroup.id().equals("12345678911")) { + assertThat(analyticsDhisVisualizationsGroup.visualizations().size()).isEqualTo(1); + } + } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java b/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java index 781d641650..28da3b5842 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/mockwebserver/Dhis2MockServer.java @@ -63,7 +63,7 @@ public class Dhis2MockServer { private static final String PROGRAM_SETTINGS_JSON = "settings/program_settings.json"; private static final String SYNCHRONIZATION_SETTTINGS_JSON = "settings/synchronization_settings.json"; private static final String APPEARANCE_SETTINGS_JSON = "settings/appearance_settings.json"; - private static final String ANALYTICS_SETTINGS_JSON = "settings/analytics_settings.json"; + private static final String ANALYTICS_SETTINGS_JSON = "settings/analytics_settings_v2.json"; private static final String USER_SETTINGS_JSON = "settings/user_settings.json"; private static final String PROGRAMS_JSON = "program/programs.json"; private static final String PROGRAM_STAGES_JSON = "program/program_stages.json"; diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java index 12dcf196a8..7e429868d1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationsSettingObjectRepository.java @@ -34,7 +34,7 @@ import org.hisp.dhis.android.core.settings.internal.AnalyticsSettingCall; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -98,7 +98,7 @@ public AnalyticsDhisVisualizationsSetting blockingGet() { group = createGroup(analyticsDhisVisualization); program.put( analyticsDhisVisualization.scopeUid(), - Collections.singletonList(group) + createGroupList(group) ); } else { AnalyticsDhisVisualizationsGroup updatedGroup = updateGroup(group, analyticsDhisVisualization); @@ -117,7 +117,7 @@ public AnalyticsDhisVisualizationsSetting blockingGet() { group = createGroup(analyticsDhisVisualization); dataSet.put( analyticsDhisVisualization.scopeUid(), - Collections.singletonList(group) + createGroupList(group) ); } else { AnalyticsDhisVisualizationsGroup updatedGroup = updateGroup(group, analyticsDhisVisualization); @@ -157,7 +157,7 @@ private AnalyticsDhisVisualizationsGroup createGroup(AnalyticsDhisVisualization .builder() .id(analyticsDhisVisualization.groupUid()) .name(analyticsDhisVisualization.groupName()) - .visualizations(Collections.singletonList(analyticsDhisVisualization)) + .visualizations(new ArrayList<>(Arrays.asList(analyticsDhisVisualization))) .build(); } @@ -173,4 +173,8 @@ private AnalyticsDhisVisualizationsGroup updateGroup( .visualizations(updatedVisualizations) .build(); } + + private List createGroupList(AnalyticsDhisVisualizationsGroup group) { + return new ArrayList<>(Arrays.asList(group)); + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java index 93cbc784f5..8da64943b0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java @@ -27,6 +27,7 @@ */ package org.hisp.dhis.android.core.settings.internal; +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualizationTableInfo; import org.hisp.dhis.android.core.settings.AnalyticsTeiAttributeTableInfo; import org.hisp.dhis.android.core.settings.AnalyticsTeiDataElementTableInfo; import org.hisp.dhis.android.core.settings.AnalyticsTeiIndicatorTableInfo; @@ -70,6 +71,7 @@ public void wipeMetadata() { tableWiper.wipeTable(AnalyticsTeiIndicatorTableInfo.TABLE_INFO); tableWiper.wipeTable(AnalyticsTeiAttributeTableInfo.TABLE_INFO); tableWiper.wipeTable(UserSettingsTableInfo.TABLE_INFO); + tableWiper.wipeTable(AnalyticsDhisVisualizationTableInfo.INSTANCE.getTABLE_INFO()); } @Override diff --git a/core/src/sharedTest/resources/settings/analytics_settings_v2.json b/core/src/sharedTest/resources/settings/analytics_settings_v2.json index e1b14c918f..511ac1a307 100644 --- a/core/src/sharedTest/resources/settings/analytics_settings_v2.json +++ b/core/src/sharedTest/resources/settings/analytics_settings_v2.json @@ -1,18 +1,63 @@ { "tei": [ { - "uid": "Lryd0j1jhho", + "uid": "fqEx2avRp1L", "data": { - "attributes": [ - "OvY4VVhSDeJ" + "dataElements": [ + "dBwrot7S420.sWoqcoByYmD", + "dBwrot7S421.Ok9OQpitjQr" ] }, - "name": "Lab monitoring weekly weight", + "name": "Height evolution", "type": "LINE", + "period": "Monthly", + "program": "IpHINAT79UW", + "programStage": "dBwrot7S420", + "shortName": "H. evolution" + }, + { + "uid": "XQUhloISaQJ", + "data": { + "indicators": [ + "dBwrot7S420.GSae40Fyppf" + ], + "attributes": [ + "cejWyOfXge6" + ] + }, + "name": "Weight gain", + "type": "BAR", "period": "Weekly", - "program": "ur1Edk5Oe2n", - "shortName": "line_weekly_kg", - "programStage": "EPEcjy3FWmI" + "program": "lxAQ7Zs9VYR", + "shortName": "W. gain" + }, + { + "WHONutrition": { + "chartType": "WFH", + "gender": { + "attribute": "cejWyOfXge6", + "values": { + "female": "female", + "male": "male" + } + }, + "x": { + "dataElements": [ + "dBwrot7S420.sWoqcoByYmD" + ] + }, + "y": { + "indicators": [ + "GSae40Fyppf" + ] + } + }, + "name": "Who chart", + "program": "IpHINAT79UW", + "programStage": "dBwrot7S420", + "shortName": "Who chart", + "type": "WHO_NUTRITION", + "uid": "yEdtdG7ql9K" } ], "lastUpdated": "2021-06-02T04:30:16.877Z", diff --git a/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt b/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt index 3d480f4bbb..b9244d7799 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/settings/AnalyticsSettingV2Should.kt @@ -34,7 +34,6 @@ import java.text.ParseException import org.hisp.dhis.android.core.common.BaseObjectShould import org.hisp.dhis.android.core.common.ObjectShould import org.hisp.dhis.android.core.period.PeriodType -import org.junit.Assert import org.junit.Test class AnalyticsSettingV2Should : BaseObjectShould("settings/analytics_settings_v2.json"), ObjectShould { @@ -44,19 +43,18 @@ class AnalyticsSettingV2Should : BaseObjectShould("settings/analytics_settings_v override fun map_from_json_string() { val analyticsSettings = objectMapper.readValue(jsonStream, AnalyticsSettings::class.java) - Truth.assertThat(analyticsSettings.tei().size).isEqualTo(1) + Truth.assertThat(analyticsSettings.tei().size).isEqualTo(3) analyticsSettings.tei().forEach { tei -> when (tei.uid()) { - "Lryd0j1jhho" -> { - Truth.assertThat(tei.name()).isEqualTo("Lab monitoring weekly weight") - Truth.assertThat(tei.shortName()).isEqualTo("line_weekly_kg") - Truth.assertThat(tei.program()).isEqualTo("ur1Edk5Oe2n") - Truth.assertThat(tei.programStage()).isEqualTo("EPEcjy3FWmI") - Truth.assertThat(tei.period()).isEquivalentAccordingToCompareTo(PeriodType.Weekly) + "fqEx2avRp1L" -> { + Truth.assertThat(tei.name()).isEqualTo("Height evolution") + Truth.assertThat(tei.shortName()).isEqualTo("H. evolution") + Truth.assertThat(tei.program()).isEqualTo("IpHINAT79UW") + Truth.assertThat(tei.programStage()).isEqualTo("dBwrot7S420") + Truth.assertThat(tei.period()).isEquivalentAccordingToCompareTo(PeriodType.Monthly) Truth.assertThat(tei.type()).isEquivalentAccordingToCompareTo(ChartType.LINE) } - else -> Assert.fail("Unexpected tei uid") } } From 636c489dad449082e7eea98dedbdb4d2e655a459 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:48:40 +0200 Subject: [PATCH 166/308] [androsdk-1383] Add DataDimensionItem table info --- .../core/visualization/DataDimensionItem.java | 52 +++++++++++- .../DataDimensionItemTableInfo.kt | 84 +++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java index 6195a38ccc..90b99c6869 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItem.java @@ -47,6 +47,9 @@ @JsonDeserialize(builder = $$AutoValue_DataDimensionItem.Builder.class) public abstract class DataDimensionItem implements CoreObject { + @Nullable + public abstract String visualization(); + @Nullable @JsonProperty() @ColumnAdapter(DataDimensionItemTypeColumnAdapter.class) @@ -86,7 +89,50 @@ public abstract class DataDimensionItem implements CoreObject { @JsonProperty() @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid programAttribute(); - + + @Nullable + @JsonProperty() + @ColumnAdapter(ObjectWithUidColumnAdapter.class) + public abstract ObjectWithUid validationRule(); + + @Nullable + public String dataDimensionItem() { + ObjectWithUid item = dataDimensionItemObject(); + if (item == null) { + return null; + } else { + return item.uid(); + } + } + + @Nullable + private ObjectWithUid dataDimensionItemObject() { + DataDimensionItemType type = dataDimensionItemType(); + if (type == null) { + return null; + } else { + switch (type) { + case INDICATOR: + return indicator(); + case DATA_ELEMENT: + return dataElement(); + case PROGRAM_ATTRIBUTE: + return programAttribute(); + case PROGRAM_DATA_ELEMENT: + return programDataElement(); + case PROGRAM_INDICATOR: + return programIndicator(); + case REPORTING_RATE: + return reportingRate(); + case DATA_ELEMENT_OPERAND: + return dataElementOperand(); + case VALIDATION_RULE: + return validationRule(); + default: + return null; + } + } + } public static Builder builder() { return new $$AutoValue_DataDimensionItem.Builder(); @@ -104,6 +150,8 @@ public static abstract class Builder { public abstract Builder id(Long id); + public abstract Builder visualization(String visualization); + public abstract Builder dataDimensionItemType(DataDimensionItemType dataDimensionItemType); public abstract Builder indicator(ObjectWithUid indicator); @@ -120,6 +168,8 @@ public static abstract class Builder { public abstract Builder programAttribute(ObjectWithUid programAttribute); + public abstract Builder validationRule(ObjectWithUid validationRule); + public abstract DataDimensionItem build(); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt new file mode 100644 index 0000000000..32caf9887c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns + +object DataDimensionItemTableInfo { + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "DataDimensionItem" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : CoreColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + VISUALIZATION, + DATA_DIMENSION_ITEM_TYPE, + INDICATOR, + DATA_ELEMENT, + DATA_ELEMENT_OPERAND, + REPORTING_RATE, + PROGRAM_INDICATOR, + PROGRAM_DATA_ELEMENT, + PROGRAM_ATTRIBUTE, + VALIDATION_RULE + ) + } + + override fun whereUpdate(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + VISUALIZATION, + DATA_DIMENSION_ITEM_TYPE + ) + } + + companion object { + const val VISUALIZATION = "visualization" + const val DATA_DIMENSION_ITEM_TYPE = "dataDimensionItemType" + const val INDICATOR = "indicator" + const val DATA_ELEMENT = "dataElement" + const val DATA_ELEMENT_OPERAND = "dataElementOperand" + const val REPORTING_RATE = "reportingRate" + const val PROGRAM_INDICATOR = "programIndicator" + const val PROGRAM_DATA_ELEMENT = "programDataElement" + const val PROGRAM_ATTRIBUTE = "programAttribute" + const val VALIDATION_RULE = "validationRule" + } + } +} From c59da0832a5972dee6110f80ed8d1249164bb48d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:48:52 +0200 Subject: [PATCH 167/308] [androsdk-1383] Add DataDimensionItem store --- .../internal/DataDimensionItemStore.kt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt new file mode 100644 index 0000000000..51eb06674d --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +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.internal.LinkStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory +import org.hisp.dhis.android.core.arch.helpers.UidsHelper +import org.hisp.dhis.android.core.visualization.DataDimensionItem +import org.hisp.dhis.android.core.visualization.DataDimensionItemTableInfo + +internal object DataDimensionItemStore { + private val BINDER = StatementBinder { o: DataDimensionItem, w: StatementWrapper -> + w.bind(1, o.visualization()) + w.bind(2, o.dataDimensionItemType()) + w.bind(3, UidsHelper.getUidOrNull(o.indicator())) + w.bind(4, UidsHelper.getUidOrNull(o.dataElement())) + w.bind(5, UidsHelper.getUidOrNull(o.dataElementOperand())) + w.bind(6, UidsHelper.getUidOrNull(o.reportingRate())) + w.bind(7, UidsHelper.getUidOrNull(o.programIndicator())) + w.bind(8, UidsHelper.getUidOrNull(o.programDataElement())) + w.bind(9, UidsHelper.getUidOrNull(o.programAttribute())) + w.bind(10, UidsHelper.getUidOrNull(o.validationRule())) + } + + fun create(databaseAdapter: DatabaseAdapter): LinkStore { + return StoreFactory.linkStore( + databaseAdapter, + DataDimensionItemTableInfo.TABLE_INFO, + DataDimensionItemTableInfo.Columns.VISUALIZATION, + BINDER + ) { DataDimensionItem.create(it) } + } +} From 1154952d0c1b7879e6ce3bddf6fa705880ac7a99 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:49:11 +0200 Subject: [PATCH 168/308] [androsdk-1383] Add DataDimensionItem DI module --- .../DataDimensionItemEntityDIModule.kt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemEntityDIModule.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemEntityDIModule.kt new file mode 100644 index 0000000000..03409a119c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemEntityDIModule.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore +import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler +import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandlerImpl +import org.hisp.dhis.android.core.visualization.DataDimensionItem + +@Module +internal class DataDimensionItemEntityDIModule { + + @Provides + @Reusable + fun store(databaseAdapter: DatabaseAdapter): LinkStore { + return DataDimensionItemStore.create(databaseAdapter) + } + + @Provides + @Reusable + fun handler(store: LinkStore): + LinkHandler { + return LinkHandlerImpl(store) + } +} From 9672b442658e86aabb876460192f364d7aab6ab2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:49:39 +0200 Subject: [PATCH 169/308] [androsdk-1383] Add VisualizationDataDimenisonItem children appender --- ...zationDataDimensionItemChildrenAppender.kt | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationDataDimensionItemChildrenAppender.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationDataDimensionItemChildrenAppender.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationDataDimensionItemChildrenAppender.kt new file mode 100644 index 0000000000..98cb5adfcf --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationDataDimensionItemChildrenAppender.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender +import org.hisp.dhis.android.core.visualization.DataDimensionItem +import org.hisp.dhis.android.core.visualization.DataDimensionItemTableInfo +import org.hisp.dhis.android.core.visualization.Visualization + +internal class VisualizationDataDimensionItemChildrenAppender +private constructor(private val childStore: LinkStore) : + ChildrenAppender() { + + override fun appendChildren(visualization: Visualization): Visualization { + val builder = visualization.toBuilder() + builder.dataDimensionItems(getChildren(visualization)) + return builder.build() + } + + private fun getChildren(o: Visualization): List { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(DataDimensionItemTableInfo.Columns.VISUALIZATION, o.uid()) + .build() + return this.childStore.selectWhere(whereClause) + } + + companion object { + fun create(databaseAdapter: DatabaseAdapter): ChildrenAppender { + return VisualizationDataDimensionItemChildrenAppender( + DataDimensionItemStore.create(databaseAdapter) + ) + } + } +} From 21911f5f50e7bfc71f7776d038f1e6c291a56c97 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:50:17 +0200 Subject: [PATCH 170/308] [androsdk-1383] Add DataDimensionItem table and migration --- core/src/main/assets/migrations/104.sql | 3 ++- core/src/main/assets/snapshots/104.sql | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/assets/migrations/104.sql b/core/src/main/assets/migrations/104.sql index b2c713d697..f91fe413b8 100644 --- a/core/src/main/assets/migrations/104.sql +++ b/core/src/main/assets/migrations/104.sql @@ -1,2 +1,3 @@ CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); -CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); \ No newline at end of file +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType)); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/104.sql b/core/src/main/assets/snapshots/104.sql index ad194953ae..9bad57a0a3 100644 --- a/core/src/main/assets/snapshots/104.sql +++ b/core/src/main/assets/snapshots/104.sql @@ -113,3 +113,4 @@ CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerTyp CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType)); From a424fa850831e9bd4e06153680878a049701f5b1 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:50:43 +0200 Subject: [PATCH 171/308] [androsdk-1383] Update Visualization handler and modules --- .../internal/VisualizationEntityDIModule.kt | 13 +++++++++---- .../visualization/internal/VisualizationHandler.kt | 8 +++++++- .../internal/VisualizationPackageDIModule.java | 1 + 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt index 944a2963a3..1c77ee9473 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt @@ -36,7 +36,6 @@ import org.hisp.dhis.android.core.arch.di.internal.IdentifiableStoreProvider import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender import org.hisp.dhis.android.core.visualization.Visualization -import java.util.* @Module internal class VisualizationEntityDIModule : IdentifiableStoreProvider { @@ -56,9 +55,15 @@ internal class VisualizationEntityDIModule : IdentifiableStoreProvider> { - return Collections.singletonMap( - VisualizationFields.CATEGORY_DIMENSIONS, - VisualizationCategoryDimensionChildrenAppender.create(databaseAdapter) + return mapOf( + Pair( + VisualizationFields.CATEGORY_DIMENSIONS, + VisualizationCategoryDimensionChildrenAppender.create(databaseAdapter) + ), + Pair( + VisualizationFields.DATA_DIMENSION_ITEMS, + VisualizationDataDimensionItemChildrenAppender.create(databaseAdapter) + ) ) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index d7e2bcb5ca..23522239bd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.arch.handlers.internal.IdentifiableHandlerImpl import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.visualization.CategoryDimension +import org.hisp.dhis.android.core.visualization.DataDimensionItem import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink import javax.inject.Inject @@ -42,7 +43,8 @@ import javax.inject.Inject internal class VisualizationHandler @Inject constructor( store: IdentifiableObjectStore, private val visualizationCategoryDimensionLinkHandler: - LinkHandler + LinkHandler, + private val dataDimensionItemHandler: LinkHandler ) : IdentifiableHandlerImpl(store) { override fun beforeCollectionHandled( @@ -66,5 +68,9 @@ internal class VisualizationHandler @Inject constructor( } } } + + dataDimensionItemHandler.handleMany(o.uid(), o.dataDimensionItems()) { + it.toBuilder().visualization(o.uid()).build() + } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java index 5131612584..001857209a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationPackageDIModule.java @@ -38,6 +38,7 @@ import retrofit2.Retrofit; @Module(includes = { + DataDimensionItemEntityDIModule.class, VisualizationEntityDIModule.class, VisualizationCategoryDimensionEntityDIModule.class }) From c396462a585db1ba598cf263cf1b56e83a9d9de1 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 13 Jul 2021 16:50:57 +0200 Subject: [PATCH 172/308] [androsdk-1383] Improve VisualizationCollectionRepositoryMockIntegrationShould --- ...izationCollectionRepositoryMockIntegrationShould.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java index e4a65f548c..224909c514 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java @@ -30,6 +30,7 @@ import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; +import org.hisp.dhis.android.core.visualization.DataDimensionItemType; import org.hisp.dhis.android.core.visualization.HideEmptyItemStrategy; import org.hisp.dhis.android.core.visualization.Visualization; import org.hisp.dhis.android.core.visualization.VisualizationType; @@ -119,4 +120,12 @@ public void include_category_dimensions_as_children() { assertThat(visualization.categoryDimensions().get(0).categoryOptions().get(1).uid()).isEqualTo("TXGfLxZlInA"); assertThat(visualization.categoryDimensions().get(0).categoryOptions().get(2).uid()).isEqualTo("uZUnebiT5DI"); } + + @Test + public void include_data_dimension_item_as_children() { + Visualization visualization = d2.visualizationModule().visualizations() + .withDataDimensionItems().one().blockingGet(); + assertThat(visualization.dataDimensionItems().get(0).dataDimensionItemType()).isEqualTo(DataDimensionItemType.DATA_ELEMENT); + assertThat(visualization.dataDimensionItems().get(0).dataDimensionItem()).isEqualTo("cYeuwXTCPkU"); + } } \ No newline at end of file From c836cc05a25f955291697545355f05145fbc7d3d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 14 Jul 2021 11:57:50 +0200 Subject: [PATCH 173/308] [ANDROSDK-1387] Fix unit test dependency --- .../aggregated/service/AnalyticsServiceMetadataHelper.kt | 7 ++++--- .../service/AnalyticsServiceMetadataHelperShould.kt | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt index 79d502f913..72eda95c8a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt @@ -109,9 +109,10 @@ internal class AnalyticsServiceMetadataHelper @Inject constructor( is DimensionItem.PeriodItem -> listOf( when (item) { - is DimensionItem.PeriodItem.Absolute -> - periodHelper.blockingGetPeriodForPeriodId(item.periodId) - .let { period -> MetadataItem.PeriodItem(period) } + is DimensionItem.PeriodItem.Absolute -> { + val period = periodHelper.blockingGetPeriodForPeriodId(item.periodId) + MetadataItem.PeriodItem(period) + } is DimensionItem.PeriodItem.Relative -> { val periods = parentPeriodGenerator.generateRelativePeriods(item.relative) MetadataItem.RelativePeriodItem(item.relative, periods) diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt index c83297f399..7bd5ae6fb3 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt @@ -42,6 +42,7 @@ import org.hisp.dhis.android.core.indicator.Indicator import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitGroup import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel +import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import org.hisp.dhis.android.core.period.internal.PeriodHelper import org.hisp.dhis.android.core.program.ProgramIndicator import org.junit.Test @@ -61,6 +62,7 @@ class AnalyticsServiceMetadataHelperShould { private val organisationUnitLevelStore: IdentifiableObjectStore = mock() private val programIndicatorStore: IdentifiableObjectStore = mock() private val analyticsOrganisationUnitHelper: AnalyticsOrganisationUnitHelper = mock() + private val parentPeriodGenerator: ParentPeriodGenerator = mock() private val periodHelper: PeriodHelper = mock() private val helper = AnalyticsServiceMetadataHelper( @@ -74,6 +76,7 @@ class AnalyticsServiceMetadataHelperShould { organisationUnitLevelStore, programIndicatorStore, analyticsOrganisationUnitHelper, + parentPeriodGenerator, periodHelper ) From 43f2871845409efbe67e031bdd8b089167733b77 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 14 Jul 2021 14:16:56 +0200 Subject: [PATCH 174/308] [DHIS-2.37] Enable version 2.37 --- .../hisp/dhis/android/core/systeminfo/DHISVersion.java | 9 +++++++-- .../android/core/systeminfo/DHISVersionManager.java | 4 ++++ .../systeminfo/internal/DHISVersionManagerImpl.java | 10 ++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java index bbf13f961f..e1e14c4597 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java @@ -36,7 +36,8 @@ public enum DHISVersion { V2_33, V2_34, V2_35, - V2_36; + V2_36, + V2_37; private static final String V2_29_STR = "2.29"; private static final String V2_30_STR = "2.30"; @@ -46,6 +47,7 @@ public enum DHISVersion { private static final String V2_34_STR = "2.34"; private static final String V2_35_STR = "2.35"; private static final String V2_36_STR = "2.36"; + private static final String V2_37_STR = "2.37"; public static DHISVersion getValue(String versionStr) { if (versionStr.startsWith(V2_29_STR)) { @@ -64,6 +66,8 @@ public static DHISVersion getValue(String versionStr) { return V2_35; } else if (versionStr.startsWith(V2_36_STR)) { return V2_36; + } else if (versionStr.startsWith(V2_37_STR)) { + return V2_37; } else { return null; } @@ -74,6 +78,7 @@ public static boolean isAllowedVersion(String versionStr) { } public static String[] allowedVersionsAsStr() { - return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, V2_36_STR}; + return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, + V2_36_STR, V2_37_STR}; } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java index 7f1712a350..8df9edf3a2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java @@ -48,6 +48,10 @@ public interface DHISVersionManager { boolean is2_35(); + boolean is2_36(); + + boolean is2_37(); + /** * Check if the current version is strictly greater than the parameter. * diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java index 6bd0473bc2..0a2bb83018 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java @@ -121,6 +121,16 @@ public boolean is2_35() { return getVersion() == DHISVersion.V2_35; } + @Override + public boolean is2_36() { + return getVersion() == DHISVersion.V2_36; + } + + @Override + public boolean is2_37() { + return getVersion() == DHISVersion.V2_37; + } + @Override public boolean isGreaterThan(DHISVersion version) { return version.compareTo(getVersion()) < 0; From 7c91eb2aa568c1684338dd803ec222507490aca7 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 14 Jul 2021 14:18:45 +0200 Subject: [PATCH 175/308] [DHIS-2.37] Update test urls --- .../android/core/MetadataCallRealIntegrationShould.java | 2 +- .../dhis/android/core/data/server/RealServerMother.java | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java index 21b6a63bfe..c7411c5248 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java @@ -70,7 +70,7 @@ make a debugger break point where desired (after sync complete) //This test is uncommented because technically it is flaky. //It depends on a live server to operate and the login is hardcoded here. //Uncomment in order to quickly test changes vs a real server, but keep it uncommented after. -// @Test + //@Test public void response_successful_on_sync_meta_data_once() throws Exception { d2.userModule().logIn(username, password, url).blockingGet(); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/data/server/RealServerMother.java b/core/src/androidTest/java/org/hisp/dhis/android/core/data/server/RealServerMother.java index 20e95a4f24..7af48ea08e 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/data/server/RealServerMother.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/data/server/RealServerMother.java @@ -31,11 +31,12 @@ public class RealServerMother { public static String url2_29 = "https://play.dhis2.org/2.29/"; public static String url2_30 = "https://play.dhis2.org/2.30/"; - public static String url2_31 = "https://play.dhis2.org/2.31.9/"; - public static String url2_32 = "https://play.dhis2.org/2.32.6/"; - public static String url2_33 = "https://play.dhis2.org/2.33.6/"; - public static String url2_34 = "https://play.dhis2.org/2.34.1/"; + public static String url2_31 = "https://play.dhis2.org/2.31/"; + public static String url2_32 = "https://play.dhis2.org/2.32/"; + public static String url2_33 = "https://play.dhis2.org/2.33/"; + public static String url2_34 = "https://play.dhis2.org/2.34/"; public static String url2_35 = "https://play.dhis2.org/2.35/"; + public static String url2_36 = "https://play.dhis2.org/2.36/"; public static String url_dev = "https://play.dhis2.org/dev/"; public static String android_current = "https://play.dhis2.org/android-current/"; public static String android_previous1 = "https://play.dhis2.org/android-previous1/"; From 715eb5836c648b29817ed920745245eeca69311e Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 14 Jul 2021 14:20:47 +0200 Subject: [PATCH 176/308] [ANDROSDK-1387] Type in operator --- .../aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt index 62ef083ba8..9ed6d26212 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt @@ -43,7 +43,7 @@ internal object AnalyticsEvaluatorHelper { const val Avg = "AVG" const val Count = "COUNT" const val Max = "MAX" - const val Min = "Min" + const val Min = "MIN" fun getInPeriodClause(period: Period): String { return "SELECT ${PeriodTableInfo.Columns.PERIOD_ID} " + From 3c13785518d91ee990c709cfa2149e31731c1804 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 15:30:31 +0200 Subject: [PATCH 177/308] [androsdk-1383] Rename .java to .kt --- ...EndpointCallShould.java => VisualizationEndpointCallShould.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/{VisualizationEndpointCallShould.java => VisualizationEndpointCallShould.kt} (100%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt similarity index 100% rename from core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.java rename to core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt From 19ddbd8398c199d0cb40fded17965a0a8874fe81 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 15:30:32 +0200 Subject: [PATCH 178/308] [androsdk-1383] Fix VisualizationEndpointCallShould --- .../VisualizationEndpointCallShould.kt | 61 +++++++++++-------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt index 513e9bc6d5..7c67f104da 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt @@ -25,36 +25,45 @@ * (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.visualization.internal -package org.hisp.dhis.android.core.visualization.internal; +import com.google.common.collect.Lists +import com.google.common.truth.Truth +import io.reactivex.Single +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyEnqueable +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.hisp.dhis.android.core.visualization.Visualization +import org.junit.BeforeClass +import org.junit.Test +import org.junit.runner.RunWith +import java.util.* -import com.google.common.collect.Lists; +@RunWith(D2JunitRunner::class) +class VisualizationEndpointCallShould : BaseMockIntegrationTestEmptyEnqueable() { -import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyEnqueable; -import org.hisp.dhis.android.core.visualization.Visualization; -import org.junit.Test; + companion object { + private lateinit var visualizationsSingle: Single> -import java.util.HashSet; -import java.util.List; - -import io.reactivex.Single; - -import static com.google.common.truth.Truth.assertThat; - -public class VisualizationEndpointCallShould extends BaseMockIntegrationTestEmptyEnqueable { + @BeforeClass + @JvmStatic + @Throws(Exception::class) + internal fun setUpClass() { + BaseMockIntegrationTestEmptyEnqueable.setUpClass() + visualizationsSingle = objects.d2DIComponent.internalModules().visualization.visualizationCall.download( + HashSet( + Lists.newArrayList("PYBH8ZaAQnC", "FAFa11yFeFe") + ) + ) + dhis2MockServer.enqueueMockResponse("visualization/visualizations.json") + d2.databaseAdapter().setForeignKeyConstraintsEnabled(false) + } + } @Test - public void download_visualization_successfully() { - Single> visualizationsSingle = - objects.d2DIComponent.internalModules().visualization.getVisualizationCall().download(new HashSet<>( - Lists.newArrayList("PYBH8ZaAQnC", "FAFa11yFeFe"))); - - dhis2MockServer.enqueueMockResponse("visualization/visualizations.json"); - - d2.databaseAdapter().setForeignKeyConstraintsEnabled(false); - List visualizations = visualizationsSingle.blockingGet(); - assertThat(visualizations.isEmpty()).isFalse(); - visualizations = d2.visualizationModule().visualizations().blockingGet(); - assertThat(visualizations.isEmpty()).isFalse(); + fun download_persist_and_get_visualizations_successfully() { + var visualizations = visualizationsSingle.blockingGet() + Truth.assertThat(visualizations.isEmpty()).isFalse() + visualizations = d2.visualizationModule().visualizations().blockingGet() + Truth.assertThat(visualizations.isEmpty()).isFalse() } -} \ No newline at end of file +} From bfcb14dd0b01a7a0b17f3a65268c9d91b370f783 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 15:31:05 +0200 Subject: [PATCH 179/308] [androsdk-1383] Add more tests --- ...DataDimensionItemStoreIntegrationShould.kt | 58 ++++++++ .../visualization/DataDimensionItemSamples.kt | 43 ++++++ .../internal/VisualizationHandlerShould.java | 126 ++++++++++++++++++ .../CategoryDimensionPublicAccessShould.java | 59 ++++++++ .../DataDimensionItemPublicAccessShould.java | 59 ++++++++ 5 files changed, 345 insertions(+) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/DataDimensionItemSamples.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java create mode 100644 core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java create mode 100644 core/src/test/java/org/hisp/dhis/android/testapp/visualization/DataDimensionItemPublicAccessShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt new file mode 100644 index 0000000000..df22952e77 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal + +import org.hisp.dhis.android.core.data.database.LinkStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.data.visualization.DataDimensionItemSamples +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.hisp.dhis.android.core.visualization.DataDimensionItem +import org.hisp.dhis.android.core.visualization.DataDimensionItemTableInfo +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class DataDimensionItemStoreIntegrationShould : + LinkStoreAbstractIntegrationShould( + DataDimensionItemStore.create(TestDatabaseAdapterFactory.get()), + DataDimensionItemTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() +) { + override fun addMasterUid(): String { + return "visualization_uid" + } + + override fun buildObject(): DataDimensionItem { + return DataDimensionItemSamples.dataDimensionItem() + } + + override fun buildObjectWithOtherMasterUid(): DataDimensionItem { + return DataDimensionItemSamples.dataDimensionItem().toBuilder() + .visualization("visualization_uid_2") + .build() + } +} diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/DataDimensionItemSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/DataDimensionItemSamples.kt new file mode 100644 index 0000000000..2593f7f933 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/DataDimensionItemSamples.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.visualization + +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.visualization.DataDimensionItem +import org.hisp.dhis.android.core.visualization.DataDimensionItemType + +object DataDimensionItemSamples { + + fun dataDimensionItem(): DataDimensionItem = + DataDimensionItem.builder() + .id(1L) + .visualization("visualization_uid") + .dataDimensionItemType(DataDimensionItemType.DATA_ELEMENT) + .dataElement(ObjectWithUid.create("data_element_uid")) + .build() +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java new file mode 100644 index 0000000000..d1d19e110c --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2021, 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.core.visualization.internal; + +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; +import org.hisp.dhis.android.core.arch.handlers.internal.IdentifiableHandlerImpl; +import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler; +import org.hisp.dhis.android.core.common.ObjectWithUid; +import org.hisp.dhis.android.core.visualization.CategoryDimension; +import org.hisp.dhis.android.core.visualization.DataDimensionItem; +import org.hisp.dhis.android.core.visualization.Visualization; +import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(JUnit4.class) +public class VisualizationHandlerShould { + + @Mock + private IdentifiableObjectStore visualizationStore; + + @Mock + private LinkHandler visualizationCategoryDimensionLinkHandler; + + @Mock + private LinkHandler dataDimensionItemHandler; + + @Mock + private DataDimensionItem dataDimensionItem; + + @Mock + private CategoryDimension categoryDimension; + + @Mock + private ObjectWithUid category; + + @Mock + private ObjectWithUid categoryOption; + + @Mock + private Visualization visualization; + + @Mock + private List categories; + + // object to test + private VisualizationHandler visualizationHandler; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.openMocks(this); + visualizationHandler = new VisualizationHandler( + visualizationStore, + visualizationCategoryDimensionLinkHandler, + dataDimensionItemHandler); + + List dataDimensionItems = new ArrayList<>(); + dataDimensionItems.add(dataDimensionItem); + List categoryDimensions = new ArrayList<>(); + categories = new ArrayList<>(); + categories.add(category); + categoryDimensions.add(categoryDimension); + + when(visualization.dataDimensionItems()).thenReturn(dataDimensionItems); + when(visualizationStore.updateOrInsert(any())).thenReturn(HandleAction.Insert); + when(visualization.uid()).thenReturn("visualization_uid"); + when(category.uid()).thenReturn("category_uid"); + when(categoryDimension.category()).thenReturn(category); + when(visualization.categoryDimensions()).thenReturn(categoryDimensions); + } + + @Test + public void extend_identifiable_sync_handler_impl() { + IdentifiableHandlerImpl genericHandler = new VisualizationHandler + (visualizationStore, visualizationCategoryDimensionLinkHandler, dataDimensionItemHandler); + } + + @Test + public void call_data_dimension_items_handler() { + visualizationHandler.handle(visualization); + verify(dataDimensionItemHandler).handleMany(any(), any(), any()); + } + + @Test + public void call_category_dimensions_link_handler() { + visualizationHandler.handle(visualization); + verify(visualizationCategoryDimensionLinkHandler).handleMany(any(), any(), any()); + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java new file mode 100644 index 0000000000..3967ff53ad --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.categoryDimension; + +import org.hisp.dhis.android.core.visualization.CategoryDimension; +import org.hisp.dhis.android.testapp.arch.BasePublicAccessShould; +import org.mockito.Mock; + +public class CategoryDimensionPublicAccessShould extends BasePublicAccessShould { + + @Mock + private CategoryDimension object; + + @Override + public CategoryDimension object() { + return object; + } + + @Override + public void has_public_create_method() { + CategoryDimension.create(null); + } + + @Override + public void has_public_builder_method() { + CategoryDimension.builder(); + } + + @Override + public void has_public_to_builder_method() { + object().toBuilder(); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/testapp/visualization/DataDimensionItemPublicAccessShould.java b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/DataDimensionItemPublicAccessShould.java new file mode 100644 index 0000000000..b94911c6da --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/DataDimensionItemPublicAccessShould.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.visualization; + +import org.hisp.dhis.android.core.visualization.DataDimensionItem; +import org.hisp.dhis.android.testapp.arch.BasePublicAccessShould; +import org.mockito.Mock; + +public class DataDimensionItemPublicAccessShould extends BasePublicAccessShould { + + @Mock + private DataDimensionItem object; + + @Override + public DataDimensionItem object() { + return object; + } + + @Override + public void has_public_create_method() { + DataDimensionItem.create(null); + } + + @Override + public void has_public_builder_method() { + DataDimensionItem.builder(); + } + + @Override + public void has_public_to_builder_method() { + object().toBuilder(); + } +} \ No newline at end of file From 0539f6e352537c2b310b83f3cb1491daaea2db1d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 15:31:44 +0200 Subject: [PATCH 180/308] [androsdk-1383] Add a todo on metadataCall to pass the visualization uids --- .../org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt index 05246fb97e..523ece105e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt @@ -140,7 +140,8 @@ class MetadataCall @Inject internal constructor( progressManager.increaseProgress(Category::class.java, false) }, visualizationDownloader.downloadMetadata( - setOf("visualization_uid") + // TODO Add visualization uids to download + emptySet() ).map { progressManager.increaseProgress(Visualization::class.java, false) } From d01ebbebcc3aa09d5e32658b8865b99e72a28545 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 15:50:40 +0200 Subject: [PATCH 181/308] [androsdk-1383] Apply ktlinformat --- .../DataDimensionItemStoreIntegrationShould.kt | 8 ++++---- ...ationCategoryDimensionLinkStoreIntegrationShould.kt | 8 ++++---- .../custom/internal/RelativePeriodsColumnAdapter.kt | 2 +- .../core/visualization/internal/VisualizationFields.kt | 1 - .../visualization/internal/VisualizationHandler.kt | 4 ++-- .../internal/VisualizationInternalModule.kt | 2 +- .../visualization/internal/VisualizationModuleImpl.kt | 2 +- .../VisualizationCategoryDimensionLinkSamples.kt | 10 +++++----- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt index df22952e77..8646efd433 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStoreIntegrationShould.kt @@ -38,10 +38,10 @@ import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) class DataDimensionItemStoreIntegrationShould : LinkStoreAbstractIntegrationShould( - DataDimensionItemStore.create(TestDatabaseAdapterFactory.get()), - DataDimensionItemTableInfo.TABLE_INFO, - TestDatabaseAdapterFactory.get() -) { + DataDimensionItemStore.create(TestDatabaseAdapterFactory.get()), + DataDimensionItemTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() + ) { override fun addMasterUid(): String { return "visualization_uid" } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt index 274795fb16..7fdc5afd2c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStoreIntegrationShould.kt @@ -38,10 +38,10 @@ import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) class VisualizationCategoryDimensionLinkStoreIntegrationShould : LinkStoreAbstractIntegrationShould( - VisualizationCategoryDimensionLinkStore.create(TestDatabaseAdapterFactory.get()), - VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO, - TestDatabaseAdapterFactory.get() -) { + VisualizationCategoryDimensionLinkStore.create(TestDatabaseAdapterFactory.get()), + VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() + ) { override fun addMasterUid(): String { return VisualizationCategoryDimensionLinkSamples.visualizationCategoryDimensionLinkSamples().visualization() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt index 781caf7c52..c8e9b5077a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -44,4 +44,4 @@ internal class RelativePeriodsColumnAdapter : JSONObjectHashMapColumnAdapter, private val visualizationCategoryDimensionLinkHandler: - LinkHandler, + LinkHandler, private val dataDimensionItemHandler: LinkHandler ) : IdentifiableHandlerImpl(store) { @@ -73,4 +73,4 @@ internal class VisualizationHandler @Inject constructor( it.toBuilder().visualization(o.uid()).build() } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt index 2954eb7610..8794551e04 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt @@ -36,4 +36,4 @@ import javax.inject.Inject @Reusable internal class VisualizationInternalModule @Inject internal constructor( @field:VisibleForTesting val visualizationCall: UidsCall -) \ No newline at end of file +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt index d2dfd7c0dd..76dabca2f0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt @@ -38,4 +38,4 @@ internal class VisualizationModuleImpl @Inject internal constructor( ) : VisualizationModule { override fun visualizations(): VisualizationCollectionRepository = visualizations -} \ No newline at end of file +} diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt index 7a8c04f3f3..51d3161136 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/visualization/VisualizationCategoryDimensionLinkSamples.kt @@ -33,9 +33,9 @@ object VisualizationCategoryDimensionLinkSamples { fun visualizationCategoryDimensionLinkSamples(): VisualizationCategoryDimensionLink = VisualizationCategoryDimensionLink.builder() - .id(1L) - .visualization("visualization_uid") - .category("category_uid") - .categoryOption("category_option_uid") - .build() + .id(1L) + .visualization("visualization_uid") + .category("category_uid") + .categoryOption("category_option_uid") + .build() } From 64a5c7370d1a31f566379bc8e0a9f6a72fe4d993 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 16:24:02 +0200 Subject: [PATCH 182/308] [androsdk-1383] Check style --- ...pColumnAdapter.kt => JSONObjectMapColumnAdapter.kt} | 10 +++++----- .../custom/internal/RelativePeriodsColumnAdapter.kt | 8 ++++---- .../dhis/android/core/visualization/Visualization.java | 7 ++++--- .../visualization/internal/DataDimensionItemStore.kt | 1 + .../VisualizationCategoryDimensionLinkStore.kt | 1 + 5 files changed, 15 insertions(+), 12 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/{JSONObjectHashMapColumnAdapter.kt => JSONObjectMapColumnAdapter.kt} (90%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt similarity index 90% rename from core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt rename to core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt index 7630eb8bec..b840b8bd1b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectHashMapColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt @@ -34,10 +34,10 @@ import com.fasterxml.jackson.databind.JsonMappingException import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory -internal abstract class JSONObjectHashMapColumnAdapter : ColumnTypeAdapter> { - protected abstract fun getObjectClass(): Class> +internal abstract class JSONObjectMapColumnAdapter : ColumnTypeAdapter> { + protected abstract fun getObjectClass(): Class> - override fun fromCursor(cursor: Cursor, columnName: String): HashMap { + override fun fromCursor(cursor: Cursor, columnName: String): Map { val columnIndex = cursor.getColumnIndex(columnName) val str = cursor.getString(columnIndex) return try { @@ -53,7 +53,7 @@ internal abstract class JSONObjectHashMapColumnAdapter : ColumnTypeAdapter } } - override fun toContentValues(contentValues: ContentValues, columnName: String, o: HashMap?) { + override fun toContentValues(contentValues: ContentValues, columnName: String, o: Map?) { try { contentValues.put(columnName, serialize(o)) } catch (e: JsonProcessingException) { @@ -61,5 +61,5 @@ internal abstract class JSONObjectHashMapColumnAdapter : ColumnTypeAdapter } } - abstract fun serialize(o: HashMap?): String? + abstract fun serialize(o: Map?): String? } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt index c8e9b5077a..7f0ccd165c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -30,15 +30,15 @@ package org.hisp.dhis.android.core.arch.db.adapters.custom.internal import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory import org.hisp.dhis.android.core.common.RelativePeriod -internal class RelativePeriodsColumnAdapter : JSONObjectHashMapColumnAdapter() { - override fun getObjectClass(): Class> { +internal class RelativePeriodsColumnAdapter : JSONObjectMapColumnAdapter() { + override fun getObjectClass(): Class> { return HashMap().javaClass } - override fun serialize(o: HashMap?): String? = RelativePeriodsColumnAdapter.serialize(o) + override fun serialize(o: Map?): String? = RelativePeriodsColumnAdapter.serialize(o) companion object { - fun serialize(o: HashMap?): String? { + fun serialize(o: Map?): String? { return o?.let { ObjectMapperFactory.objectMapper().writeValueAsString(it.filter { it.value }) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java index ec8f159d1f..269abd3d47 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/Visualization.java @@ -53,11 +53,12 @@ import org.hisp.dhis.android.core.common.ObjectWithUid; import org.hisp.dhis.android.core.common.RelativePeriod; -import java.util.HashMap; import java.util.List; +import java.util.Map; @AutoValue @JsonDeserialize(builder = $$AutoValue_Visualization.Builder.class) +@SuppressWarnings({"PMD.ExcessivePublicCount"}) public abstract class Visualization extends BaseIdentifiableObject implements CoreObject { @Nullable @@ -151,7 +152,7 @@ public abstract class Visualization extends BaseIdentifiableObject implements Co @Nullable @JsonProperty() @ColumnAdapter(RelativePeriodsColumnAdapter.class) - public abstract HashMap relativePeriods(); + public abstract Map relativePeriods(); @Nullable @JsonProperty() @@ -263,7 +264,7 @@ public static abstract class Builder extends BaseIdentifiableObject.Builder relativePeriods); + public abstract Builder relativePeriods(Map relativePeriods); public abstract Builder categoryDimensions(List categoryDimensions); diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt index 51eb06674d..a33be162f3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemStore.kt @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.arch.helpers.UidsHelper import org.hisp.dhis.android.core.visualization.DataDimensionItem import org.hisp.dhis.android.core.visualization.DataDimensionItemTableInfo +@Suppress("MagicNumber") internal object DataDimensionItemStore { private val BINDER = StatementBinder { o: DataDimensionItem, w: StatementWrapper -> w.bind(1, o.visualization()) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt index 3e678f89da..c558e1772f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCategoryDimensionLinkStore.kt @@ -35,6 +35,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo +@Suppress("MagicNumber") internal object VisualizationCategoryDimensionLinkStore { private val BINDER = StatementBinder { o: VisualizationCategoryDimensionLink, w: StatementWrapper -> w.bind(1, o.visualization()) From a7c77aa84ce18289a94b828c68c2903ef64daafd Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 14 Jul 2021 16:42:10 +0200 Subject: [PATCH 183/308] [androsdk-1383] Add categories and data imensions to the visualization fields --- .../core/visualization/internal/VisualizationFields.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt index 3e978de6ac..3729144a4a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt @@ -63,11 +63,11 @@ internal object VisualizationFields { fh.field(VisualizationTableInfo.Columns.DISPLAY_DENSITY), fh.field(VisualizationTableInfo.Columns.DIGIT_GROUP_SEPARATOR), fh.field(VisualizationTableInfo.Columns.RELATIVE_PERIODS), - // fh.nestedField(CATEGORY_DIMENSIONS).with(CategoryDimensionFields.allFields), + fh.nestedField(CATEGORY_DIMENSIONS), fh.nestedField(VisualizationTableInfo.Columns.FILTER_DIMENSIONS), fh.nestedField(VisualizationTableInfo.Columns.ROW_DIMENSIONS), fh.nestedField(VisualizationTableInfo.Columns.COLUMN_DIMENSIONS), - // fh.nestedField(DATA_DIMENSION_ITEMS).with(DataDimensionItemsFields.allFields), + fh.nestedField(DATA_DIMENSION_ITEMS), fh.nestedField(VisualizationTableInfo.Columns.ORGANISATION_UNIT_LEVELS), fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT), fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT_CHILDREN), From 93fc7c4a8b05b50cb5c0742ba787ecedd3d2de40 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Jul 2021 11:52:19 +0200 Subject: [PATCH 184/308] [androsdk-1383] Fix migrations --- core/src/main/assets/migrations/104.sql | 2 +- core/src/main/assets/snapshots/104.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/assets/migrations/104.sql b/core/src/main/assets/migrations/104.sql index f91fe413b8..7a4b6ec4e8 100644 --- a/core/src/main/assets/migrations/104.sql +++ b/core/src/main/assets/migrations/104.sql @@ -1,3 +1,3 @@ CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); -CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType)); \ No newline at end of file +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/104.sql b/core/src/main/assets/snapshots/104.sql index 9bad57a0a3..ad1c684d00 100644 --- a/core/src/main/assets/snapshots/104.sql +++ b/core/src/main/assets/snapshots/104.sql @@ -113,4 +113,4 @@ CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerTyp CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); -CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType)); +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); From af5c4651c0873f63d57f012d9b64fff2737ae33d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Jul 2021 11:53:14 +0200 Subject: [PATCH 185/308] [androsdk-1383] Add nested fields to VisualizationFields --- .../DataDimensionItemTableInfo.kt | 10 +++- .../internal/CategoryDimensionFields.kt | 46 ++++++++++++++++ .../internal/DataDimensionItemFields.kt | 55 +++++++++++++++++++ .../internal/VisualizationFields.kt | 12 ++-- 4 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/CategoryDimensionFields.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemFields.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt index 32caf9887c..333766140c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt @@ -64,7 +64,15 @@ object DataDimensionItemTableInfo { return CollectionsHelper.appendInNewArray( super.all(), VISUALIZATION, - DATA_DIMENSION_ITEM_TYPE + DATA_DIMENSION_ITEM_TYPE, + INDICATOR, + DATA_ELEMENT, + DATA_ELEMENT_OPERAND, + REPORTING_RATE, + PROGRAM_INDICATOR, + PROGRAM_DATA_ELEMENT, + PROGRAM_ATTRIBUTE, + VALIDATION_RULE ) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/CategoryDimensionFields.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/CategoryDimensionFields.kt new file mode 100644 index 0000000000..dfb6d5d0ef --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/CategoryDimensionFields.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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), + fh.field(* 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.api.fields.internal.Fields +import org.hisp.dhis.android.core.arch.fields.internal.FieldsHelper +import org.hisp.dhis.android.core.visualization.CategoryDimension + +internal object CategoryDimensionFields { + internal const val CATEGORY = "category" + internal const val CATEGORY_OPTIONS = "categoryOptions" + private val fh = FieldsHelper() + + val allFields: Fields = + Fields.builder() + .fields( + fh.nestedFieldWithUid(CATEGORY), + fh.nestedFieldWithUid(CATEGORY_OPTIONS) + ) + .build() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemFields.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemFields.kt new file mode 100644 index 0000000000..451837b279 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/DataDimensionItemFields.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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), + fh.field(* 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.core.visualization.internal + +import org.hisp.dhis.android.core.arch.api.fields.internal.Fields +import org.hisp.dhis.android.core.arch.fields.internal.FieldsHelper +import org.hisp.dhis.android.core.visualization.DataDimensionItem +import org.hisp.dhis.android.core.visualization.DataDimensionItemTableInfo +import org.hisp.dhis.android.core.visualization.DataDimensionItemType + +internal object DataDimensionItemFields { + internal const val CATEGORY = "category" + internal const val CATEGORY_OPTIONS = "categoryOptions" + private val fh = FieldsHelper() + + val allFields: Fields = + Fields.builder() + .fields( + fh.field(DataDimensionItemTableInfo.Columns.DATA_DIMENSION_ITEM_TYPE), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.INDICATOR), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.DATA_ELEMENT), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.DATA_ELEMENT_OPERAND), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.REPORTING_RATE), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.PROGRAM_INDICATOR), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.PROGRAM_DATA_ELEMENT), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.PROGRAM_ATTRIBUTE), + fh.nestedFieldWithUid(DataDimensionItemTableInfo.Columns.VALIDATION_RULE) + ) + .build() +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt index 3729144a4a..a47d27036d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationFields.kt @@ -63,12 +63,12 @@ internal object VisualizationFields { fh.field(VisualizationTableInfo.Columns.DISPLAY_DENSITY), fh.field(VisualizationTableInfo.Columns.DIGIT_GROUP_SEPARATOR), fh.field(VisualizationTableInfo.Columns.RELATIVE_PERIODS), - fh.nestedField(CATEGORY_DIMENSIONS), - fh.nestedField(VisualizationTableInfo.Columns.FILTER_DIMENSIONS), - fh.nestedField(VisualizationTableInfo.Columns.ROW_DIMENSIONS), - fh.nestedField(VisualizationTableInfo.Columns.COLUMN_DIMENSIONS), - fh.nestedField(DATA_DIMENSION_ITEMS), - fh.nestedField(VisualizationTableInfo.Columns.ORGANISATION_UNIT_LEVELS), + fh.nestedField(CATEGORY_DIMENSIONS).with(CategoryDimensionFields.allFields), + fh.field(VisualizationTableInfo.Columns.FILTER_DIMENSIONS), + fh.field(VisualizationTableInfo.Columns.ROW_DIMENSIONS), + fh.field(VisualizationTableInfo.Columns.COLUMN_DIMENSIONS), + fh.nestedField(DATA_DIMENSION_ITEMS).with(DataDimensionItemFields.allFields), + fh.field>(VisualizationTableInfo.Columns.ORGANISATION_UNIT_LEVELS), fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT), fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT_CHILDREN), fh.field(VisualizationTableInfo.Columns.USER_ORGANISATION_UNIT_GRAND_CHILDREN), From d64f78aea2b764aae8b265f964412f7f0ff74338 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Jul 2021 11:53:31 +0200 Subject: [PATCH 186/308] [androsdk-1383] Remove data read check --- .../core/visualization/internal/VisualizationCall.kt | 3 --- .../core/visualization/internal/VisualizationService.kt | 1 - .../sharedTest/resources/visualization/visualizations.json | 7 ------- 3 files changed, 11 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt index 3185c91a0f..1b06a9ae6a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt @@ -32,7 +32,6 @@ import io.reactivex.Single import org.hisp.dhis.android.core.arch.api.executors.internal.APIDownloader import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall import org.hisp.dhis.android.core.arch.handlers.internal.Handler -import org.hisp.dhis.android.core.common.internal.DataAccessFields import org.hisp.dhis.android.core.visualization.Visualization import javax.inject.Inject @@ -48,7 +47,6 @@ internal class VisualizationCall @Inject constructor( } override fun download(uids: Set): Single> { - val accessDataReadFilter = "access." + DataAccessFields.read.eq(true).generateString() return apiDownloader.downloadPartitioned( uids, MAX_UID_LIST_SIZE, @@ -57,7 +55,6 @@ internal class VisualizationCall @Inject constructor( service.getVisualizations( VisualizationFields.allFields, VisualizationFields.uid.`in`(partitionUids), - accessDataReadFilter, paging = false ) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt index 01950a565c..85b3f06fe8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationService.kt @@ -43,7 +43,6 @@ internal interface VisualizationService { fun getVisualizations( @Query("fields") @Which fields: Fields, @Query("filter") @Where uids: Filter, - @Query("filter") accessDataReadFilter: String, @Query("paging") paging: Boolean ): Single> } diff --git a/core/src/sharedTest/resources/visualization/visualizations.json b/core/src/sharedTest/resources/visualization/visualizations.json index 91a5f27899..72b6dbf25c 100644 --- a/core/src/sharedTest/resources/visualization/visualizations.json +++ b/core/src/sharedTest/resources/visualization/visualizations.json @@ -1,11 +1,4 @@ { - "pager": { - "page": 1, - "pageCount": 6, - "total": 271, - "pageSize": 50, - "nextPage": "https://play.dhis2.org/2.36.3/api/visualizations.json?page=2" - }, "visualizations": [ { "id": "PYBH8ZaAQnC", From 770f552d04ac4fb2159c5dddf61a913c1afea98e Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 15 Jul 2021 12:32:21 +0200 Subject: [PATCH 187/308] [androsdk-1383] Update migration and snapshot to 105 --- core/src/main/assets/migrations/105.sql | 3 +++ core/src/main/assets/snapshots/{104.sql => 105.sql} | 0 .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 core/src/main/assets/migrations/105.sql rename core/src/main/assets/snapshots/{104.sql => 105.sql} (100%) diff --git a/core/src/main/assets/migrations/105.sql b/core/src/main/assets/migrations/105.sql new file mode 100644 index 0000000000..7a4b6ec4e8 --- /dev/null +++ b/core/src/main/assets/migrations/105.sql @@ -0,0 +1,3 @@ +CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/104.sql b/core/src/main/assets/snapshots/105.sql similarity index 100% rename from core/src/main/assets/snapshots/104.sql rename to core/src/main/assets/snapshots/105.sql diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index 5aafddb5ee..75dd2ca255 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 104; + static final int VERSION = 105; private final AssetManager assetManager; private final int targetVersion; From 6501572ec01d7cdde01b4b81f45babfc9225e02b Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 14 Jul 2021 16:50:05 +0200 Subject: [PATCH 188/308] [ANDROSDK-1384] Add @JvmField annotation to TABLE_INFO --- .../core/settings/AnalyticsDhisVisualizationTableInfo.kt | 1 + .../android/core/settings/internal/AnalyticsSettingCall.kt | 4 +--- .../android/core/settings/internal/SettingModuleWiper.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt index f20383e452..0b61f3d3c9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/AnalyticsDhisVisualizationTableInfo.kt @@ -35,6 +35,7 @@ import org.hisp.dhis.android.core.common.IdentifiableColumns object AnalyticsDhisVisualizationTableInfo { + @JvmField val TABLE_INFO: TableInfo = object : TableInfo() { override fun name(): String { return "AnalyticsDhisVisualization" diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt index 338832993e..b32c577b97 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/AnalyticsSettingCall.kt @@ -75,8 +75,6 @@ internal class AnalyticsSettingCall @Inject constructor( SettingsAppHelper.getAnalyticsDhisVisualizations(it) } ?: emptyList() - item?.dhisVisualizations()?.let { - analyticsDhisVisualizationsSettingHandler.handleMany(analyticsDhisVisualizations) - } + analyticsDhisVisualizationsSettingHandler.handleMany(analyticsDhisVisualizations) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java index 8da64943b0..e1c490436b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/SettingModuleWiper.java @@ -71,7 +71,7 @@ public void wipeMetadata() { tableWiper.wipeTable(AnalyticsTeiIndicatorTableInfo.TABLE_INFO); tableWiper.wipeTable(AnalyticsTeiAttributeTableInfo.TABLE_INFO); tableWiper.wipeTable(UserSettingsTableInfo.TABLE_INFO); - tableWiper.wipeTable(AnalyticsDhisVisualizationTableInfo.INSTANCE.getTABLE_INFO()); + tableWiper.wipeTable(AnalyticsDhisVisualizationTableInfo.TABLE_INFO); } @Override From 2d31b002eabb5296a5bd14a1b8d7bc1a940be4ae Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 16 Jul 2021 08:12:10 +0200 Subject: [PATCH 189/308] [androsdk-1383] Rebase develop migrations --- core/src/main/assets/migrations/105.sql | 6 +----- core/src/main/assets/migrations/106.sql | 4 ++++ core/src/main/assets/snapshots/{105.sql => 106.sql} | 0 .../arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 core/src/main/assets/migrations/106.sql rename core/src/main/assets/snapshots/{105.sql => 106.sql} (100%) diff --git a/core/src/main/assets/migrations/105.sql b/core/src/main/assets/migrations/105.sql index 93d5052e56..b0386950a5 100644 --- a/core/src/main/assets/migrations/105.sql +++ b/core/src/main/assets/migrations/105.sql @@ -1,5 +1 @@ -CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); - -CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); -CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); -CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); \ No newline at end of file +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); \ No newline at end of file diff --git a/core/src/main/assets/migrations/106.sql b/core/src/main/assets/migrations/106.sql new file mode 100644 index 0000000000..a4e693a7e9 --- /dev/null +++ b/core/src/main/assets/migrations/106.sql @@ -0,0 +1,4 @@ +# New tables for visualization objects +CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/105.sql b/core/src/main/assets/snapshots/106.sql similarity index 100% rename from core/src/main/assets/snapshots/105.sql rename to core/src/main/assets/snapshots/106.sql diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index 75dd2ca255..a5251c21c5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 105; + static final int VERSION = 106; private final AssetManager assetManager; private final int targetVersion; From a0cdd06e923ccc6a31feb2b12dbd7db656d76f8d Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 16 Jul 2021 08:22:23 +0200 Subject: [PATCH 190/308] [androsdk-1383] Sort kotlin imports --- .../visualization/internal/VisualizationEndpointCallShould.kt | 2 +- .../org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt | 2 +- .../android/core/visualization/internal/VisualizationCall.kt | 2 +- .../android/core/visualization/internal/VisualizationHandler.kt | 2 +- .../core/visualization/internal/VisualizationInternalModule.kt | 2 +- .../visualization/internal/VisualizationModuleDownloader.kt | 2 +- .../core/visualization/internal/VisualizationModuleImpl.kt | 2 +- .../core/visualization/internal/VisualizationModuleWiper.kt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt index 7c67f104da..880c6f8eaa 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEndpointCallShould.kt @@ -30,13 +30,13 @@ package org.hisp.dhis.android.core.visualization.internal import com.google.common.collect.Lists import com.google.common.truth.Truth import io.reactivex.Single +import java.util.* import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyEnqueable import org.hisp.dhis.android.core.utils.runner.D2JunitRunner import org.hisp.dhis.android.core.visualization.Visualization import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith -import java.util.* @RunWith(D2JunitRunner::class) class VisualizationEndpointCallShould : BaseMockIntegrationTestEmptyEnqueable() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt index 523ece105e..b1fa1fd422 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt @@ -31,6 +31,7 @@ import dagger.Reusable import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.RxAPICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager @@ -61,7 +62,6 @@ import org.hisp.dhis.android.core.user.User import org.hisp.dhis.android.core.user.internal.UserModuleDownloader import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.internal.VisualizationModuleDownloader -import javax.inject.Inject @Suppress("LongParameterList") @Reusable diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt index 1b06a9ae6a..a38c8495c7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt @@ -29,11 +29,11 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APIDownloader import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.visualization.Visualization -import javax.inject.Inject @Reusable internal class VisualizationCall @Inject constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index 586cc76608..871efb6efa 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.arch.handlers.internal.IdentifiableHandlerImpl @@ -37,7 +38,6 @@ import org.hisp.dhis.android.core.visualization.CategoryDimension import org.hisp.dhis.android.core.visualization.DataDimensionItem import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink -import javax.inject.Inject @Reusable internal class VisualizationHandler @Inject constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt index 8794551e04..2394af507a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationInternalModule.kt @@ -29,9 +29,9 @@ package org.hisp.dhis.android.core.visualization.internal import androidx.annotation.VisibleForTesting import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall import org.hisp.dhis.android.core.visualization.Visualization -import javax.inject.Inject @Reusable internal class VisualizationInternalModule @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt index bcbb341009..10e6cedf73 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt @@ -29,10 +29,10 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall import org.hisp.dhis.android.core.arch.modules.internal.MetadataModuleByUidDownloader import org.hisp.dhis.android.core.visualization.Visualization -import javax.inject.Inject @Reusable class VisualizationModuleDownloader @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt index 76dabca2f0..07010c03f6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleImpl.kt @@ -28,9 +28,9 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.visualization.VisualizationCollectionRepository import org.hisp.dhis.android.core.visualization.VisualizationModule -import javax.inject.Inject @Reusable internal class VisualizationModuleImpl @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt index 36f56790bb..0c85cf51d4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt @@ -28,11 +28,11 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo import org.hisp.dhis.android.core.visualization.VisualizationTableInfo import org.hisp.dhis.android.core.wipe.internal.ModuleWiper import org.hisp.dhis.android.core.wipe.internal.TableWiper -import javax.inject.Inject @Reusable class VisualizationModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { From 9682909e4550f7b505613b2d4735d39b438c60df Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 27 Apr 2021 17:09:34 +0200 Subject: [PATCH 191/308] [ANDROSDK-1312] Refactor in event call to ease deletions --- .../internal/EventTrackerImporterPostCall.kt | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index cbc3de3f9a..740398fd51 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -58,23 +58,7 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( ): Observable { return Observable.defer { val eventsToPost = payloadGenerator.getEvents(events) - stateManager.markObjectsAs(eventsToPost, State.UPLOADING) - Single.fromCallable { - val eventPayload = NewTrackerImporterEventPayload(eventsToPost) - val res = apiCallExecutor.executeObjectCall( - service.postEvents( - eventPayload, ATOMIC_MODE_OBJECT, - IMPORT_STRATEGY_CREATE_AND_UPDATE - ) - ) - val jobId = res.response().uid() - jobObjectHandler.handleMany(generateJobObjects(eventsToPost, jobId)) - jobId - }.doOnError { - stateManager.markObjectsAs(eventsToPost, DataStateHelper.errorIfOnline(it)) - }.flatMapObservable { - jobQueryCall.queryJob(it) - } + doPostCall(eventsToPost, IMPORT_STRATEGY_CREATE_AND_UPDATE) } } @@ -90,4 +74,25 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( .build() } } + + private fun doPostCall(events: List, importStrategy: String): Observable { + stateManager.markObjectsAs(events, State.UPLOADING) + return Single.fromCallable { + doPostCallInternal(events, importStrategy) + }.doOnError { + stateManager.markObjectsAs(events, DataStateHelper.errorIfOnline(it)) + }.flatMapObservable { + jobQueryCall.queryJob(it) + } + } + + private fun doPostCallInternal(events: List, importStrategy: String): String { + val eventPayload = NewTrackerImporterEventPayload(events) + val res = apiCallExecutor.executeObjectCall( + service.postEvents(eventPayload, ATOMIC_MODE_OBJECT, importStrategy) + ) + val jobId = res.response().uid() + jobObjectHandler.handleMany(generateJobObjects(events, jobId)) + return jobId + } } From 006928207171969539585121609d418a1e034816 Mon Sep 17 00:00:00 2001 From: luis Date: Tue, 27 Apr 2021 17:14:20 +0200 Subject: [PATCH 192/308] [ANDROSDK-1312] Implement deletion of events --- .../internal/EventTrackerImporterPostCall.kt | 24 ++++++++++++------- .../internal/TrackerImporterService.kt | 1 + 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index 740398fd51..36412e670e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -58,7 +58,11 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( ): Observable { return Observable.defer { val eventsToPost = payloadGenerator.getEvents(events) - doPostCall(eventsToPost, IMPORT_STRATEGY_CREATE_AND_UPDATE) + val partition = eventsToPost.partition { it.deleted()!! } + Observable.concat( + doPostCall(partition.first, IMPORT_STRATEGY_DELETE), + doPostCall(partition.second, IMPORT_STRATEGY_CREATE_AND_UPDATE) + ) } } @@ -76,13 +80,17 @@ internal class EventTrackerImporterPostCall @Inject internal constructor( } private fun doPostCall(events: List, importStrategy: String): Observable { - stateManager.markObjectsAs(events, State.UPLOADING) - return Single.fromCallable { - doPostCallInternal(events, importStrategy) - }.doOnError { - stateManager.markObjectsAs(events, DataStateHelper.errorIfOnline(it)) - }.flatMapObservable { - jobQueryCall.queryJob(it) + return if (events.isEmpty()) { + Observable.empty() + } else { + stateManager.markObjectsAs(events, State.UPLOADING) + Single.fromCallable { + doPostCallInternal(events, importStrategy) + }.doOnError { + stateManager.markObjectsAs(events, DataStateHelper.errorIfOnline(it)) + }.flatMapObservable { + jobQueryCall.queryJob(it) + } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt index f920eab6df..c783210d8f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt @@ -41,6 +41,7 @@ internal const val ATOMIC_MODE_OBJECT = "OBJECT" internal const val IMPORT_STRATEGY = "importStrategy" internal const val IMPORT_STRATEGY_CREATE_AND_UPDATE = "CREATE_AND_UPDATE" +internal const val IMPORT_STRATEGY_DELETE = "DELETE" internal const val JOB_ID = "jobId" internal interface TrackerImporterService { From ec3f9534d1f5191b223babfc090b24da57ca93ae Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 28 Apr 2021 14:54:47 +0200 Subject: [PATCH 193/308] [ANDROSDK-1312] Add delete real integration test --- .../EventPostCallRealIntegrationShould.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java index 7ce9542bbf..70fddc289f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostCallRealIntegrationShould.java @@ -134,6 +134,19 @@ public void pull_event_with_correct_category_combo_after_be_pushed() throws Exce assertThatEventPushedIsDownloaded(pushedEvent); } + //@Test + public void pull_events_delete_with_repository_and_post() throws Exception { + downloadMetadata(); + + d2.eventModule().eventDownloader().limit(10).blockingDownload(); + + String uid = d2.eventModule().events().one().blockingGet().uid(); + + d2.eventModule().events().uid(uid).blockingDelete(); + + d2.eventModule().events().blockingUpload(); + } + // commented out since it is a flaky test that works against a real server. //@Test public void pull_two_events_with_correct_category_combo_after_be_pushed() throws Exception { From 85f57d875a0fa9ef84dfee2dee582d0a2afb5731 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 16 Jul 2021 08:57:55 +0200 Subject: [PATCH 194/308] [ANDROSDK-1312] Support granular TEI sync --- ...InstancePostCallRealIntegrationShould.java | 6 - .../NewTrackerImporterEnrollment.java | 10 ++ ...NewTrackerImporterEnrollmentTransformer.kt | 1 + .../internal/EventTrackerImporterPostCall.kt | 3 +- .../NewTrackerImporterTrackedEntity.java | 11 ++ ...rackerImporterTranckedEntityTransformer.kt | 1 + .../internal/NewTrackerImporterPayload.kt} | 14 +- ...kt => NewTrackerImporterPayloadWrapper.kt} | 7 +- ...porterTrackedEntityPostPayloadGenerator.kt | 75 ++-------- ...erTrackedEntityPostPayloadGeneratorTask.kt | 138 ++++++++++++++++++ ...erImporterTrackedEntityPostStateManager.kt | 22 ++- .../tracker/importer/internal/JobQueryCall.kt | 12 +- ...edEntityInstanceTrackerImporterPostCall.kt | 67 ++++++--- .../internal/TrackerImporterService.kt | 7 +- 14 files changed, 255 insertions(+), 119 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/{event/internal/NewTrackerImporterEventPayload.kt => trackedentity/internal/NewTrackerImporterPayload.kt} (72%) rename core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/{NewTrackerImporterTrackedEntityPayload.kt => NewTrackerImporterPayloadWrapper.kt} (88%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java index 7db558c6c6..ff8c68cff1 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCallRealIntegrationShould.java @@ -474,15 +474,9 @@ public void post_a_tei_and_delete_one_event() throws Exception { downloadMetadata(); d2.trackedEntityModule().trackedEntityInstanceDownloader().byUid().eq("LxMVYhJm3Jp").blockingDownload(); - TrackedEntityInstance tei = trackedEntityInstanceStore.selectFirst(); - - Enrollment enrollment = enrollmentStore.selectFirst(); - Event event = eventStore.selectFirst(); String eventUid = event.uid(); - trackedEntityInstanceStore.setSyncState(tei.uid(), State.TO_UPDATE); - enrollmentStore.setSyncState(enrollment.uid(), State.TO_UPDATE); d2.eventModule().events().uid(eventUid).blockingDelete(); d2.trackedEntityModule().trackedEntityInstances().blockingUpload(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java index 176123fa9d..f8166b9d3b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java @@ -43,12 +43,15 @@ import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbDateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbGeometryColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.EnrollmentStatusColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNewTrackerImporterEventListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNewTrackerImporterNoteListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreRelationshipListColumnAdapter; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentFields; import org.hisp.dhis.android.core.event.NewTrackerImporterEvent; import org.hisp.dhis.android.core.note.NewTrackerImporterNote; @@ -127,6 +130,11 @@ public abstract class NewTrackerImporterEnrollment extends BaseDeletableDataObje @ColumnAdapter(DbGeometryColumnAdapter.class) public abstract Geometry geometry(); + @Nullable + @ColumnName(DataColumns.AGGREGATED_SYNC_STATE) + @ColumnAdapter(StateColumnAdapter.class) + public abstract State aggregatedSyncState(); + @Nullable @JsonProperty() @ColumnAdapter(IgnoreNewTrackerImporterEventListColumnAdapter.class) @@ -188,6 +196,8 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder events); public abstract Builder notes(List notes); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt index fa30fc2ad7..c5411920de 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollmentTransformer.kt @@ -49,6 +49,7 @@ internal class NewTrackerImporterEnrollmentTransformer : Transformer, importStrategy: String): String { - val eventPayload = NewTrackerImporterEventPayload(events) + val eventPayload = NewTrackerImporterPayload(events = events.toMutableList()) val res = apiCallExecutor.executeObjectCall( service.postEvents(eventPayload, ATOMIC_MODE_OBJECT, importStrategy) ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java index c02ce0ba09..68859ed51a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java @@ -37,15 +37,19 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.gabrielittner.auto.value.cursor.ColumnAdapter; +import com.gabrielittner.auto.value.cursor.ColumnName; 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.DbGeometryColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNewTrackerImporterEnrollmentListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNewTrackerImporterTrackedEntityAttributeValueListColumnAdapter; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceFields; @@ -94,6 +98,11 @@ public abstract class NewTrackerImporterTrackedEntity extends BaseDeletableDataO @ColumnAdapter(DbGeometryColumnAdapter.class) public abstract Geometry geometry(); + @Nullable + @ColumnName(DataColumns.AGGREGATED_SYNC_STATE) + @ColumnAdapter(StateColumnAdapter.class) + public abstract State aggregatedSyncState(); + @Nullable @JsonProperty(TrackedEntityInstanceFields.TRACKED_ENTITY_ATTRIBUTE_VALUES) @ColumnAdapter(IgnoreNewTrackerImporterTrackedEntityAttributeValueListColumnAdapter.class) @@ -137,6 +146,8 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder trackedEntityAttributeValues); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt index 8a0e5e60d1..8d6ae66296 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTranckedEntityTransformer.kt @@ -44,6 +44,7 @@ internal class NewTrackerImporterTranckedEntityTransformer : .trackedEntityType(o.trackedEntityType()) .geometry(o.geometry()) .syncState(o.syncState()) + .aggregatedSyncState(o.aggregatedSyncState()) .build() } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/NewTrackerImporterEventPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt similarity index 72% rename from core/src/main/java/org/hisp/dhis/android/core/event/internal/NewTrackerImporterEventPayload.kt rename to core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt index f4a058e5cc..2dc74f743e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/NewTrackerImporterEventPayload.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt @@ -25,8 +25,18 @@ * (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.event.internal +package org.hisp.dhis.android.core.trackedentity.internal +import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.event.NewTrackerImporterEvent +import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntity -internal data class NewTrackerImporterEventPayload(val events: List) +internal data class NewTrackerImporterPayload( + val trackedEntities: MutableList = mutableListOf(), + val enrollments: MutableList = mutableListOf(), + val events: MutableList = mutableListOf() +) { + fun isEmpty(): Boolean { + return trackedEntities.isEmpty() && enrollments.isEmpty() && events.isEmpty() + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayloadWrapper.kt similarity index 88% rename from core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPayload.kt rename to core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayloadWrapper.kt index 31b8aab13d..e069acdddb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPayload.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayloadWrapper.kt @@ -27,8 +27,7 @@ */ package org.hisp.dhis.android.core.trackedentity.internal -import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntity - -internal data class NewTrackerImporterTrackedEntityPayload( - val trackedEntities: List +internal data class NewTrackerImporterPayloadWrapper( + val deleted: NewTrackerImporterPayload = NewTrackerImporterPayload(), + val updated: NewTrackerImporterPayload = NewTrackerImporterPayload() ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index e9fcbbd5f6..ed56a7c4b5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -28,22 +28,22 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Transformer import org.hisp.dhis.android.core.common.DataColumns import org.hisp.dhis.android.core.common.State -import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollmentTransformer import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore -import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.event.NewTrackerImporterEventTransformer import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.note.NewTrackerImporterNote import org.hisp.dhis.android.core.note.NewTrackerImporterNoteTransformer import org.hisp.dhis.android.core.note.Note -import org.hisp.dhis.android.core.trackedentity.* +import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityAttributeValueTransformer +import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityDataValueTransformer +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject internal constructor( @@ -51,13 +51,12 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter private val eventStore: EventStore, private val trackedEntityDataValueStore: TrackedEntityDataValueStore, private val trackedEntityAttributeValueStore: TrackedEntityAttributeValueStore, - private val noteStore: IdentifiableObjectStore, - private val stateManager: NewTrackerImporterTrackedEntityPostStateManager + private val noteStore: IdentifiableObjectStore ) { fun getTrackedEntities( filteredTrackedEntityInstances: List - ): List { + ): NewTrackerImporterPayloadWrapper { val dataValueMap = transformMap( trackedEntityDataValueStore.queryTrackerTrackedEntityDataValues(), NewTrackerImporterTrackedEntityDataValueTransformer() @@ -76,21 +75,14 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter ) val notes = getNotes() - val trackedEntityTransformer = NewTrackerImporterTranckedEntityTransformer() - - val trackedEntitiesToSync = filteredTrackedEntityInstances.map { - addTrackedEntityChildren( - trackedEntityTransformer.transform(it), - dataValueMap, - eventMap, - enrollmentMap, - attributeValueMap, - notes - ) - } - - stateManager.setStates(trackedEntitiesToSync, State.UPLOADING) - return trackedEntitiesToSync + return NewTrackerImporterTrackedEntityPostPayloadGeneratorTask( + filteredTrackedEntityInstances, + dataValueMap, + eventMap, + enrollmentMap, + attributeValueMap, + notes + ).generate() } private fun getNotes(): List { @@ -107,45 +99,8 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter map: Map>, transformer: Transformer ): Map> { - return map.mapValues { - v -> + return map.mapValues { v -> v.value.map { transformer.transform(it) } } } - - @Suppress("LongParameterList") - private fun addTrackedEntityChildren( - trackedEntity: NewTrackerImporterTrackedEntity, - dataValueMap: Map>, - eventMap: Map>, - enrollmentMap: Map>, - attributeValueMap: Map>, - notes: List - ): NewTrackerImporterTrackedEntity { - return trackedEntity.toBuilder() - .enrollments(getEnrollments(dataValueMap, eventMap, enrollmentMap, notes, trackedEntity.uid())) - .trackedEntityAttributeValues(attributeValueMap[trackedEntity.uid()] ?: emptyList()) - .build() - } - - private fun getEnrollments( - dataValueMap: Map>, - eventMap: Map>, - enrollmentMap: Map>, - notes: List, - trackedEntityInstanceUid: String - ): List { - return enrollmentMap[trackedEntityInstanceUid]?.map { enrollment -> - val events = eventMap[enrollment.uid()]?.map { event -> - val eventBuilder = event.toBuilder() - .trackedEntityDataValues(dataValueMap[event.uid()]) - .notes(notes.filter { it.event() == event.uid() }) - eventBuilder.build() - } ?: emptyList() - enrollment.toBuilder() - .events(events) - .notes(notes.filter { it.enrollment() == enrollment.uid() }) - .build() - } ?: emptyList() - } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt new file mode 100644 index 0000000000..f13629ae28 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment +import org.hisp.dhis.android.core.event.NewTrackerImporterEvent +import org.hisp.dhis.android.core.note.NewTrackerImporterNote +import org.hisp.dhis.android.core.trackedentity.* +import javax.inject.Inject + +@Reusable +internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject internal constructor( + private val trackedEntities: List, + private val dataValueMap: Map>, + private val eventMap: Map>, + private val enrollmentMap: Map>, + private val attributeValueMap: Map>, + private val notes: List +) { + + fun generate(): NewTrackerImporterPayloadWrapper { + val trackedEntityTransformer = NewTrackerImporterTranckedEntityTransformer() + val wrapper = NewTrackerImporterPayloadWrapper() + + val partitioned = trackedEntities + .filter { it.syncState() != State.SYNCED } + .map { trackedEntityTransformer.transform(it) } + .map { getTrackedEntity(it) } + .partition { it.deleted()!! } + + partitioned.first.forEach { + wrapper.deleted.trackedEntities.add(getTrackedEntityWithEnrollments(it)) + } + + partitioned.second.forEach { entity -> + wrapper.updated.trackedEntities.add(entity) + + val partitionedEnrollments = getEnrollments(entity.uid()) + .filter { it.syncState() != State.SYNCED } + .partition { it.deleted()!! } + + partitionedEnrollments.first.forEach { + wrapper.deleted.enrollments.add(getEnrollmentWithEvents(it)) + } + + partitionedEnrollments.second.forEach { enrollment -> + wrapper.updated.enrollments.add(enrollment) + + val partitionedEvents = getEvents(enrollment.uid()) + .filter { it.syncState() != State.SYNCED } + .partition { it.deleted()!! } + + wrapper.deleted.events.addAll(partitionedEvents.first) + wrapper.updated.events.addAll(partitionedEvents.second) + } + } + + return wrapper + } + + private fun getTrackedEntityWithEnrollments( + trackedEntity: NewTrackerImporterTrackedEntity + ): NewTrackerImporterTrackedEntity { + return getTrackedEntity(trackedEntity).toBuilder() + .enrollments(getEnrollmentsWithEvents(trackedEntity.uid())) + .build() + } + + private fun getTrackedEntity( + trackedEntity: NewTrackerImporterTrackedEntity + ): NewTrackerImporterTrackedEntity { + return trackedEntity.toBuilder() + .trackedEntityAttributeValues(attributeValueMap[trackedEntity.uid()] ?: emptyList()) + .build() + } + + private fun getEnrollmentsWithEvents( + trackedEntityInstanceUid: String + ): List { + return getEnrollments(trackedEntityInstanceUid).map { getEnrollmentWithEvents(it) } + } + + private fun getEnrollmentWithEvents( + enrollment: NewTrackerImporterEnrollment + ): NewTrackerImporterEnrollment { + return enrollment.toBuilder() + .events(getEvents(enrollment.uid())) + .build() + } + + private fun getEnrollments( + trackedEntityInstanceUid: String + ): List { + return enrollmentMap[trackedEntityInstanceUid]?.map { enrollment -> + enrollment.toBuilder() + .notes(notes.filter { it.enrollment() == enrollment.uid() }) + .build() + } ?: emptyList() + } + + private fun getEvents( + enrollmentUid: String + ): List { + return eventMap[enrollmentUid]?.map { event -> + val eventBuilder = event.toBuilder() + .trackedEntityDataValues(dataValueMap[event.uid()]) + .notes(notes.filter { it.event() == event.uid() }) + eventBuilder.build() + } ?: emptyList() + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt index 3cfeef339b..990b157129 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt @@ -42,25 +42,23 @@ internal class NewTrackerImporterTrackedEntityPostStateManager @Inject internal private val h: StatePersistorHelper ) { - fun restoreStates(trackedEntities: List) { - setStates(trackedEntities, null) + fun restoreStates(payload: NewTrackerImporterPayload) { + setStates(payload, null) } @Suppress("NestedBlockDepth") - fun setStates(trackedEntities: List, forcedState: State?) { + fun setStates(payload: NewTrackerImporterPayload, forcedState: State?) { val teiMap = mutableMapOf>() val enrollmentMap = mutableMapOf>() val eventMap = mutableMapOf>() - for (trackedEntity in trackedEntities) { - h.addState(teiMap, trackedEntity, forcedState) - for (enrollment in trackedEntity.enrollments()!!) { - h.addState(enrollmentMap, enrollment, forcedState) - for (event in enrollment.events()!!) { - h.addState(eventMap, event, forcedState) - } - } - } + val trackedEntities = payload.trackedEntities + val enrollments = trackedEntities.flatMap { it.enrollments()!! } + payload.enrollments + val events = enrollments.flatMap { it.events()!! } + payload.events + + trackedEntities.forEach { h.addState(teiMap, it, forcedState) } + enrollments.forEach { h.addState(enrollmentMap, it, forcedState) } + events.forEach { h.addState(eventMap, it, forcedState) } h.persistStates(teiMap, trackedEntityInstanceStore) h.persistStates(enrollmentMap, enrollmentStore) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index c245b7fa62..c0904aa48d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -63,8 +63,7 @@ internal class JobQueryCall @Inject internal constructor( } fun queryJob(jobId: String): Observable { - val jobObjects = trackerJobObjectStore.selectAll() - .filter { it.jobUid() == jobId } + val jobObjects = trackerJobObjectStore.selectWhere(byJobIdClause(jobId)) return queryJobInternal(jobId, jobObjects, true, ATTEMPTS_AFTER_UPLOAD) } @@ -97,10 +96,11 @@ internal class JobQueryCall @Inject internal constructor( private fun downloadAndHandle(jobId: String, jobObjects: List) { val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) - val whereClause = WhereClauseBuilder() - .appendKeyStringValue(TrackerJobObjectTableInfo.Columns.JOB_UID, jobId) - .build() - trackerJobObjectStore.deleteWhere(whereClause) + trackerJobObjectStore.deleteWhere(byJobIdClause(jobId)) handler.handle(jobReport, jobObjects) } + + private fun byJobIdClause(jobId: String) = WhereClauseBuilder() + .appendKeyStringValue(TrackerJobObjectTableInfo.Columns.JOB_UID, jobId) + .build() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 68fb49bc6f..4813dcb4da 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -30,18 +30,18 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single -import java.util.Date -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.common.ObjectWithUidInterface +import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.relationship.internal.RelationshipDeleteCall -import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntity import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPayload +import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostPayloadGenerator import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostStateManager +import java.util.* +import javax.inject.Inject @Reusable internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal constructor( @@ -57,32 +57,51 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con filteredTrackedEntityInstances: List ): Observable { return Observable.defer { - val trackedEntitiesToPost = payloadGenerator.getTrackedEntities(filteredTrackedEntityInstances) + val payloadWrapper = payloadGenerator.getTrackedEntities(filteredTrackedEntityInstances) + + // TODO HANDLE DELETIONS + // TODO HANDLE RELATIONSHIPS + // TODO HANDLE DELETED RELATIONSHIPS + // relationshipDeleteCall.postDeletedRelationships(partition) + Observable.concat( + doPostCall(payloadWrapper.deleted, IMPORT_STRATEGY_DELETE), + doPostCall(payloadWrapper.updated, IMPORT_STRATEGY_CREATE_AND_UPDATE) + ) + } + } + + private fun doPostCall( + payload: NewTrackerImporterPayload, + importStrategy: String + ): Observable { + return if (payload.isEmpty()) { + Observable.empty() + } else { + stateManager.setStates(payload, State.UPLOADING) Single.fromCallable { - // TODO HANDLE DELETIONS - // TODO HANDLE RELATIONSHIPS - // TODO HANDLE DELETED RELATIONSHIPS - // relationshipDeleteCall.postDeletedRelationships(partition) - val trackedEntityInstancePayload = NewTrackerImporterTrackedEntityPayload(trackedEntitiesToPost) - val res = apiCallExecutor.executeObjectCall( - service.postTrackedEntityInstances( - trackedEntityInstancePayload, ATOMIC_MODE_OBJECT, - IMPORT_STRATEGY_CREATE_AND_UPDATE - ) - ) - val jobId = res.response().uid() - jobObjectHandler.handleMany(generateJobObjects(trackedEntitiesToPost, jobId)) - jobId + doPostCallInternal(payload, importStrategy) }.doOnError { - stateManager.restoreStates(trackedEntitiesToPost) + stateManager.restoreStates(payload) }.flatMapObservable { jobQueryCall.queryJob(it) } } } + private fun doPostCallInternal( + payload: NewTrackerImporterPayload, + importStrategy: String + ): String { + val res = apiCallExecutor.executeObjectCall( + service.postTrackedEntityInstances(payload, ATOMIC_MODE_OBJECT, importStrategy) + ) + val jobId = res.response().uid() + jobObjectHandler.handleMany(generateJobObjects(payload, jobId)) + return jobId + } + private fun generateJobObjects( - trackedEntities: List, + payload: NewTrackerImporterPayload, jobUid: String ): List { val builder = TrackerJobObject @@ -90,10 +109,10 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con .jobUid(jobUid) .lastUpdated(Date()) - val enrollments = trackedEntities.flatMap { it.enrollments()!! } - val events = enrollments.flatMap { it.events()!! } + val enrollments = payload.trackedEntities.flatMap { it.enrollments()!! } + payload.enrollments + val events = enrollments.flatMap { it.events()!! } + payload.events - return generateTypeObjects(builder, TrackerImporterObjectTypes.TRACKED_ENTITY, trackedEntities) + + return generateTypeObjects(builder, TrackerImporterObjectTypes.TRACKED_ENTITY, payload.trackedEntities) + generateTypeObjects(builder, TrackerImporterObjectTypes.ENROLLMENT, enrollments) + generateTypeObjects(builder, TrackerImporterObjectTypes.EVENT, events) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt index c783210d8f..5c076d5785 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterService.kt @@ -27,8 +27,7 @@ */ package org.hisp.dhis.android.core.tracker.importer.internal -import org.hisp.dhis.android.core.event.internal.NewTrackerImporterEventPayload -import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPayload +import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterPayload import org.hisp.dhis.android.core.trackedentity.internal.ObjectWithUidWebResponse import retrofit2.Call import retrofit2.http.* @@ -48,14 +47,14 @@ internal interface TrackerImporterService { @POST(TRACKER_URL) fun postTrackedEntityInstances( - @Body payload: NewTrackerImporterTrackedEntityPayload, + @Body payload: NewTrackerImporterPayload, @Query(ATOMIC_MODE) atomicMode: String, @Query(IMPORT_STRATEGY) importStrategy: String ): Call @POST(TRACKER_URL) fun postEvents( - @Body events: NewTrackerImporterEventPayload, + @Body events: NewTrackerImporterPayload, @Query(ATOMIC_MODE) atomicMode: String, @Query(IMPORT_STRATEGY) importStrategy: String ): Call From e7520103b9899a801282d870191f31f39d2d6a47 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 16 Jul 2021 09:45:00 +0200 Subject: [PATCH 195/308] [ANDROSDK-1312] Add payload generator unit test --- ...erTrackedEntityPostPayloadGeneratorTask.kt | 10 +- ...kedEntityPostPayloadGeneratorTaskShould.kt | 136 ++++++++++++++++++ 2 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt index f13629ae28..85dfad41b6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt @@ -50,7 +50,6 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i val wrapper = NewTrackerImporterPayloadWrapper() val partitioned = trackedEntities - .filter { it.syncState() != State.SYNCED } .map { trackedEntityTransformer.transform(it) } .map { getTrackedEntity(it) } .partition { it.deleted()!! } @@ -60,10 +59,11 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i } partitioned.second.forEach { entity -> - wrapper.updated.trackedEntities.add(entity) + if (entity.syncState() != State.SYNCED) { + wrapper.updated.trackedEntities.add(entity) + } val partitionedEnrollments = getEnrollments(entity.uid()) - .filter { it.syncState() != State.SYNCED } .partition { it.deleted()!! } partitionedEnrollments.first.forEach { @@ -71,7 +71,9 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i } partitionedEnrollments.second.forEach { enrollment -> - wrapper.updated.enrollments.add(enrollment) + if (enrollment.syncState() != State.SYNCED) { + wrapper.updated.enrollments.add(enrollment) + } val partitionedEvents = getEvents(enrollment.uid()) .filter { it.syncState() != State.SYNCED } diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt new file mode 100644 index 0000000000..2b61292a21 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import com.google.common.truth.Truth.assertThat +import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment +import org.hisp.dhis.android.core.event.NewTrackerImporterEvent +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { + + private val uidGenerator = UidGeneratorImpl() + + @Test + fun should_generate_granular_payload_for_enrollments() { + val syncedTei = generateTEI(State.SYNCED) + val updatedEnrollment = generateEnrollment(syncedTei.uid(), State.TO_UPDATE) + val updatedEvent = generateEvent(updatedEnrollment.uid()) + + val wrapper = getTaskFor( + listOf(syncedTei), + mapOf(updatedEnrollment.uid()!! to listOf(updatedEvent)), + mapOf(syncedTei.uid()!! to listOf(updatedEnrollment)) + ).generate() + + assertThat(wrapper.deleted.isEmpty()).isTrue() + + assertThat(wrapper.updated.trackedEntities).isEmpty() + assertThat(wrapper.updated.enrollments).hasSize(1) + assertThat(wrapper.updated.events).hasSize(1) + } + + @Test + fun should_generate_deleted_payload_for_event() { + val syncedTei = generateTEI() + val syncedEnrollment = generateEnrollment(syncedTei.uid()) + val deletedEvent = generateEvent(syncedEnrollment.uid(), true) + + val wrapper = getTaskFor( + listOf(syncedTei), + mapOf(syncedEnrollment.uid()!! to listOf(deletedEvent)), + mapOf(syncedTei.uid()!! to listOf(syncedEnrollment)) + ).generate() + + assertThat(wrapper.deleted.trackedEntities).isEmpty() + assertThat(wrapper.deleted.enrollments).isEmpty() + assertThat(wrapper.deleted.events).hasSize(1) + + assertThat(wrapper.updated.isEmpty()).isTrue() + } + + private fun generateTEI( + synState: State = State.SYNCED, + deleted: Boolean = false + ): TrackedEntityInstance { + return TrackedEntityInstance.builder() + .uid(uidGenerator.generate()) + .syncState(synState) + .aggregatedSyncState(State.TO_UPDATE) + .deleted(deleted) + .build() + } + + private fun generateEnrollment( + teiUid: String, + synState: State = State.SYNCED, + deleted: Boolean = false + ): NewTrackerImporterEnrollment { + return NewTrackerImporterEnrollment.builder() + .uid(uidGenerator.generate()) + .trackedEntityInstance(teiUid) + .syncState(synState) + .aggregatedSyncState(State.TO_UPDATE) + .deleted(deleted) + .build() + } + + private fun generateEvent( + enrollmentUid: String, + deleted: Boolean = false + ): NewTrackerImporterEvent { + return NewTrackerImporterEvent.builder() + .uid(uidGenerator.generate()) + .enrollment(enrollmentUid) + .syncState(State.TO_UPDATE) + .deleted(deleted) + .build() + } + + private fun getTaskFor( + trackedEntities: List, + eventMap: Map>, + enrollmentMap: Map> + ): NewTrackerImporterTrackedEntityPostPayloadGeneratorTask { + return NewTrackerImporterTrackedEntityPostPayloadGeneratorTask( + trackedEntities, + mapOf(), + eventMap, + enrollmentMap, + mapOf(), + listOf() + ) + } +} \ No newline at end of file From d0f79ef973153e0035b33a53576656856dcd7b05 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 16 Jul 2021 09:59:51 +0200 Subject: [PATCH 196/308] [ANDROSDK-1312] Refresh aggregated sync states --- .../core/common/internal/DataStatePropagator.kt | 4 +++- .../common/internal/DataStatePropagatorImpl.kt | 14 ++++++++++++++ .../tracker/importer/internal/JobReportHandler.kt | 14 +++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index 4766719b72..6b7aa5d271 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -34,7 +34,7 @@ import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue -interface DataStatePropagator { +internal interface DataStatePropagator { fun propagateEnrollmentUpdate(enrollment: Enrollment?) @@ -55,4 +55,6 @@ interface DataStatePropagator { fun refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid: String) fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) + + fun refreshAggregatedSyncStatesCausedBy(enrollmentUids: List, eventUids: List) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index e911bbf0b4..78cc6d0022 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -231,6 +231,20 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } } + override fun refreshAggregatedSyncStatesCausedBy(enrollmentUids: List, eventUids: List) { + val enrollmentsFromEvents = eventStore.selectByUids(eventUids).mapNotNull { it.enrollment() } + + val enrollments = enrollmentStore.selectByUids(enrollmentUids + enrollmentsFromEvents) + enrollments.forEach { + refreshEnrollmentAggregatedSyncState(it.uid()) + } + + val trackedEntityInstanceUids = enrollments.mapNotNull { it.trackedEntityInstance() } + trackedEntityInstanceUids.forEach { + refreshTrackedEntityInstanceAggregatedSyncState(it) + } + } + private fun getAggregatedSyncState(states: List): State { return when { states.contains(State.RELATIONSHIP) -> State.RELATIONSHIP diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index e2c6de97ae..810ef8e4c7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY @@ -38,14 +39,18 @@ import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjec internal class JobReportHandler @Inject internal constructor( private val eventHandler: JobReportEventHandler, private val enrollmentHandler: JobReportEnrollmentHandler, - private val trackedEntityHandler: JobReportTrackedEntityHandler + private val trackedEntityHandler: JobReportTrackedEntityHandler, + private val dataStatePropagator: DataStatePropagator ) { fun handle(o: JobReport, jobObjects: List) { val jobObjectsMap = jobObjects.groupBy { jo -> Pair(jo.trackerType(), jo.objectUid()) } + handleErrors(o, jobObjectsMap) handleSuccesses(o, jobObjectsMap) handleNotPresentObjects(o, jobObjects) + + refreshAggregatedSyncStates(jobObjects) } private fun handleErrors(o: JobReport, jobObjectsMap: Map, List>) { @@ -108,4 +113,11 @@ internal class JobReportHandler @Inject internal constructor( .filter { jobObjects.containsKey(Pair(it.trackerType, it.uid)) } .forEach { typeHandler.handleSuccess(it.uid) } } + + private fun refreshAggregatedSyncStates(jobObjects: List) { + dataStatePropagator.refreshAggregatedSyncStatesCausedBy( + jobObjects.filter { it.trackerType() == ENROLLMENT }.map { it.objectUid() }, + jobObjects.filter { it.trackerType() == EVENT }.map { it.objectUid() } + ) + } } From ebebc81303eb558e216e0cad2a43ca054f1cd20c Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 16 Jul 2021 10:57:29 +0200 Subject: [PATCH 197/308] [androsdk-1383] Fix tests --- .../hisp/dhis/android/core/domain/metadata/MetadataCall.kt | 2 +- .../core/visualization/internal/VisualizationModuleWiper.kt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt index b1fa1fd422..63034d8669 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt @@ -141,7 +141,7 @@ class MetadataCall @Inject internal constructor( }, visualizationDownloader.downloadMetadata( // TODO Add visualization uids to download - emptySet() + setOf("visualization_uid_example") ).map { progressManager.increaseProgress(Visualization::class.java, false) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt index 0c85cf51d4..8312f83f22 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleWiper.kt @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable import javax.inject.Inject +import org.hisp.dhis.android.core.visualization.DataDimensionItemTableInfo import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLinkTableInfo import org.hisp.dhis.android.core.visualization.VisualizationTableInfo import org.hisp.dhis.android.core.wipe.internal.ModuleWiper @@ -39,7 +40,8 @@ class VisualizationModuleWiper @Inject internal constructor(private val tableWip override fun wipeMetadata() { tableWiper.wipeTables( VisualizationTableInfo.TABLE_INFO, - VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO + VisualizationCategoryDimensionLinkTableInfo.TABLE_INFO, + DataDimensionItemTableInfo.TABLE_INFO ) } From 082302d51095e6053eb9c96171d71ad6a6c4800b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 16 Jul 2021 11:00:58 +0200 Subject: [PATCH 198/308] [ANDROSDK-1312] Support empty enrollment and event lists --- .../core/common/internal/DataStatePropagator.kt | 6 +++++- .../core/common/internal/DataStatePropagatorImpl.kt | 10 +++++++--- .../core/enrollment/NewTrackerImporterEnrollment.java | 6 +++--- .../NewTrackerImporterEnrollmentTransformer.kt | 2 +- .../NewTrackerImporterTrackedEntityPostStateManager.kt | 4 ++-- .../core/tracker/importer/internal/JobReportHandler.kt | 1 + .../TrackedEntityInstanceTrackerImporterPostCall.kt | 4 ++-- ...orterTrackedEntityPostPayloadGeneratorTaskShould.kt | 2 +- 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index 6b7aa5d271..5c621eeaee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -56,5 +56,9 @@ internal interface DataStatePropagator { fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) - fun refreshAggregatedSyncStatesCausedBy(enrollmentUids: List, eventUids: List) + fun refreshAggregatedSyncStatesCausedBy( + trackedEntityInstanceUids: List, + enrollmentUids: List, + eventUids: List + ) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 78cc6d0022..e6701801d8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -231,7 +231,11 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } } - override fun refreshAggregatedSyncStatesCausedBy(enrollmentUids: List, eventUids: List) { + override fun refreshAggregatedSyncStatesCausedBy( + trackedEntityInstanceUids: List, + enrollmentUids: List, + eventUids: List + ) { val enrollmentsFromEvents = eventStore.selectByUids(eventUids).mapNotNull { it.enrollment() } val enrollments = enrollmentStore.selectByUids(enrollmentUids + enrollmentsFromEvents) @@ -239,8 +243,8 @@ internal class DataStatePropagatorImpl @Inject internal constructor( refreshEnrollmentAggregatedSyncState(it.uid()) } - val trackedEntityInstanceUids = enrollments.mapNotNull { it.trackedEntityInstance() } - trackedEntityInstanceUids.forEach { + val teiUids = trackedEntityInstanceUids + enrollments.mapNotNull { it.trackedEntityInstance() } + teiUids.forEach { refreshTrackedEntityInstanceAggregatedSyncState(it) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java index f8166b9d3b..f67fb683ca 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java @@ -122,8 +122,8 @@ public abstract class NewTrackerImporterEnrollment extends BaseDeletableDataObje public abstract EnrollmentStatus status(); @Nullable - @JsonIgnore() - public abstract String trackedEntityInstance(); + @JsonProperty() + public abstract String trackedEntity(); @Nullable @JsonProperty() @@ -192,7 +192,7 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder>() val trackedEntities = payload.trackedEntities - val enrollments = trackedEntities.flatMap { it.enrollments()!! } + payload.enrollments - val events = enrollments.flatMap { it.events()!! } + payload.events + val enrollments = trackedEntities.flatMap { it.enrollments() ?: emptyList() } + payload.enrollments + val events = enrollments.flatMap { it.events() ?: emptyList() } + payload.events trackedEntities.forEach { h.addState(teiMap, it, forcedState) } enrollments.forEach { h.addState(enrollmentMap, it, forcedState) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 810ef8e4c7..13e97ac608 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -116,6 +116,7 @@ internal class JobReportHandler @Inject internal constructor( private fun refreshAggregatedSyncStates(jobObjects: List) { dataStatePropagator.refreshAggregatedSyncStatesCausedBy( + jobObjects.filter { it.trackerType() == TRACKED_ENTITY }.map { it.objectUid() }, jobObjects.filter { it.trackerType() == ENROLLMENT }.map { it.objectUid() }, jobObjects.filter { it.trackerType() == EVENT }.map { it.objectUid() } ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 4813dcb4da..8cecbdafaf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -109,8 +109,8 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con .jobUid(jobUid) .lastUpdated(Date()) - val enrollments = payload.trackedEntities.flatMap { it.enrollments()!! } + payload.enrollments - val events = enrollments.flatMap { it.events()!! } + payload.events + val enrollments = payload.trackedEntities.flatMap { it.enrollments() ?: emptyList() } + payload.enrollments + val events = enrollments.flatMap { it.events() ?: emptyList() } + payload.events return generateTypeObjects(builder, TrackerImporterObjectTypes.TRACKED_ENTITY, payload.trackedEntities) + generateTypeObjects(builder, TrackerImporterObjectTypes.ENROLLMENT, enrollments) + diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt index 2b61292a21..94def8782d 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt @@ -100,7 +100,7 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { ): NewTrackerImporterEnrollment { return NewTrackerImporterEnrollment.builder() .uid(uidGenerator.generate()) - .trackedEntityInstance(teiUid) + .trackedEntity(teiUid) .syncState(synState) .aggregatedSyncState(State.TO_UPDATE) .deleted(deleted) From fd6dbcea51d822b10f91e934754366fae26f112c Mon Sep 17 00:00:00 2001 From: FerdyRod Date: Fri, 16 Jul 2021 11:17:26 +0200 Subject: [PATCH 199/308] [Follow up] Adds Follow up enumerator to ProgramFilter.java --- .../org/hisp/dhis/android/core/settings/ProgramFilter.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java b/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java index 802233371d..6e56475bfd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java @@ -53,5 +53,8 @@ public enum ProgramFilter { ORG_UNIT, @JsonProperty("categoryCombo") - CAT_COMBO + CAT_COMBO, + + @JsonProperty("followUp") + FOLLOW_UP } From 3a60fa278b2ed8663f9ccb6346d5e71d7f8963e1 Mon Sep 17 00:00:00 2001 From: FerdyRod Date: Fri, 16 Jul 2021 11:22:20 +0200 Subject: [PATCH 200/308] blank commit to fix semantic one-commit error --- .../java/org/hisp/dhis/android/core/settings/ProgramFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java b/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java index 6e56475bfd..ef2c51e545 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/ProgramFilter.java @@ -57,4 +57,4 @@ public enum ProgramFilter { @JsonProperty("followUp") FOLLOW_UP -} +} \ No newline at end of file From c10d9340b2739d3debb6bb3aa1b12af3b8088ceb Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 16 Jul 2021 11:35:04 +0200 Subject: [PATCH 201/308] [ANDROSDK-1312] Include context information in event conflict --- .../importer/internal/JobReportEventHandler.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index f046190a0c..8e1e215c54 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -33,6 +33,7 @@ import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuil import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.common.DataColumns import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.event.EventTableInfo import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore @@ -44,6 +45,7 @@ internal class JobReportEventHandler @Inject internal constructor( private val noteStore: IdentifiableObjectStore, private val conflictStore: TrackerImportConflictStore, private val eventStore: EventStore, + private val enrollmentStore: EnrollmentStore, private val conflictHelper: TrackerConflictHelper ) : JobReportTypeHandler() { @@ -66,10 +68,17 @@ internal class JobReportEventHandler @Inject internal constructor( } override fun storeConflict(errorReport: JobValidationError) { + val event = eventStore.selectByUid(errorReport.uid) + val trackedEntityInstanceUid = event?.enrollment()?.let { + enrollmentStore.selectByUid(it)?.trackedEntityInstance() + } conflictStore.insert( conflictHelper.getConflictBuilder(errorReport) .tableReference(EventTableInfo.TABLE_INFO.name()) - .event(errorReport.uid).build() + .trackedEntityInstance(trackedEntityInstanceUid) + .enrollment(event?.enrollment()) + .event(errorReport.uid) + .build() ) } } From 9081962fbfa15cb0c98d6f5be5ce6b9d5c5b51e5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 19 Jul 2021 13:16:44 +0200 Subject: [PATCH 202/308] [ANDROSDK-1312] Ktlint, pmd --- .../dhis/android/core/common/internal/DataStatePropagator.kt | 1 + .../core/trackedentity/internal/NewTrackerImporterPayload.kt | 2 +- .../NewTrackerImporterTrackedEntityPostPayloadGenerator.kt | 2 +- ...NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt | 2 +- .../NewTrackerImporterTrackedEntityPostStateManager.kt | 1 - .../internal/TrackedEntityInstanceTrackerImporterPostCall.kt | 4 ++-- ...ckerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index 5c621eeaee..112a9cc290 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue +@Suppress("TooManyFunctions") internal interface DataStatePropagator { fun propagateEnrollmentUpdate(enrollment: Enrollment?) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt index 2dc74f743e..a78d8e2628 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt @@ -39,4 +39,4 @@ internal data class NewTrackerImporterPayload( fun isEmpty(): Boolean { return trackedEntities.isEmpty() && enrollments.isEmpty() && events.isEmpty() } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index ed56a7c4b5..e1745f7076 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Transformer @@ -43,7 +44,6 @@ import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityAttributeValueTransformer import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityDataValueTransformer import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt index 85dfad41b6..484a2a2800 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt @@ -28,12 +28,12 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.note.NewTrackerImporterNote import org.hisp.dhis.android.core.trackedentity.* -import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt index f3bea0c158..18c2742aed 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt @@ -32,7 +32,6 @@ import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.event.internal.EventStore -import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntity @Reusable internal class NewTrackerImporterTrackedEntityPostStateManager @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 8cecbdafaf..3dac0a0d85 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -30,6 +30,8 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler @@ -40,8 +42,6 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostPayloadGenerator import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostStateManager -import java.util.* -import javax.inject.Inject @Reusable internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal constructor( diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt index 94def8782d..32e84667f3 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt @@ -133,4 +133,4 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { listOf() ) } -} \ No newline at end of file +} From 82dcddbb62104a75db2b3995504ff4da24f6b030 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Jul 2021 14:05:59 +0200 Subject: [PATCH 203/308] [androsdk-1383] Add @JvmField to tableInfos --- .../dhis/android/core/datavalue/DataValueConflictTableInfo.kt | 2 ++ .../android/core/visualization/DataDimensionItemTableInfo.kt | 2 ++ .../VisualizationCategoryDimensionLinkTableInfo.kt | 2 ++ .../dhis/android/core/visualization/VisualizationTableInfo.kt | 2 ++ 4 files changed, 8 insertions(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt index 04c40955a9..6b71154021 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datavalue/DataValueConflictTableInfo.kt @@ -33,6 +33,8 @@ import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper import org.hisp.dhis.android.core.common.CoreColumns object DataValueConflictTableInfo { + + @JvmField val TABLE_INFO: TableInfo = object : TableInfo() { override fun name(): String { return "DataValueConflict" diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt index 333766140c..7b734bce8f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/DataDimensionItemTableInfo.kt @@ -33,6 +33,8 @@ import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper import org.hisp.dhis.android.core.common.CoreColumns object DataDimensionItemTableInfo { + + @JvmField val TABLE_INFO: TableInfo = object : TableInfo() { override fun name(): String { return "DataDimensionItem" diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt index 9f94a3d8c1..e79c35e78e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationCategoryDimensionLinkTableInfo.kt @@ -33,6 +33,8 @@ import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper import org.hisp.dhis.android.core.common.CoreColumns object VisualizationCategoryDimensionLinkTableInfo { + + @JvmField val TABLE_INFO: TableInfo = object : TableInfo() { override fun name(): String { return "VisualizationCategoryDimensionLink" diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt index 4e1c8fdc66..1a3286b251 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/VisualizationTableInfo.kt @@ -34,6 +34,8 @@ import org.hisp.dhis.android.core.common.CoreColumns import org.hisp.dhis.android.core.common.IdentifiableColumns object VisualizationTableInfo { + + @JvmField val TABLE_INFO: TableInfo = object : TableInfo() { override fun name(): String { return "Visualization" From 5567c3ce2d7207e6b6419dc301a987a620838f46 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Jul 2021 14:20:16 +0200 Subject: [PATCH 204/308] [androsdk-1383] Delete unique restriction on dataDimensionItems --- core/src/main/assets/migrations/106.sql | 2 +- core/src/main/assets/snapshots/106.sql | 2 +- .../internal/VisualizationHandler.kt | 7 +++++- .../internal/VisualizationHandlerShould.java | 24 ++++++++++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/core/src/main/assets/migrations/106.sql b/core/src/main/assets/migrations/106.sql index a4e693a7e9..a90e11fb17 100644 --- a/core/src/main/assets/migrations/106.sql +++ b/core/src/main/assets/migrations/106.sql @@ -1,4 +1,4 @@ # New tables for visualization objects CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); -CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); \ No newline at end of file +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/106.sql b/core/src/main/assets/snapshots/106.sql index ad6ebd1238..5881507545 100644 --- a/core/src/main/assets/snapshots/106.sql +++ b/core/src/main/assets/snapshots/106.sql @@ -114,4 +114,4 @@ CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); -CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, dataDimensionItemType, indicator, dataElement, dataElementOperand, reportingRate, programIndicator, programDataElement, programAttribute, validationRule)); +CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index 871efb6efa..c671f4b4f4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,8 +28,8 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.arch.handlers.internal.IdentifiableHandlerImpl import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler @@ -38,10 +38,13 @@ import org.hisp.dhis.android.core.visualization.CategoryDimension import org.hisp.dhis.android.core.visualization.DataDimensionItem import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink +import javax.inject.Inject @Reusable internal class VisualizationHandler @Inject constructor( store: IdentifiableObjectStore, + private val visualizationCategoryDimensionLinkStore: LinkStore, + private val dataDimensionItemStore: LinkStore, private val visualizationCategoryDimensionLinkHandler: LinkHandler, private val dataDimensionItemHandler: LinkHandler @@ -51,6 +54,8 @@ internal class VisualizationHandler @Inject constructor( oCollection: Collection ): Collection { store.delete() + visualizationCategoryDimensionLinkStore.delete() + dataDimensionItemStore.delete() return oCollection } diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java index d1d19e110c..8f05d2055d 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.visualization.internal; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; +import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; import org.hisp.dhis.android.core.arch.handlers.internal.IdentifiableHandlerImpl; import org.hisp.dhis.android.core.arch.handlers.internal.LinkHandler; @@ -44,6 +45,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static org.mockito.Matchers.any; @@ -56,6 +58,12 @@ public class VisualizationHandlerShould { @Mock private IdentifiableObjectStore visualizationStore; + @Mock + private LinkStore dataDimensionItemStore; + + @Mock + private LinkStore visualizationCategoryDimensionLinkStore; + @Mock private LinkHandler visualizationCategoryDimensionLinkHandler; @@ -83,11 +91,16 @@ public class VisualizationHandlerShould { // object to test private VisualizationHandler visualizationHandler; + public VisualizationHandlerShould() { + } + @Before public void setUp() throws Exception { MockitoAnnotations.openMocks(this); visualizationHandler = new VisualizationHandler( visualizationStore, + visualizationCategoryDimensionLinkStore, + dataDimensionItemStore, visualizationCategoryDimensionLinkHandler, dataDimensionItemHandler); @@ -109,7 +122,16 @@ public void setUp() throws Exception { @Test public void extend_identifiable_sync_handler_impl() { IdentifiableHandlerImpl genericHandler = new VisualizationHandler - (visualizationStore, visualizationCategoryDimensionLinkHandler, dataDimensionItemHandler); + (visualizationStore, visualizationCategoryDimensionLinkStore, dataDimensionItemStore, + visualizationCategoryDimensionLinkHandler, dataDimensionItemHandler); + } + + @Test + public void call_stores_to_delete_before_collection_handled() { + visualizationHandler.handleMany(Collections.singletonList(visualization)); + verify(visualizationStore).delete(); + verify(visualizationCategoryDimensionLinkStore).delete(); + verify(dataDimensionItemStore).delete(); } @Test From 085b1de8511a8f4394b01b9b9cc40d98b8d07656 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Jul 2021 14:31:38 +0200 Subject: [PATCH 205/308] [androsdk-1383] Only download visualizations if version is greater or equal than 2.34 --- .../internal/VisualizationCall.kt | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt index a38c8495c7..96ee2b5a8e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationCall.kt @@ -33,12 +33,15 @@ import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APIDownloader import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall import org.hisp.dhis.android.core.arch.handlers.internal.Handler +import org.hisp.dhis.android.core.systeminfo.DHISVersion +import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.visualization.Visualization @Reusable internal class VisualizationCall @Inject constructor( private val handler: Handler, private val service: VisualizationService, + private val dhis2VersionManager: DHISVersionManager, private val apiDownloader: APIDownloader ) : UidsCall { @@ -47,16 +50,20 @@ internal class VisualizationCall @Inject constructor( } override fun download(uids: Set): Single> { - return apiDownloader.downloadPartitioned( - uids, - MAX_UID_LIST_SIZE, - handler - ) { partitionUids: Set -> - service.getVisualizations( - VisualizationFields.allFields, - VisualizationFields.uid.`in`(partitionUids), - paging = false - ) + return if (dhis2VersionManager.isGreaterOrEqualThan(DHISVersion.V2_34)) { + apiDownloader.downloadPartitioned( + uids, + MAX_UID_LIST_SIZE, + handler + ) { partitionUids: Set -> + service.getVisualizations( + VisualizationFields.allFields, + VisualizationFields.uid.`in`(partitionUids), + paging = false + ) + } + } else { + Single.just(listOf()) } } } From 4539b8721e750735a5d9e9398b69a61e8c46374b Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Jul 2021 15:52:49 +0200 Subject: [PATCH 206/308] [androsdk-1383] Download visualizations from AWSA --- .../android/core/domain/metadata/MetadataCall.kt | 5 +---- .../internal/VisualizationModuleDownloader.kt | 13 ++++++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt index 63034d8669..6efc42a19c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/domain/metadata/MetadataCall.kt @@ -139,10 +139,7 @@ class MetadataCall @Inject internal constructor( categoryDownloader.downloadMetadata().toSingle { progressManager.increaseProgress(Category::class.java, false) }, - visualizationDownloader.downloadMetadata( - // TODO Add visualization uids to download - setOf("visualization_uid_example") - ).map { + visualizationDownloader.downloadMetadata().map { progressManager.increaseProgress(Visualization::class.java, false) } ).toObservable() diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt index 10e6cedf73..f28f4f2dfa 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationModuleDownloader.kt @@ -31,16 +31,19 @@ import dagger.Reusable import io.reactivex.Single import javax.inject.Inject import org.hisp.dhis.android.core.arch.call.factories.internal.UidsCall -import org.hisp.dhis.android.core.arch.modules.internal.MetadataModuleByUidDownloader +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.modules.internal.TypedModuleDownloader +import org.hisp.dhis.android.core.settings.AnalyticsDhisVisualization import org.hisp.dhis.android.core.visualization.Visualization @Reusable class VisualizationModuleDownloader @Inject internal constructor( - private val visualizationCall: UidsCall + private val visualizationCall: UidsCall, + private val analyticsDhisVisualizationStore: ObjectWithoutUidStore ) : - MetadataModuleByUidDownloader> { + TypedModuleDownloader> { - override fun downloadMetadata(visualizationUids: Set): Single> { - return visualizationCall.download(visualizationUids) + override fun downloadMetadata(): Single> { + return visualizationCall.download(analyticsDhisVisualizationStore.selectAll().map { it.uid() }.toSet()) } } From 41fb85e069c25d0532f4fb0d269f5cf2176c4ed2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Jul 2021 16:00:58 +0200 Subject: [PATCH 207/308] [androsdk-1383] Optimize imports --- .../android/core/visualization/internal/VisualizationHandler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index c671f4b4f4..3224606b91 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction @@ -38,7 +39,6 @@ import org.hisp.dhis.android.core.visualization.CategoryDimension import org.hisp.dhis.android.core.visualization.DataDimensionItem import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLink -import javax.inject.Inject @Reusable internal class VisualizationHandler @Inject constructor( From 6037f3762fc3a74c45bd2911498b62c9bcb954f4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 19 Jul 2021 16:19:43 +0200 Subject: [PATCH 208/308] [androsdk-1383] Fix tests --- ...isualizationCollectionRepositoryMockIntegrationShould.java | 4 ++-- .../dhis/android/core/domain/metadata/MetadataCallShould.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java index 224909c514..a370a91de7 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/visualization/VisualizationCollectionRepositoryMockIntegrationShould.java @@ -125,7 +125,7 @@ public void include_category_dimensions_as_children() { public void include_data_dimension_item_as_children() { Visualization visualization = d2.visualizationModule().visualizations() .withDataDimensionItems().one().blockingGet(); - assertThat(visualization.dataDimensionItems().get(0).dataDimensionItemType()).isEqualTo(DataDimensionItemType.DATA_ELEMENT); - assertThat(visualization.dataDimensionItems().get(0).dataDimensionItem()).isEqualTo("cYeuwXTCPkU"); + assertThat(visualization.dataDimensionItems().get(0).dataDimensionItemType()).isEqualTo(DataDimensionItemType.INDICATOR); + assertThat(visualization.dataDimensionItems().get(0).dataDimensionItem()).isEqualTo("Uvn6LCg7dVU"); } } \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt b/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt index 796ac438e0..40e22adc63 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/domain/metadata/MetadataCallShould.kt @@ -100,7 +100,7 @@ class MetadataCallShould : BaseCallShould() { whenever(dataSetDownloader.downloadMetadata(any())).thenReturn( Single.just(emptyList()) ) - whenever(visualizationDownloader.downloadMetadata(any())).thenReturn( + whenever(visualizationDownloader.downloadMetadata()).thenReturn( Single.just(emptyList()) ) whenever(constantDownloader.downloadMetadata()).thenReturn(Single.just(emptyList())) @@ -173,7 +173,7 @@ class MetadataCallShould : BaseCallShould() { @Test fun fail_when_visualization_download_call_fail() { - whenever(visualizationDownloader.downloadMetadata(any())).thenReturn(Single.error(d2Error)) + whenever(visualizationDownloader.downloadMetadata()).thenReturn(Single.error(d2Error)) downloadAndAssertError() } From 5ae346240102d2b8a11636de5f5a78321958f8d9 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 20 Jul 2021 10:11:43 +0200 Subject: [PATCH 209/308] [androsdk-1383] Remove unique constraint from category dimensions table --- core/src/main/assets/migrations/106.sql | 2 +- core/src/main/assets/snapshots/106.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/assets/migrations/106.sql b/core/src/main/assets/migrations/106.sql index a90e11fb17..a155ad398e 100644 --- a/core/src/main/assets/migrations/106.sql +++ b/core/src/main/assets/migrations/106.sql @@ -1,4 +1,4 @@ # New tables for visualization objects CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); -CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/106.sql b/core/src/main/assets/snapshots/106.sql index 5881507545..d6964e170e 100644 --- a/core/src/main/assets/snapshots/106.sql +++ b/core/src/main/assets/snapshots/106.sql @@ -113,5 +113,5 @@ CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerTyp CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); -CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (visualization, category, categoryOption)); +CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); From 40b823fc099bba72e1546406fda14afe270fba8b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 20 Jul 2021 12:18:43 +0200 Subject: [PATCH 210/308] [ANDROSDK-1386] [ANDROSDK-1386-2] Visualizations service structure --- .../android/core/analytics/AnalyticsModule.kt | 4 +- .../core/analytics/AnalyticsModuleImpl.kt | 6 +- .../aggregated/AggregatedEntityDIModule.kt | 10 +- ...t => AnalyticsVisualizationsRepository.kt} | 4 +- .../AnalyticsVisualizationsRepositoryImpl.kt | 57 ++++++++ ...AnalyticsVisualizationsRepositoryParams.kt | 33 +++++ ... MockAnalyticsVisualizationsRepository.kt} | 6 +- .../service/AnalyticsVisualizationsService.kt | 86 ++++++++++++ ...icsVisualizationsServiceDimensionHelper.kt | 130 ++++++++++++++++++ 9 files changed, 324 insertions(+), 12 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{VisualizationsRepository.kt => AnalyticsVisualizationsRepository.kt} (93%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/{MockVisualizationsRepository.kt => MockAnalyticsVisualizationsRepository.kt} (87%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt index c27be745d1..281df57e4b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModule.kt @@ -28,7 +28,7 @@ package org.hisp.dhis.android.core.analytics import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository -import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository import org.hisp.dhis.android.core.analytics.linelist.EventLineListRepository interface AnalyticsModule { @@ -37,5 +37,5 @@ interface AnalyticsModule { fun analytics(): AnalyticsRepository - fun visualizations(): VisualizationsRepository + fun visualizations(): AnalyticsVisualizationsRepository } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt index c364ef1887..a9a4dc15a2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/AnalyticsModuleImpl.kt @@ -30,19 +30,19 @@ package org.hisp.dhis.android.core.analytics import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository -import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository import org.hisp.dhis.android.core.analytics.linelist.EventLineListRepository @Reusable internal class AnalyticsModuleImpl @Inject constructor( private val eventLineListRepository: EventLineListRepository, private val analyticsRepository: AnalyticsRepository, - private val visualizationsRepository: VisualizationsRepository + private val analyticsVisualizationsRepository: AnalyticsVisualizationsRepository ) : AnalyticsModule { override fun eventLineList(): EventLineListRepository = eventLineListRepository override fun analytics(): AnalyticsRepository = analyticsRepository - override fun visualizations(): VisualizationsRepository = visualizationsRepository + override fun visualizations(): AnalyticsVisualizationsRepository = analyticsVisualizationsRepository } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index 7c9ad8b85e..123378c40e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -31,7 +31,7 @@ import dagger.Module import dagger.Provides import dagger.Reusable import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsRepository -import org.hisp.dhis.android.core.analytics.aggregated.mock.MockVisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsVisualizationsRepository @Module internal class AggregatedEntityDIModule { @@ -44,7 +44,7 @@ internal class AggregatedEntityDIModule { @Provides @Reusable - fun visualizations(impl: MockVisualizationsRepository): VisualizationsRepository { + fun visualizations(impl: MockAnalyticsVisualizationsRepository): AnalyticsVisualizationsRepository { return impl } @@ -53,4 +53,10 @@ internal class AggregatedEntityDIModule { fun emptyAnalyticsParams(): AnalyticsRepositoryParams { return AnalyticsRepositoryParams(listOf(), listOf()) } + + @Provides + @Reusable + fun emptyAnalyticsVisualizationsParam(): AnalyticsVisualizationsRepositoryParams { + return AnalyticsVisualizationsRepositoryParams(null) + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt similarity index 93% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt index 2e0ed90264..c45b5115bd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/VisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt @@ -30,9 +30,9 @@ package org.hisp.dhis.android.core.analytics.aggregated import io.reactivex.Single -interface VisualizationsRepository { +interface AnalyticsVisualizationsRepository { - fun withVisualization(visualization: String): VisualizationsRepository + fun withVisualization(visualization: String): AnalyticsVisualizationsRepository fun evaluate(): Single diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt new file mode 100644 index 0000000000..a3ec8a30a2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +import io.reactivex.Single +import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsVisualizationsService +import javax.inject.Inject + +internal class AnalyticsVisualizationsRepositoryImpl @Inject constructor( + private val params: AnalyticsVisualizationsRepositoryParams, + private val service: AnalyticsVisualizationsService +) : AnalyticsVisualizationsRepository { + + override fun withVisualization(visualization: String): AnalyticsVisualizationsRepositoryImpl { + return updateParams { params -> params.copy(visualization = visualization) } + } + + override fun evaluate(): Single { + return Single.fromCallable { blockingEvaluate() } + } + + override fun blockingEvaluate(): GridAnalyticsResponse { + return service.evaluate(params) + } + + private fun updateParams( + func: (params: AnalyticsVisualizationsRepositoryParams) -> AnalyticsVisualizationsRepositoryParams + ): AnalyticsVisualizationsRepositoryImpl { + return AnalyticsVisualizationsRepositoryImpl(func(params), service) + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt new file mode 100644 index 0000000000..a05223977c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated + +internal data class AnalyticsVisualizationsRepositoryParams( + val visualization: String? +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt similarity index 87% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt index 348b0aa9f7..8ac9172a4f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockVisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt @@ -32,12 +32,12 @@ import dagger.Reusable import io.reactivex.Single import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse -import org.hisp.dhis.android.core.analytics.aggregated.VisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository @Reusable -class MockVisualizationsRepository @Inject constructor() : VisualizationsRepository { +class MockAnalyticsVisualizationsRepository @Inject constructor() : AnalyticsVisualizationsRepository { - override fun withVisualization(visualization: String): VisualizationsRepository = TODO() + override fun withVisualization(visualization: String): AnalyticsVisualizationsRepository = TODO() override fun evaluate(): Single { return Single.fromCallable { blockingEvaluate() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt new file mode 100644 index 0000000000..d8961e508e --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse +import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse +import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationCollectionRepository +import javax.inject.Inject + +internal class AnalyticsVisualizationsService @Inject constructor( + private val analyticsRepository: AnalyticsRepository, + private val visualizationCollectionRepository: VisualizationCollectionRepository, + private val dimensionHelper: AnalyticsVisualizationsServiceDimensionHelper +) { + + fun evaluate(params: AnalyticsVisualizationsRepositoryParams): GridAnalyticsResponse { + if (params.visualization == null) { + throw AnalyticsException.InvalidArguments("Null visualization id") + } + + val visualization = getVisualization(params.visualization) + val dimensionalResponse = getDimensionalResponse(visualization) + } + + private fun getVisualization(visualizationId: String): Visualization { + return visualizationCollectionRepository + .withCategoryDimensions() + .withDataDimensionItems() + .uid(visualizationId) + .blockingGet() + ?: throw AnalyticsException.InvalidArguments("Visualization $visualizationId does not exist") + } + + private fun getDimensionalResponse(visualization: Visualization): DimensionalResponse { + var analyticsRepository = analyticsRepository + + val queryDimensions = + (visualization.rowDimensions() ?: emptyList()) + + (visualization.columnDimensions() ?: emptyList()) + + dimensionHelper.getDimensionItems( + visualization, + queryDimensions + ).forEach { item -> + analyticsRepository = analyticsRepository.withDimension(item) + } + + dimensionHelper.getDimensionItems( + visualization, + visualization.filterDimensions() + ).forEach { item -> + analyticsRepository = analyticsRepository.withFilter(item) + } + + return analyticsRepository.blockingEvaluate() + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt new file mode 100644 index 0000000000..c0c4da8080 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit.* +import org.hisp.dhis.android.core.visualization.DataDimensionItemType +import org.hisp.dhis.android.core.visualization.Visualization +import javax.inject.Inject + +internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor( + private val categoryStore: IdentifiableObjectStore +) { + private val dataDimension = "dx" + private val orgUnitDimension = "ou" + private val periodDimension = "pe" + private val uidRegex = "^\\w{11}\$".toRegex() + private val dataElementOperandRegex = "^(\\w{11})\\.(\\w{11})\$".toRegex() + + fun getDimensionItems(visualization: Visualization, dimensions: List?): List { + return dimensions?.map { dimension -> + when(dimension) { + dataDimension -> extractDataDimensionItems(visualization) + orgUnitDimension -> extractOrgunitDimensionItems(visualization) + periodDimension -> extractPeriodDimensionItems(visualization) + else -> { + if (uidRegex.matches(dimension)) { + extractUidDimensionItems(visualization, dimension) + } else { + emptyList() + } + } + } + }?.flatten() ?: emptyList() + } + + private fun extractDataDimensionItems(visualization: Visualization): List { + return visualization.dataDimensionItems()?.mapNotNull { item -> + when (item.dataDimensionItemType()) { + DataDimensionItemType.INDICATOR -> + item.indicator()?.let { DimensionItem.DataItem.IndicatorItem(it.uid()) } + DataDimensionItemType.DATA_ELEMENT -> + item.dataElement()?.let { DimensionItem.DataItem.DataElementItem(it.uid()) } + DataDimensionItemType.DATA_ELEMENT_OPERAND -> + TODO() + DataDimensionItemType.PROGRAM_INDICATOR -> + item.programIndicator()?.let { DimensionItem.DataItem.ProgramIndicatorItem(it.uid()) } + else -> + null + } + } ?: emptyList() + } + + private fun extractOrgunitDimensionItems(visualization: Visualization): List { + val absolute = visualization.organisationUnits()?.map { + DimensionItem.OrganisationUnitItem.Absolute(it.uid()) + } ?: emptyList() + + val levels = visualization.organisationUnitLevels()?.map { + DimensionItem.OrganisationUnitItem.Level(it) + } ?: emptyList() + + val relative = listOfNotNull( + if (visualization.userOrganisationUnit() == true) USER_ORGUNIT else null, + if (visualization.userOrganisationUnitChildren() == true) USER_ORGUNIT_CHILDREN else null, + if (visualization.userOrganisationUnitGrandChildren() == true) USER_ORGUNIT_GRANDCHILDREN else null + ).map { item -> + DimensionItem.OrganisationUnitItem.Relative(item) + } + + return absolute + levels + relative + } + + private fun extractPeriodDimensionItems(visualization: Visualization): List { + val absolute = visualization.periods()?.map { + DimensionItem.PeriodItem.Absolute(it.uid()) + } ?: emptyList() + + val relative = visualization.relativePeriods() + ?.filter { it.value == true } + ?.map { + DimensionItem.PeriodItem.Relative(it.key) + } ?: emptyList() + + return absolute + relative + } + + private fun extractUidDimensionItems(visualization: Visualization, uid: String): List { + val category = categoryStore.selectByUid(uid) + + return if (category != null) { + val categoryDimension = visualization.categoryDimensions()?.find { it.category()?.uid() == uid } + + categoryDimension?.categoryOptions()?.map { + DimensionItem.CategoryItem(uid, it.uid()) + } ?: emptyList() + + } else { + emptyList() + } + } +} From 90782cec3c46f2fa008d2a573a7db5962f3410d2 Mon Sep 17 00:00:00 2001 From: andresmr Date: Tue, 20 Jul 2021 13:27:47 +0200 Subject: [PATCH 211/308] feat: [ANDROAPP-4099] EnrollmentService.kt check if allow event creation --- .../core/enrollment/EnrollmentService.kt | 34 +++++++- .../enrollment/EnrollmentServiceShould.kt | 87 ++++++++++++++++++- 2 files changed, 118 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt index 695a0ac9fd..c7ab252014 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt @@ -30,10 +30,14 @@ package org.hisp.dhis.android.core.enrollment import dagger.Reusable import io.reactivex.Single import javax.inject.Inject +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.EventCollectionRepository import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitCollectionRepository import org.hisp.dhis.android.core.program.AccessLevel import org.hisp.dhis.android.core.program.ProgramCollectionRepository +import org.hisp.dhis.android.core.program.ProgramStage +import org.hisp.dhis.android.core.program.ProgramStageCollectionRepository import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceCollectionRepository @Reusable @@ -41,7 +45,9 @@ class EnrollmentService @Inject constructor( private val enrollmentRepository: EnrollmentCollectionRepository, private val trackedEntityInstanceRepository: TrackedEntityInstanceCollectionRepository, private val programRepository: ProgramCollectionRepository, - private val organisationUnitRepository: OrganisationUnitCollectionRepository + private val organisationUnitRepository: OrganisationUnitCollectionRepository, + private val eventCollectionRepository: EventCollectionRepository, + private val programStagesCollectionRepository: ProgramStageCollectionRepository ) { /** @@ -104,4 +110,30 @@ class EnrollmentService @Inject constructor( .uid(tei.organisationUnit()) .blockingExists() } + + fun allowEventCreation(enrollmentUid: String, stagesToHide: List): Boolean { + val programStages = eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid ?: "") + .byDeleted().isFalse.get() + .toFlowable().flatMapIterable { events: List? -> events } + .map { event: Event -> event.programStage() } + .toList() + .flatMap { currentProgramStagesUids: List -> + val repository = programStagesCollectionRepository.byProgramUid().eq( + enrollmentRepository.uid(enrollmentUid).blockingGet().program() + ) + + repository.get().toFlowable() + .flatMapIterable { stages: List? -> stages } + .filter { programStage: ProgramStage -> + programStage.access().data() + .write() == true && ( + !currentProgramStagesUids.contains(programStage.uid()) || + programStage.repeatable()!! + ) + } + .toList() + }.blockingGet() + + return programStages.find { !stagesToHide.contains(it.uid()) } != null + } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt b/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt index 431b2e8a81..6a0165cef3 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt @@ -30,12 +30,19 @@ package org.hisp.dhis.android.core.enrollment import com.nhaarman.mockitokotlin2.doReturn import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever +import io.reactivex.Single import org.hisp.dhis.android.core.arch.helpers.AccessHelper +import org.hisp.dhis.android.core.common.Access +import org.hisp.dhis.android.core.common.DataAccess +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.EventCollectionRepository import org.hisp.dhis.android.core.organisationunit.OrganisationUnit import org.hisp.dhis.android.core.organisationunit.OrganisationUnitCollectionRepository import org.hisp.dhis.android.core.program.AccessLevel import org.hisp.dhis.android.core.program.Program import org.hisp.dhis.android.core.program.ProgramCollectionRepository +import org.hisp.dhis.android.core.program.ProgramStage +import org.hisp.dhis.android.core.program.ProgramStageCollectionRepository import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceCollectionRepository import org.junit.Assert.assertFalse @@ -62,10 +69,18 @@ class EnrollmentServiceShould { private val programRepository: ProgramCollectionRepository = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) private val organisationUnitRepository: OrganisationUnitCollectionRepository = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) + private val eventCollectionRepository: EventCollectionRepository = + mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) + private val programStageCollectionRepository: ProgramStageCollectionRepository = + mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) private val enrollmentService = EnrollmentService( - enrollmentRepository, trackedEntityInstanceRepository, - programRepository, organisationUnitRepository + enrollmentRepository, + trackedEntityInstanceRepository, + programRepository, + organisationUnitRepository, + eventCollectionRepository, + programStageCollectionRepository ) @Before @@ -152,4 +167,72 @@ class EnrollmentServiceShould { val access = enrollmentService.blockingGetEnrollmentAccess(trackedEntityInstanceUid, programUid) assert(access == EnrollmentAccess.PROTECTED_PROGRAM_DENIED) } + + @Test + fun `Enrollment has any events that allows events creation`() { + + whenever(enrollmentRepository.uid(enrollmentUid).blockingGet()) doReturn enrollment + whenever(enrollment.program()) doReturn programUid + + whenever( + programStageCollectionRepository.byProgramUid().eq(programUid) + ) doReturn programStageCollectionRepository + whenever(programStageCollectionRepository.get()) doReturn Single.just(getProgramStages()) + + whenever( + eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid) + ) doReturn eventCollectionRepository + whenever( + eventCollectionRepository.byDeleted().isFalse + ) doReturn eventCollectionRepository + whenever(eventCollectionRepository.get()) doReturn Single.just(getEventList()) + + assertTrue(enrollmentService.allowEventCreation(enrollmentUid, listOf("1"))) + } + + @Test + fun `Enrollment has not any events that allows events creation`() { + + whenever(enrollmentRepository.uid(enrollmentUid).blockingGet()) doReturn enrollment + whenever(enrollment.program()) doReturn programUid + + whenever( + programStageCollectionRepository.byProgramUid().eq(programUid) + ) doReturn programStageCollectionRepository + whenever(programStageCollectionRepository.get()) doReturn Single.just(getProgramStages()) + + whenever( + eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid) + ) doReturn eventCollectionRepository + whenever( + eventCollectionRepository.byDeleted().isFalse + ) doReturn eventCollectionRepository + whenever(eventCollectionRepository.get()) doReturn Single.just(getEventList()) + + assertFalse(enrollmentService.allowEventCreation(enrollmentUid, listOf("1", "2"))) + } + + private fun getEventList() = listOf( + Event.builder() + .uid("eventUid1") + .programStage("1") + .build(), + Event.builder() + .uid("eventUid2") + .programStage("2") + .build() + ) + + private fun getProgramStages() = listOf( + ProgramStage.builder() + .access(Access.create(true, true, DataAccess.create(true, true))) + .uid("1") + .repeatable(true) + .build(), + ProgramStage.builder() + .access(Access.create(true, true, DataAccess.create(true, true))) + .uid("2") + .repeatable(true) + .build() + ) } From e8e7b803f9f78d858487eea9c270d5883cdffd3a Mon Sep 17 00:00:00 2001 From: andresmr Date: Wed, 21 Jul 2021 09:34:06 +0200 Subject: [PATCH 212/308] [ANDROAPP-4099] Create SINGLE and BlockingGet methods for allowEventCreation --- .../core/enrollment/EnrollmentService.kt | 17 +++++++++-------- .../enrollment/EnrollmentServiceShould.kt | 19 ++++++++++++++----- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt index c7ab252014..38a3eb6508 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/EnrollmentService.kt @@ -111,8 +111,8 @@ class EnrollmentService @Inject constructor( .blockingExists() } - fun allowEventCreation(enrollmentUid: String, stagesToHide: List): Boolean { - val programStages = eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid ?: "") + fun blockingGetAllowEventCreation(enrollmentUid: String, stagesToHide: List): Boolean { + val programStages = eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid) .byDeleted().isFalse.get() .toFlowable().flatMapIterable { events: List? -> events } .map { event: Event -> event.programStage() } @@ -120,20 +120,21 @@ class EnrollmentService @Inject constructor( .flatMap { currentProgramStagesUids: List -> val repository = programStagesCollectionRepository.byProgramUid().eq( enrollmentRepository.uid(enrollmentUid).blockingGet().program() - ) + ).byAccessDataWrite().isTrue repository.get().toFlowable() .flatMapIterable { stages: List? -> stages } .filter { programStage: ProgramStage -> - programStage.access().data() - .write() == true && ( - !currentProgramStagesUids.contains(programStage.uid()) || - programStage.repeatable()!! - ) + !currentProgramStagesUids.contains(programStage.uid()) || + programStage.repeatable()!! } .toList() }.blockingGet() return programStages.find { !stagesToHide.contains(it.uid()) } != null } + + fun allowEventCreation(enrollmentUid: String, stagesToHide: List): Single { + return Single.fromCallable { blockingGetAllowEventCreation(enrollmentUid, stagesToHide) } + } } diff --git a/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt b/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt index 6a0165cef3..bb469ad2f9 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/enrollment/EnrollmentServiceShould.kt @@ -61,7 +61,6 @@ class EnrollmentServiceShould { private val enrollment: Enrollment = mock() private val trackedEntityInstance: TrackedEntityInstance = mock() private val program: Program = mock() - private val organisationUnit: OrganisationUnit = mock() private val enrollmentRepository: EnrollmentCollectionRepository = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) private val trackedEntityInstanceRepository: TrackedEntityInstanceCollectionRepository = @@ -177,7 +176,12 @@ class EnrollmentServiceShould { whenever( programStageCollectionRepository.byProgramUid().eq(programUid) ) doReturn programStageCollectionRepository - whenever(programStageCollectionRepository.get()) doReturn Single.just(getProgramStages()) + whenever( + programStageCollectionRepository.byAccessDataWrite().isTrue + ) doReturn programStageCollectionRepository + whenever( + programStageCollectionRepository.get() + ) doReturn Single.just(getProgramStages()) whenever( eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid) @@ -187,7 +191,7 @@ class EnrollmentServiceShould { ) doReturn eventCollectionRepository whenever(eventCollectionRepository.get()) doReturn Single.just(getEventList()) - assertTrue(enrollmentService.allowEventCreation(enrollmentUid, listOf("1"))) + assertTrue(enrollmentService.blockingGetAllowEventCreation(enrollmentUid, listOf("1"))) } @Test @@ -199,7 +203,12 @@ class EnrollmentServiceShould { whenever( programStageCollectionRepository.byProgramUid().eq(programUid) ) doReturn programStageCollectionRepository - whenever(programStageCollectionRepository.get()) doReturn Single.just(getProgramStages()) + whenever( + programStageCollectionRepository.byAccessDataWrite().isTrue + ) doReturn programStageCollectionRepository + whenever( + programStageCollectionRepository.get() + ) doReturn Single.just(getProgramStages()) whenever( eventCollectionRepository.byEnrollmentUid().eq(enrollmentUid) @@ -209,7 +218,7 @@ class EnrollmentServiceShould { ) doReturn eventCollectionRepository whenever(eventCollectionRepository.get()) doReturn Single.just(getEventList()) - assertFalse(enrollmentService.allowEventCreation(enrollmentUid, listOf("1", "2"))) + assertFalse(enrollmentService.blockingGetAllowEventCreation(enrollmentUid, listOf("1", "2"))) } private fun getEventList() = listOf( From 8f2df2b9cceeca717ffa4531615a837fd27f35b2 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 21 Jul 2021 09:49:20 +0200 Subject: [PATCH 213/308] [ANDROSDK-1386] Implement visualization dimension helper --- .../service/AnalyticsVisualizationsService.kt | 26 +- ...icsVisualizationsServiceDimensionHelper.kt | 5 +- ...ualizationsServiceDimensionHelperShould.kt | 262 ++++++++++++++++++ 3 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt index d8961e508e..a32eab0ec3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt @@ -28,10 +28,8 @@ package org.hisp.dhis.android.core.analytics.aggregated.service -import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.* import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepositoryParams -import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse -import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCollectionRepository import javax.inject.Inject @@ -49,6 +47,28 @@ internal class AnalyticsVisualizationsService @Inject constructor( val visualization = getVisualization(params.visualization) val dimensionalResponse = getDimensionalResponse(visualization) + + return GridAnalyticsResponse( + metadata = dimensionalResponse.metadata, + headers = GridHeader( + columns = listOf(), + rows = listOf() + ), + dimensions = GridDimension( + columns = dimensionalResponse.dimensions.toList(), + rows = listOf() + ), + filters = dimensionalResponse.filters, + values = listOf( + dimensionalResponse.values.map { + GridResponseValue( + columns = it.dimensions, + rows = listOf(), + value = it.value + ) + } + ) + ) } private fun getVisualization(visualizationId: String): Visualization { diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt index c0c4da8080..e7adbf6987 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt @@ -70,7 +70,10 @@ internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor DataDimensionItemType.DATA_ELEMENT -> item.dataElement()?.let { DimensionItem.DataItem.DataElementItem(it.uid()) } DataDimensionItemType.DATA_ELEMENT_OPERAND -> - TODO() + item.dataElementOperand()?.let { + val (dataElement, coc) = dataElementOperandRegex.find(it.uid())!!.destructured + DimensionItem.DataItem.DataElementOperandItem(dataElement, coc) + } DataDimensionItemType.PROGRAM_INDICATOR -> item.programIndicator()?.let { DimensionItem.DataItem.ProgramIndicatorItem(it.uid()) } else -> diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt new file mode 100644 index 0000000000..09a880b3b5 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.service + +import com.google.common.truth.Truth.assertThat +import com.nhaarman.mockitokotlin2.doReturn +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import junit.framework.Assert.fail +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.category.Category +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit +import org.hisp.dhis.android.core.common.RelativePeriod +import org.hisp.dhis.android.core.visualization.CategoryDimension +import org.hisp.dhis.android.core.visualization.DataDimensionItem +import org.hisp.dhis.android.core.visualization.DataDimensionItemType +import org.hisp.dhis.android.core.visualization.Visualization +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class AnalyticsVisualizationsServiceDimensionHelperShould { + + private val categoryStore: IdentifiableObjectStore = mock() + private val category: Category = mock() + private val visualization: Visualization = mock() + + private val uid1 = "GMpWZUg2QUf" + private val uid2 = "AC6H8zCDb3B" + private val uid3 = "eEIN8RQWxWp" + + private val helper = AnalyticsVisualizationsServiceDimensionHelper(categoryStore) + + @Test + fun `Should parse dataElement dimension items`() { + val dataDimensionItems = listOf( + DataDimensionItem.builder() + .dataElement(ObjectWithUid.create(uid1)) + .dataDimensionItemType(DataDimensionItemType.DATA_ELEMENT) + .build() + ) + + whenever(visualization.dataDimensionItems()) doReturn dataDimensionItems + + val dimensionItems = helper.getDimensionItems(visualization, listOf("dx")) + + assertThat(dimensionItems).hasSize(1) + when (val item = dimensionItems.first()) { + is DimensionItem.DataItem.DataElementItem -> + assertThat(item.uid).isEqualTo(uid1) + else -> + fail("Unexpected dimension item type") + } + } + + @Test + fun `Should parse dataElementOperand dimension items`() { + val dataDimensionItems = listOf( + DataDimensionItem.builder() + .dataElementOperand(ObjectWithUid.create("$uid1.$uid2")) + .dataDimensionItemType(DataDimensionItemType.DATA_ELEMENT_OPERAND) + .build() + ) + + whenever(visualization.dataDimensionItems()) doReturn dataDimensionItems + + val dimensionItems = helper.getDimensionItems(visualization, listOf("dx")) + + assertThat(dimensionItems).hasSize(1) + when (val item = dimensionItems.first()) { + is DimensionItem.DataItem.DataElementOperandItem -> { + assertThat(item.dataElement).isEqualTo(uid1) + assertThat(item.categoryOptionCombo).isEqualTo(uid2) + } + else -> + fail("Unexpected dimension item type") + } + } + + @Test + fun `Should parse indicator dimension items`() { + val dataDimensionItems = listOf( + DataDimensionItem.builder() + .indicator(ObjectWithUid.create(uid1)) + .dataDimensionItemType(DataDimensionItemType.INDICATOR) + .build() + ) + + whenever(visualization.dataDimensionItems()) doReturn dataDimensionItems + + val dimensionItems = helper.getDimensionItems(visualization, listOf("dx")) + + assertThat(dimensionItems).hasSize(1) + when (val item = dimensionItems.first()) { + is DimensionItem.DataItem.IndicatorItem -> + assertThat(item.uid).isEqualTo(uid1) + else -> + fail("Unexpected dimension item type") + } + } + + @Test + fun `Should parse programIndicator dimension items`() { + val dataDimensionItems = listOf( + DataDimensionItem.builder() + .programIndicator(ObjectWithUid.create(uid1)) + .dataDimensionItemType(DataDimensionItemType.PROGRAM_INDICATOR) + .build() + ) + + whenever(visualization.dataDimensionItems()) doReturn dataDimensionItems + + val dimensionItems = helper.getDimensionItems(visualization, listOf("dx")) + + assertThat(dimensionItems).hasSize(1) + when (val item = dimensionItems.first()) { + is DimensionItem.DataItem.ProgramIndicatorItem -> + assertThat(item.uid).isEqualTo(uid1) + else -> + fail("Unexpected dimension item type") + } + } + + @Test + fun `Should parse organisation unit uids and levels`() { + val orgunitItems = listOf( + ObjectWithUid.create(uid1), + ObjectWithUid.create(uid2) + ) + val orgunitLevels = listOf(1, 3) + + whenever(visualization.organisationUnits()) doReturn orgunitItems + whenever(visualization.organisationUnitLevels()) doReturn orgunitLevels + + val dimensionItems = helper.getDimensionItems(visualization, listOf("ou")) + + assertThat(dimensionItems).hasSize(4) + + val absolute = dimensionItems.filterIsInstance() + assertThat(absolute.map { it.uid }).containsExactly(uid1, uid2) + + val levels = dimensionItems.filterIsInstance() + assertThat(levels.map { it.level }).containsExactlyElementsIn(orgunitLevels) + } + + @Test + fun `Should parse relative organisation unit`() { + whenever(visualization.userOrganisationUnit()) doReturn true + whenever(visualization.userOrganisationUnitChildren()) doReturn true + whenever(visualization.userOrganisationUnitGrandChildren()) doReturn true + + val dimensionItems = helper.getDimensionItems(visualization, listOf("ou")) + + assertThat(dimensionItems).hasSize(3) + + val relative = dimensionItems.filterIsInstance() + assertThat(relative.map { it.relative }).containsExactly( + RelativeOrganisationUnit.USER_ORGUNIT, + RelativeOrganisationUnit.USER_ORGUNIT_CHILDREN, + RelativeOrganisationUnit.USER_ORGUNIT_GRANDCHILDREN + ) + } + + @Test + fun `Should parse period dimension items`() { + val periods = listOf( + ObjectWithUid.create(uid1), + ObjectWithUid.create(uid2) + ) + val relativePeriods = mapOf( + RelativePeriod.THIS_MONTH to true, + RelativePeriod.LAST_MONTH to true + ) + + whenever(visualization.periods()) doReturn periods + whenever(visualization.relativePeriods()) doReturn relativePeriods + + val dimensionItems = helper.getDimensionItems(visualization, listOf("pe")) + + assertThat(dimensionItems).hasSize(4) + + val absolute = dimensionItems.filterIsInstance() + assertThat(absolute.map { it.periodId }).containsExactly(uid1, uid2) + + val relative = dimensionItems.filterIsInstance() + assertThat(relative.map { it.relative }).containsExactly(RelativePeriod.THIS_MONTH, RelativePeriod.LAST_MONTH) + } + + @Test + fun `Should parse category dimension items`() { + val categoryDimensions = listOf( + CategoryDimension.builder() + .category(ObjectWithUid.create(uid1)) + .categoryOptions(listOf(ObjectWithUid.create(uid2), ObjectWithUid.create(uid3))) + .build() + ) + + whenever(visualization.categoryDimensions()) doReturn categoryDimensions + whenever(categoryStore.selectByUid(uid1)) doReturn category + + val dimensionItems = helper.getDimensionItems(visualization, listOf(uid1)) + + assertThat(dimensionItems).hasSize(2) + + val catDimension = dimensionItems.filterIsInstance() + catDimension.forEach { assertThat(it.uid).isEqualTo(uid1) } + assertThat(catDimension.map { it.categoryOption }).containsExactly(uid2, uid3) + } + + @Test + fun `Should combine dimensions items`() { + val periods = listOf( + ObjectWithUid.create(uid1), + ObjectWithUid.create(uid2) + ) + val orgunits = listOf( + ObjectWithUid.create(uid3) + ) + + whenever(visualization.periods()) doReturn periods + whenever(visualization.organisationUnits()) doReturn orgunits + + val dimensionItems = helper.getDimensionItems(visualization, listOf("pe", "ou")) + + assertThat(dimensionItems).hasSize(3) + + val periodItems = dimensionItems.filterIsInstance() + assertThat(periodItems).hasSize(2) + + val orgunitItems = dimensionItems.filterIsInstance() + assertThat(orgunitItems).hasSize(1) + } +} \ No newline at end of file From e8ecee12e8f56d00d31def70a99be3cc26bc47ed Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 21 Jul 2021 09:53:58 +0200 Subject: [PATCH 214/308] [ANDROSDK-1386] Refactor packages --- .../DataElementEvaluatorIntegrationShould.kt | 36 +++++++++---------- .../evaluator/DataElementEvaluatorSamples.kt | 2 +- .../aggregated/AggregatedEntityDIModule.kt | 2 ++ .../AnalyticsException.kt | 2 +- .../AnalyticsOrganisationUnitHelper.kt | 2 +- .../{ => internal}/AnalyticsRepositoryImpl.kt | 6 ++-- .../AnalyticsRepositoryParams.kt | 4 ++- .../{service => internal}/AnalyticsService.kt | 3 +- .../AnalyticsServiceDimensionHelper.kt | 3 +- .../AnalyticsServiceEvaluationItem.kt | 2 +- .../AnalyticsServiceEvaluatorHelper.kt | 6 ++-- .../AnalyticsServiceMetadataHelper.kt | 2 +- .../AnalyticsVisualizationsRepositoryImpl.kt | 5 +-- ...AnalyticsVisualizationsRepositoryParams.kt | 2 +- .../AnalyticsVisualizationsService.kt | 3 +- ...icsVisualizationsServiceDimensionHelper.kt | 2 +- .../evaluator/AnalyticsEvaluator.kt | 4 +-- .../evaluator/AnalyticsEvaluatorHelper.kt | 2 +- .../evaluator/DataElementEvaluator.kt | 6 ++-- .../AnalyticsServiceDimensionHelperShould.kt | 5 ++- .../AnalyticsServiceHelperSamples.kt | 2 +- .../AnalyticsServiceMetadataHelperShould.kt | 4 +-- ...ualizationsServiceDimensionHelperShould.kt | 2 +- 23 files changed, 55 insertions(+), 52 deletions(-) rename core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/evaluator/DataElementEvaluatorIntegrationShould.kt (87%) rename core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/evaluator/DataElementEvaluatorSamples.kt (98%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsException.kt (96%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsOrganisationUnitHelper.kt (98%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{ => internal}/AnalyticsRepositoryImpl.kt (90%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{ => internal}/AnalyticsRepositoryParams.kt (92%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsService.kt (95%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceDimensionHelper.kt (96%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceEvaluationItem.kt (96%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceEvaluatorHelper.kt (94%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceMetadataHelper.kt (99%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{ => internal}/AnalyticsVisualizationsRepositoryImpl.kt (91%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{ => internal}/AnalyticsVisualizationsRepositoryParams.kt (96%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsVisualizationsService.kt (96%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsVisualizationsServiceDimensionHelper.kt (98%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/evaluator/AnalyticsEvaluator.kt (91%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/evaluator/AnalyticsEvaluatorHelper.kt (98%) rename core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/evaluator/DataElementEvaluator.kt (97%) rename core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceDimensionHelperShould.kt (97%) rename core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceHelperSamples.kt (97%) rename core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsServiceMetadataHelperShould.kt (96%) rename core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/{service => internal}/AnalyticsVisualizationsServiceDimensionHelperShould.kt (99%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluatorIntegrationShould.kt similarity index 87% rename from core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt rename to core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluatorIntegrationShould.kt index a481d4682a..f0bac9912a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluatorIntegrationShould.kt @@ -25,28 +25,28 @@ * (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.analytics.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator import com.google.common.truth.Truth.assertThat import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.category -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCategoryComboLink -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCategoryOptionLink -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryCombo -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOption -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionCombo -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.categoryOptionComboCategoryOptionLink -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement1 -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElement2 -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.dataElementOperand -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild1 -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitChild2 -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.orgunitParent -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodDec -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodNov -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluatorSamples.periodQ4 +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsServiceEvaluationItem +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.category +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.categoryCategoryComboLink +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.categoryCategoryOptionLink +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.categoryCombo +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.categoryOption +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.categoryOptionCombo +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.categoryOptionComboCategoryOptionLink +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.dataElement1 +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.dataElement2 +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.dataElementOperand +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.orgunitChild1 +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.orgunitChild2 +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.orgunitParent +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.periodDec +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.periodNov +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluatorSamples.periodQ4 import org.hisp.dhis.android.core.category.internal.* import org.hisp.dhis.android.core.common.RelativeOrganisationUnit import org.hisp.dhis.android.core.common.RelativePeriod diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluatorSamples.kt similarity index 98% rename from core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt rename to core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluatorSamples.kt index d912841128..1c3dfbdfda 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluatorSamples.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluatorSamples.kt @@ -25,7 +25,7 @@ * (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.analytics.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator import org.hisp.dhis.android.core.arch.helpers.DateUtils import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index 123378c40e..8f4cf7e2a8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -32,6 +32,8 @@ import dagger.Provides import dagger.Reusable import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsRepository import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsVisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsVisualizationsRepositoryParams @Module internal class AggregatedEntityDIModule { diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsException.kt similarity index 96% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsException.kt index c027166485..3e58696501 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsException.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsException.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal sealed class AnalyticsException(message: String) : Throwable(message) { class InvalidArguments(message: String) : AnalyticsException(message) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsOrganisationUnitHelper.kt similarity index 98% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsOrganisationUnitHelper.kt index 1fe19a2015..58e732f2c9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsOrganisationUnitHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsOrganisationUnitHelper.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt similarity index 90% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt index 51debf51ae..38147e8178 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt @@ -26,11 +26,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated +package org.hisp.dhis.android.core.analytics.aggregated.internal import io.reactivex.Single +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse import javax.inject.Inject -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsService internal class AnalyticsRepositoryImpl @Inject constructor( private val params: AnalyticsRepositoryParams, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryParams.kt similarity index 92% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryParams.kt index dac86921ea..6d40111b59 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsRepositoryParams.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryParams.kt @@ -26,7 +26,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated +package org.hisp.dhis.android.core.analytics.aggregated.internal + +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem internal data class AnalyticsRepositoryParams( val dimensions: List, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt similarity index 95% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt index 97e60749e3..c0dc1b7eb6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt @@ -26,10 +26,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import javax.inject.Inject -import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt similarity index 96% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt index 1caa76faf1..5ebbe321e5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt @@ -26,11 +26,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem -import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceEvaluationItem.kt similarity index 96% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceEvaluationItem.kt index 0a272622f6..4a28da7ae7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluationItem.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceEvaluationItem.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceEvaluatorHelper.kt similarity index 94% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceEvaluatorHelper.kt index 55fa90eaa9..2c721cec42 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceEvaluatorHelper.kt @@ -26,14 +26,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.AnalyticsEvaluator -import org.hisp.dhis.android.core.analytics.aggregated.service.evaluator.DataElementEvaluator +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.AnalyticsEvaluator +import org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator.DataElementEvaluator internal class AnalyticsServiceEvaluatorHelper @Inject constructor( private val dataElementEvaluator: DataElementEvaluator diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelper.kt similarity index 99% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelper.kt index 72eda95c8a..329fa02b57 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelper.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt similarity index 91% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt index a3ec8a30a2..f23b939a82 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt @@ -26,10 +26,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated +package org.hisp.dhis.android.core.analytics.aggregated.internal import io.reactivex.Single -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsVisualizationsService +import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse import javax.inject.Inject internal class AnalyticsVisualizationsRepositoryImpl @Inject constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt similarity index 96% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt index a05223977c..89b39feae0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepositoryParams.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated +package org.hisp.dhis.android.core.analytics.aggregated.internal internal data class AnalyticsVisualizationsRepositoryParams( val visualization: String? diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt similarity index 96% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt index a32eab0ec3..e36768fe2b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt @@ -26,10 +26,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import org.hisp.dhis.android.core.analytics.aggregated.* -import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepositoryParams import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCollectionRepository import javax.inject.Inject diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt similarity index 98% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt index e7adbf6987..0a3cce48a9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsEvaluator.kt similarity index 91% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsEvaluator.kt index 4982699aab..24a01cb058 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsEvaluator.kt @@ -26,10 +26,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsServiceEvaluationItem internal interface AnalyticsEvaluator { diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsEvaluatorHelper.kt similarity index 98% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsEvaluatorHelper.kt index 9ed6d26212..b01eb27907 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/AnalyticsEvaluatorHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsEvaluatorHelper.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator import org.hisp.dhis.android.core.arch.helpers.DateUtils import org.hisp.dhis.android.core.category.CategoryCategoryComboLinkTableInfo as cToCcInfo diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluator.kt similarity index 97% rename from core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt rename to core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluator.kt index 62f279a85e..246ef4a756 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/service/evaluator/DataElementEvaluator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/DataElementEvaluator.kt @@ -26,14 +26,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service.evaluator +package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsException -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceEvaluationItem +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsException +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsServiceEvaluationItem import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.AggregationType diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt similarity index 97% rename from core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt rename to core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt index 8c3aa949ee..5b4db61a75 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceDimensionHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt @@ -27,17 +27,16 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import org.hisp.dhis.android.core.analytics.aggregated.AbsoluteDimensionItem -import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsServiceHelperSamples as s import org.hisp.dhis.android.core.period.Period import org.hisp.dhis.android.core.period.internal.ParentPeriodGenerator import org.junit.Test diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceHelperSamples.kt similarity index 97% rename from core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt rename to core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceHelperSamples.kt index e4285a1466..5f0564a05d 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceHelperSamples.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceHelperSamples.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt similarity index 96% rename from core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt rename to core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt index 7bd5ae6fb3..e241da4f4e 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsServiceMetadataHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt @@ -26,13 +26,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples -import org.hisp.dhis.android.core.analytics.aggregated.service.AnalyticsServiceHelperSamples as s +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsServiceHelperSamples as s import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.category.CategoryOption diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt similarity index 99% rename from core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt rename to core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt index 09a880b3b5..4fd8c7fdf3 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/service/AnalyticsVisualizationsServiceDimensionHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt @@ -26,7 +26,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.core.analytics.aggregated.service +package org.hisp.dhis.android.core.analytics.aggregated.internal import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.doReturn From 1b6d06de2884d9c7764021ca338e381db50c20bb Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 21 Jul 2021 11:38:09 +0200 Subject: [PATCH 215/308] [ANDROSDK-1386] Force RelativePeriods adapter to return an Enum --- .../internal/JSONObjectMapColumnAdapter.kt | 65 ------------------- .../internal/RelativePeriodsColumnAdapter.kt | 37 +++++++++-- 2 files changed, 33 insertions(+), 69 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt deleted file mode 100644 index b840b8bd1b..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/JSONObjectMapColumnAdapter.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.db.adapters.custom.internal - -import android.content.ContentValues -import android.database.Cursor -import com.fasterxml.jackson.core.JsonProcessingException -import com.fasterxml.jackson.databind.JsonMappingException -import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter -import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory - -internal abstract class JSONObjectMapColumnAdapter : ColumnTypeAdapter> { - protected abstract fun getObjectClass(): Class> - - override fun fromCursor(cursor: Cursor, columnName: String): Map { - val columnIndex = cursor.getColumnIndex(columnName) - val str = cursor.getString(columnIndex) - return try { - ObjectMapperFactory.objectMapper().readValue(str, getObjectClass()) - } catch (e: JsonProcessingException) { - hashMapOf() - } catch (e: JsonMappingException) { - hashMapOf() - } catch (e: IllegalArgumentException) { - hashMapOf() - } catch (e: IllegalStateException) { - hashMapOf() - } - } - - override fun toContentValues(contentValues: ContentValues, columnName: String, o: Map?) { - try { - contentValues.put(columnName, serialize(o)) - } catch (e: JsonProcessingException) { - e.printStackTrace() - } - } - - abstract fun serialize(o: Map?): String? -} diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt index 7f0ccd165c..1676628923 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -27,15 +27,44 @@ */ package org.hisp.dhis.android.core.arch.db.adapters.custom.internal +import android.content.ContentValues +import android.database.Cursor +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.JsonMappingException +import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory import org.hisp.dhis.android.core.common.RelativePeriod +import java.util.* +import kotlin.collections.HashMap -internal class RelativePeriodsColumnAdapter : JSONObjectMapColumnAdapter() { - override fun getObjectClass(): Class> { - return HashMap().javaClass +internal class RelativePeriodsColumnAdapter : ColumnTypeAdapter> { + + override fun fromCursor(cursor: Cursor, columnName: String): Map { + val columnIndex = cursor.getColumnIndex(columnName) + val str = cursor.getString(columnIndex) + return try { + val map = ObjectMapperFactory.objectMapper().readValue(str, (HashMap())::class.java) + map.mapKeys { RelativePeriod.valueOf(it.key) } + } catch (e: JsonProcessingException) { + EnumMap(RelativePeriod::class.java) + } catch (e: JsonMappingException) { + EnumMap(RelativePeriod::class.java) + } catch (e: IllegalArgumentException) { + EnumMap(RelativePeriod::class.java) + } catch (e: IllegalStateException) { + EnumMap(RelativePeriod::class.java) + } + } + + override fun toContentValues(contentValues: ContentValues, columnName: String, o: Map?) { + try { + contentValues.put(columnName, serialize(o)) + } catch (e: JsonProcessingException) { + e.printStackTrace() + } } - override fun serialize(o: Map?): String? = RelativePeriodsColumnAdapter.serialize(o) + private fun serialize(o: Map?): String? = RelativePeriodsColumnAdapter.serialize(o) companion object { fun serialize(o: Map?): String? { From b70cd0058255c193bc3a5640f9db4506487664c1 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 21 Jul 2021 11:41:05 +0200 Subject: [PATCH 216/308] [ANDROSDK-1386] Ktlint --- .../core/analytics/aggregated/AggregatedEntityDIModule.kt | 4 ++-- .../analytics/aggregated/internal/AnalyticsRepositoryImpl.kt | 2 +- .../internal/AnalyticsVisualizationsRepositoryImpl.kt | 2 +- .../aggregated/internal/AnalyticsVisualizationsService.kt | 4 ++-- .../AnalyticsVisualizationsServiceDimensionHelper.kt | 5 ++--- .../aggregated/mock/MockAnalyticsVisualizationsRepository.kt | 2 +- .../adapters/custom/internal/RelativePeriodsColumnAdapter.kt | 4 ++-- .../internal/AnalyticsServiceMetadataHelperShould.kt | 2 +- .../AnalyticsVisualizationsServiceDimensionHelperShould.kt | 2 +- 9 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index 8f4cf7e2a8..55ec8513b5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -30,10 +30,10 @@ package org.hisp.dhis.android.core.analytics.aggregated import dagger.Module import dagger.Provides import dagger.Reusable -import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsRepository -import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsVisualizationsRepository import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsRepositoryParams import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsVisualizationsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsRepository +import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsVisualizationsRepository @Module internal class AggregatedEntityDIModule { diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt index 38147e8178..e71bd8fe61 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsRepositoryImpl.kt @@ -29,10 +29,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsRepository import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse -import javax.inject.Inject internal class AnalyticsRepositoryImpl @Inject constructor( private val params: AnalyticsRepositoryParams, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt index f23b939a82..73d90ce71e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt @@ -29,9 +29,9 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal import io.reactivex.Single +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse -import javax.inject.Inject internal class AnalyticsVisualizationsRepositoryImpl @Inject constructor( private val params: AnalyticsVisualizationsRepositoryParams, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt index e36768fe2b..7eec2d170c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.* import org.hisp.dhis.android.core.visualization.Visualization import org.hisp.dhis.android.core.visualization.VisualizationCollectionRepository -import javax.inject.Inject internal class AnalyticsVisualizationsService @Inject constructor( private val analyticsRepository: AnalyticsRepository, @@ -84,7 +84,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( val queryDimensions = (visualization.rowDimensions() ?: emptyList()) + - (visualization.columnDimensions() ?: emptyList()) + (visualization.columnDimensions() ?: emptyList()) dimensionHelper.getDimensionItems( visualization, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt index 0a3cce48a9..326ec8942c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt @@ -28,13 +28,13 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal +import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.common.RelativeOrganisationUnit.* import org.hisp.dhis.android.core.visualization.DataDimensionItemType import org.hisp.dhis.android.core.visualization.Visualization -import javax.inject.Inject internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor( private val categoryStore: IdentifiableObjectStore @@ -47,7 +47,7 @@ internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor fun getDimensionItems(visualization: Visualization, dimensions: List?): List { return dimensions?.map { dimension -> - when(dimension) { + when (dimension) { dataDimension -> extractDataDimensionItems(visualization) orgUnitDimension -> extractOrgunitDimensionItems(visualization) periodDimension -> extractPeriodDimensionItems(visualization) @@ -125,7 +125,6 @@ internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor categoryDimension?.categoryOptions()?.map { DimensionItem.CategoryItem(uid, it.uid()) } ?: emptyList() - } else { emptyList() } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt index 8ac9172a4f..dda4db5268 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt @@ -31,8 +31,8 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock import dagger.Reusable import io.reactivex.Single import javax.inject.Inject -import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse @Reusable class MockAnalyticsVisualizationsRepository @Inject constructor() : AnalyticsVisualizationsRepository { diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt index 1676628923..02881ddc2c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/RelativePeriodsColumnAdapter.kt @@ -32,10 +32,10 @@ import android.database.Cursor import com.fasterxml.jackson.core.JsonProcessingException import com.fasterxml.jackson.databind.JsonMappingException import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter -import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory -import org.hisp.dhis.android.core.common.RelativePeriod import java.util.* import kotlin.collections.HashMap +import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.common.RelativePeriod internal class RelativePeriodsColumnAdapter : ColumnTypeAdapter> { diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt index e241da4f4e..80f7e01dd4 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceMetadataHelperShould.kt @@ -31,8 +31,8 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever -import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsServiceHelperSamples as s +import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.category.CategoryOption diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt index 4fd8c7fdf3..c9c53f7bcf 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelperShould.kt @@ -259,4 +259,4 @@ class AnalyticsVisualizationsServiceDimensionHelperShould { val orgunitItems = dimensionItems.filterIsInstance() assertThat(orgunitItems).hasSize(1) } -} \ No newline at end of file +} From 7ec3af04463fb28a9c72ced9dde4d3ea0914bc6b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 21 Jul 2021 12:00:00 +0200 Subject: [PATCH 217/308] [ANDROSDK-1386] Add Visualization integration test --- ...isualizationRepositoryIntegrationShould.kt | 46 +++++++++++++++++++ .../MockAnalyticsVisualizationsRepository.kt | 4 +- .../visualization/visualizations.json | 40 +++------------- 3 files changed, 55 insertions(+), 35 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt new file mode 100644 index 0000000000..a1e4979436 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.analytics.aggregated.internal.evaluator + +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher +import org.junit.Test + +class AnalyticsVisualizationRepositoryIntegrationShould : BaseMockIntegrationTestFullDispatcher() { + + private val visualationUid = "FAFa11yFeFe" + + @Test + fun evaluate_visualization() { + val result = d2.analyticsModule().visualizations() + .withVisualization(visualationUid) + .blockingEvaluate() + + // TODO Implement when actual visualization service is used + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt index dda4db5268..301e8090e7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt @@ -37,7 +37,9 @@ import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse @Reusable class MockAnalyticsVisualizationsRepository @Inject constructor() : AnalyticsVisualizationsRepository { - override fun withVisualization(visualization: String): AnalyticsVisualizationsRepository = TODO() + override fun withVisualization(visualization: String): AnalyticsVisualizationsRepository { + return MockAnalyticsVisualizationsRepository() + } override fun evaluate(): Single { return Single.fromCallable { blockingEvaluate() } diff --git a/core/src/sharedTest/resources/visualization/visualizations.json b/core/src/sharedTest/resources/visualization/visualizations.json index 72b6dbf25c..355ac94450 100644 --- a/core/src/sharedTest/resources/visualization/visualizations.json +++ b/core/src/sharedTest/resources/visualization/visualizations.json @@ -128,23 +128,8 @@ "displayDensity": "NORMAL", "digitGroupSeparator": "COMMA", "relativePeriods": { - "today": true, - "last12Months": false }, "categoryDimensions": [ - { - "category": { - "id": "cX5k9anHEHd" - }, - "categoryOptions": [ - { - "id": "apsOixVZlf1" - }, - { - "id": "jRbMi0aBjYn" - } - ] - } ], "filterDimensions": [ "ou" @@ -153,48 +138,35 @@ "pe" ], "columnDimensions": [ - "dx", - "fMZEcRHuamy", - "fkAkrdC7eJF" + "dx" ], "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "Uvn6LCg7dVU" - } - }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "cYeuwXTCPkU" + "id": "g9eOBujte1U" } } ], "organisationUnitLevels": [ - 1, - 2 ], "userOrganisationUnit": false, "userOrganisationUnitChildren": false, "userOrganisationUnitGrandChildren": false, "organisationUnits": [ { - "id": "YuQRtpLP10I" - }, - { - "id": "vWbkYPRmKyS" + "id": "DiszpKrYNg8" } ], "periods": [ { - "id": "202102" + "id": "2016" }, { - "id": "202103" + "id": "2017" }, { - "id": "2021S2" + "id": "2018" } ] } From 564373c59a1e0e58d619b2892f2088be3140f059 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 22 Jul 2021 08:17:24 +0200 Subject: [PATCH 218/308] [ANDROSDK-1386] Build GridResponseValue --- .../AnalyticsVisualizationsService.kt | 95 ++++++++++++++----- ...icsVisualizationsServiceDimensionHelper.kt | 36 +++++++ 2 files changed, 109 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt index 7eec2d170c..6fad733939 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt @@ -47,27 +47,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( val visualization = getVisualization(params.visualization) val dimensionalResponse = getDimensionalResponse(visualization) - return GridAnalyticsResponse( - metadata = dimensionalResponse.metadata, - headers = GridHeader( - columns = listOf(), - rows = listOf() - ), - dimensions = GridDimension( - columns = dimensionalResponse.dimensions.toList(), - rows = listOf() - ), - filters = dimensionalResponse.filters, - values = listOf( - dimensionalResponse.values.map { - GridResponseValue( - columns = it.dimensions, - rows = listOf(), - value = it.value - ) - } - ) - ) + return buildGridResponse(visualization, dimensionalResponse) } private fun getVisualization(visualizationId: String): Visualization { @@ -84,7 +64,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( val queryDimensions = (visualization.rowDimensions() ?: emptyList()) + - (visualization.columnDimensions() ?: emptyList()) + (visualization.columnDimensions() ?: emptyList()) dimensionHelper.getDimensionItems( visualization, @@ -102,4 +82,75 @@ internal class AnalyticsVisualizationsService @Inject constructor( return analyticsRepository.blockingEvaluate() } + + private fun buildGridResponse( + visualization: Visualization, + dimensionalResponse: DimensionalResponse + ): GridAnalyticsResponse { + + val gridDimension = dimensionHelper.getGridDimensions(visualization) + + val rowIndexes = gridDimension.rows.map { dimensionalResponse.dimensions.indexOf(it) } + + val groupedByRow = dimensionalResponse.values.groupBy { value -> + rowIndexes.map { rowIndex -> value.dimensions[rowIndex] } + } + + val gridValues = groupedByRow.map { (rows, valueList) -> + valueList.map { value -> + GridResponseValue( + columns = value.dimensions.filterNot { rows.contains(it) }, + rows = rows, + value = value.value + ) + } + } + + val gridHeader = buildGridHeader(gridValues) + + return GridAnalyticsResponse( + metadata = dimensionalResponse.metadata, + headers = gridHeader, + dimensions = gridDimension, + filters = dimensionalResponse.filters, + values = gridValues + ) + } + + private fun buildGridHeader(gridValues: List>): GridHeader { + if (gridValues.isEmpty() || gridValues.first().isEmpty()) { + return GridHeader(emptyList(), emptyList()) + } + + val sampleRow = gridValues.first() + + val columnCount = sampleRow.first().columns.size + val columns = (0 until columnCount).map { columnIdx -> + val columnValues = sampleRow.map { it.columns[columnIdx] } + getGridHeaderItems(columnValues) + } + + val sampleColumn = gridValues.map { it.first() } + + val rowCount = sampleColumn.first().rows.size + val rows = (0 until rowCount).map { rowIdx -> + val rowValues = sampleColumn.map { it.rows[rowIdx] } + getGridHeaderItems(rowValues) + } + + return GridHeader(columns, rows) + } + + private fun getGridHeaderItems(values: List): List { + val groups = mutableListOf() + values.forEach { + val last = groups.lastOrNull() + if (last?.id == it) { + groups[groups.lastIndex] = last.copy(width = last.width + 1) + } else { + groups.add(GridHeaderItem(it, 1)) + } + } + return groups + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt index 326ec8942c..be99ccd9d7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt @@ -28,8 +28,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal +import org.hisp.dhis.android.core.analytics.aggregated.Dimension import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.analytics.aggregated.GridDimension import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.category.Category import org.hisp.dhis.android.core.common.RelativeOrganisationUnit.* @@ -129,4 +131,38 @@ internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor emptyList() } } + + fun getGridDimensions(visualization: Visualization): GridDimension { + val columns = mapDimensions(visualization.columnDimensions()) + val rows = mapDimensions(visualization.rowDimensions()) + + return GridDimension(columns, rows) + } + + private fun mapDimensions(dimensionStrs: List?): List { + return dimensionStrs?.mapNotNull { + when(it) { + dataDimension -> Dimension.Data + periodDimension -> Dimension.Period + orgUnitDimension -> Dimension.OrganisationUnit + else -> { + if (uidRegex.matches(it)) { + extractUidDimension(it) + } else { + null + } + } + } + } ?: emptyList() + } + + private fun extractUidDimension(uid: String): Dimension? { + val category = categoryStore.selectByUid(uid) + + return if (category != null) { + Dimension.Category(uid) + } else { + null + } + } } From 3aadc6161c8e2e1aec306850bd5f933fe4ea764c Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 22 Jul 2021 09:24:29 +0200 Subject: [PATCH 219/308] [ANDROSDK-1386] Disable mock analytic repositories --- ...nalyticsVisualizationRepositoryIntegrationShould.kt | 10 +++++++--- .../analytics/aggregated/AggregatedEntityDIModule.kt | 8 ++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt index a1e4979436..3ff7a47d90 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt @@ -28,19 +28,23 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator +import com.google.common.truth.Truth.assertThat import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher import org.junit.Test class AnalyticsVisualizationRepositoryIntegrationShould : BaseMockIntegrationTestFullDispatcher() { - private val visualationUid = "FAFa11yFeFe" + private val visualizationUid = "FAFa11yFeFe" @Test fun evaluate_visualization() { val result = d2.analyticsModule().visualizations() - .withVisualization(visualationUid) + .withVisualization(visualizationUid) .blockingEvaluate() - // TODO Implement when actual visualization service is used + assertThat(result.dimensions.columns).hasSize(1) + assertThat(result.dimensions.rows).hasSize(1) + assertThat(result.metadata).isNotEmpty() + assertThat(result.values).hasSize(3) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index 55ec8513b5..bee9a5b06a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -30,23 +30,23 @@ package org.hisp.dhis.android.core.analytics.aggregated import dagger.Module import dagger.Provides import dagger.Reusable +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsRepositoryImpl import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsRepositoryParams +import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsVisualizationsRepositoryImpl import org.hisp.dhis.android.core.analytics.aggregated.internal.AnalyticsVisualizationsRepositoryParams -import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsRepository -import org.hisp.dhis.android.core.analytics.aggregated.mock.MockAnalyticsVisualizationsRepository @Module internal class AggregatedEntityDIModule { @Provides @Reusable - fun analytics(impl: MockAnalyticsRepository): AnalyticsRepository { + fun analytics(impl: AnalyticsRepositoryImpl): AnalyticsRepository { return impl } @Provides @Reusable - fun visualizations(impl: MockAnalyticsVisualizationsRepository): AnalyticsVisualizationsRepository { + fun visualizations(impl: AnalyticsVisualizationsRepositoryImpl): AnalyticsVisualizationsRepository { return impl } From 20ea5949c08cf9a7d6fc0851b23f90e447055301 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 22 Jul 2021 09:25:16 +0200 Subject: [PATCH 220/308] [ANDROSDK-1386] Explicitly adapt ObjectWithUid list --- .../ObjectWithUidListColumnAdapter.kt | 37 +++++++++++++++++-- .../core/visualization/CategoryDimension.java | 14 ++----- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt index da0d49fef9..d8a8ac87ed 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt @@ -27,15 +27,44 @@ */ package org.hisp.dhis.android.core.arch.db.adapters.custom.internal +import android.content.ContentValues +import android.database.Cursor +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.JsonMappingException +import com.fasterxml.jackson.module.kotlin.readValue +import com.gabrielittner.auto.value.cursor.ColumnTypeAdapter import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory +import org.hisp.dhis.android.core.common.BaseIdentifiableObject import org.hisp.dhis.android.core.common.ObjectWithUid -internal class ObjectWithUidListColumnAdapter : JSONObjectListColumnAdapter() { - override fun getObjectClass(): Class> { - return ArrayList().javaClass +internal class ObjectWithUidListColumnAdapter : ColumnTypeAdapter> { + + override fun fromCursor(cursor: Cursor, columnName: String): List { + val columnIndex = cursor.getColumnIndex(columnName) + val str = cursor.getString(columnIndex) + return try { + val list = ObjectMapperFactory.objectMapper().readValue>>(str) + list.map { ObjectWithUid.create(it[BaseIdentifiableObject.UID].toString()) } + } catch (e: JsonProcessingException) { + listOf() + } catch (e: JsonMappingException) { + listOf() + } catch (e: IllegalArgumentException) { + listOf() + } catch (e: IllegalStateException) { + listOf() + } + } + + override fun toContentValues(contentValues: ContentValues, columnName: String, o: List?) { + try { + contentValues.put(columnName, serialize(o)) + } catch (e: JsonProcessingException) { + e.printStackTrace() + } } - override fun serialize(o: List?): String? = ObjectWithUidListColumnAdapter.serialize(o) + private fun serialize(o: List?): String? = ObjectWithUidListColumnAdapter.serialize(o) companion object { fun serialize(o: List?): String? { diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java index d3a806144d..459bc74ea6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java @@ -35,32 +35,26 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; -import com.gabrielittner.auto.value.cursor.ColumnAdapter; import com.google.auto.value.AutoValue; -import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.ObjectWithUidListColumnAdapter; -import org.hisp.dhis.android.core.arch.db.adapters.identifiable.internal.ObjectWithUidColumnAdapter; -import org.hisp.dhis.android.core.common.CoreObject; import org.hisp.dhis.android.core.common.ObjectWithUid; import java.util.List; @AutoValue -@JsonDeserialize(builder = $$AutoValue_CategoryDimension.Builder.class) -public abstract class CategoryDimension implements CoreObject { +@JsonDeserialize(builder = $AutoValue_CategoryDimension.Builder.class) +public abstract class CategoryDimension { @Nullable @JsonProperty() - @ColumnAdapter(ObjectWithUidColumnAdapter.class) public abstract ObjectWithUid category(); @Nullable @JsonProperty() - @ColumnAdapter(ObjectWithUidListColumnAdapter.class) public abstract List categoryOptions(); public static Builder builder() { - return new $$AutoValue_CategoryDimension.Builder(); + return new $AutoValue_CategoryDimension.Builder(); } public static CategoryDimension create(Cursor cursor) { @@ -73,8 +67,6 @@ public static CategoryDimension create(Cursor cursor) { @JsonPOJOBuilder(withPrefix = "") public static abstract class Builder { - public abstract Builder id(Long id); - public abstract Builder category(ObjectWithUid category); public abstract Builder categoryOptions(List categoryOptions); From e3fa8e543b7eda167709105490724bd2b96f68e9 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 22 Jul 2021 09:28:42 +0200 Subject: [PATCH 221/308] [ANDROSDK-1386] Ktlint --- .../aggregated/internal/AnalyticsVisualizationsService.kt | 2 +- .../internal/AnalyticsVisualizationsServiceDimensionHelper.kt | 4 ++-- .../custom/internal/ObjectWithUidListColumnAdapter.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt index 6fad733939..0c16cb1502 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt @@ -64,7 +64,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( val queryDimensions = (visualization.rowDimensions() ?: emptyList()) + - (visualization.columnDimensions() ?: emptyList()) + (visualization.columnDimensions() ?: emptyList()) dimensionHelper.getDimensionItems( visualization, diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt index be99ccd9d7..83be5c1891 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsServiceDimensionHelper.kt @@ -28,8 +28,8 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal -import org.hisp.dhis.android.core.analytics.aggregated.Dimension import javax.inject.Inject +import org.hisp.dhis.android.core.analytics.aggregated.Dimension import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.GridDimension import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore @@ -141,7 +141,7 @@ internal class AnalyticsVisualizationsServiceDimensionHelper @Inject constructor private fun mapDimensions(dimensionStrs: List?): List { return dimensionStrs?.mapNotNull { - when(it) { + when (it) { dataDimension -> Dimension.Data periodDimension -> Dimension.Period orgUnitDimension -> Dimension.OrganisationUnit diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt index d8a8ac87ed..a233e40c79 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/custom/internal/ObjectWithUidListColumnAdapter.kt @@ -43,7 +43,7 @@ internal class ObjectWithUidListColumnAdapter : ColumnTypeAdapter>>(str) + val list = ObjectMapperFactory.objectMapper().readValue>>(str) list.map { ObjectWithUid.create(it[BaseIdentifiableObject.UID].toString()) } } catch (e: JsonProcessingException) { listOf() From 3eb8b4980170e959a0c20f1a6e3ba8d1ab33e196 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 22 Jul 2021 09:53:54 +0200 Subject: [PATCH 222/308] [ANDROSDK-1386] Clean up CategoryDimension class --- .../MetadataCallRealIntegrationShould.java | 16 ++++++++++++++-- .../core/visualization/CategoryDimension.java | 10 ++-------- .../CategoryDimensionPublicAccessShould.java | 18 ++++-------------- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java index c7411c5248..670da73b26 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java @@ -30,7 +30,10 @@ import android.util.Log; +import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse; +import org.hisp.dhis.android.core.data.server.RealServerMother; import org.junit.Before; +import org.junit.Test; import java.io.IOException; @@ -70,11 +73,20 @@ make a debugger break point where desired (after sync complete) //This test is uncommented because technically it is flaky. //It depends on a live server to operate and the login is hardcoded here. //Uncomment in order to quickly test changes vs a real server, but keep it uncommented after. - //@Test + @Test public void response_successful_on_sync_meta_data_once() throws Exception { - d2.userModule().logIn(username, password, url).blockingGet(); + d2.userModule().logIn(username, password, RealServerMother.android_previous1).blockingGet(); d2.metadataModule().blockingDownload(); + d2.aggregatedModule().data().blockingDownload(); + + GridAnalyticsResponse response1 = d2.analyticsModule().visualizations() + .withVisualization("AfvoZpi4thl") + .blockingEvaluate(); + + GridAnalyticsResponse response2 = d2.analyticsModule().visualizations() + .withVisualization("TXcKIg4LuA3") + .blockingEvaluate(); //TODO: add additional sync + break point. diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java index 459bc74ea6..2cfb87c924 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/CategoryDimension.java @@ -28,8 +28,6 @@ package org.hisp.dhis.android.core.visualization; -import android.database.Cursor; - import androidx.annotation.Nullable; import com.fasterxml.jackson.annotation.JsonProperty; @@ -42,7 +40,7 @@ import java.util.List; @AutoValue -@JsonDeserialize(builder = $AutoValue_CategoryDimension.Builder.class) +@JsonDeserialize(builder = AutoValue_CategoryDimension.Builder.class) public abstract class CategoryDimension { @Nullable @@ -54,11 +52,7 @@ public abstract class CategoryDimension { public abstract List categoryOptions(); public static Builder builder() { - return new $AutoValue_CategoryDimension.Builder(); - } - - public static CategoryDimension create(Cursor cursor) { - return AutoValue_CategoryDimension.createFromCursor(cursor); + return new AutoValue_CategoryDimension.Builder(); } public abstract Builder toBuilder(); diff --git a/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java index 3967ff53ad..5934641cb8 100644 --- a/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java +++ b/core/src/test/java/org/hisp/dhis/android/testapp/visualization/CategoryDimensionPublicAccessShould.java @@ -26,27 +26,17 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.testapp.categoryDimension; +package org.hisp.dhis.android.testapp.visualization; import org.hisp.dhis.android.core.visualization.CategoryDimension; -import org.hisp.dhis.android.testapp.arch.BasePublicAccessShould; +import org.hisp.dhis.android.testapp.arch.ObjectWithBuilderShould; import org.mockito.Mock; -public class CategoryDimensionPublicAccessShould extends BasePublicAccessShould { +public class CategoryDimensionPublicAccessShould extends ObjectWithBuilderShould { @Mock private CategoryDimension object; - @Override - public CategoryDimension object() { - return object; - } - - @Override - public void has_public_create_method() { - CategoryDimension.create(null); - } - @Override public void has_public_builder_method() { CategoryDimension.builder(); @@ -54,6 +44,6 @@ public void has_public_builder_method() { @Override public void has_public_to_builder_method() { - object().toBuilder(); + object.toBuilder(); } } \ No newline at end of file From 46ddc31b1af7d6ab4229da97d878bfe2ab8db581 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 22 Jul 2021 11:29:06 +0200 Subject: [PATCH 223/308] [ANDROSDK-1386] Minor changes in anaytics model --- .../MetadataCallRealIntegrationShould.java | 18 +++--------------- ...VisualizationRepositoryIntegrationShould.kt | 6 +++--- .../aggregated/DimensionalResponse.kt | 2 +- .../aggregated/GridAnalyticsResponse.kt | 2 +- .../AnalyticsServiceDimensionHelper.kt | 6 +++--- .../internal/AnalyticsVisualizationsService.kt | 2 +- .../mock/DimensionalResponseSamples.kt | 2 +- .../AnalyticsServiceDimensionHelperShould.kt | 8 ++++---- 8 files changed, 17 insertions(+), 29 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java index 670da73b26..580f59ad43 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/MetadataCallRealIntegrationShould.java @@ -30,10 +30,7 @@ import android.util.Log; -import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse; -import org.hisp.dhis.android.core.data.server.RealServerMother; import org.junit.Before; -import org.junit.Test; import java.io.IOException; @@ -73,21 +70,12 @@ make a debugger break point where desired (after sync complete) //This test is uncommented because technically it is flaky. //It depends on a live server to operate and the login is hardcoded here. //Uncomment in order to quickly test changes vs a real server, but keep it uncommented after. - @Test + //@Test public void response_successful_on_sync_meta_data_once() throws Exception { - d2.userModule().logIn(username, password, RealServerMother.android_previous1).blockingGet(); + d2.userModule().logIn(username, password, url).blockingGet(); d2.metadataModule().blockingDownload(); - d2.aggregatedModule().data().blockingDownload(); - - GridAnalyticsResponse response1 = d2.analyticsModule().visualizations() - .withVisualization("AfvoZpi4thl") - .blockingEvaluate(); - - GridAnalyticsResponse response2 = d2.analyticsModule().visualizations() - .withVisualization("TXcKIg4LuA3") - .blockingEvaluate(); - + //TODO: add additional sync + break point. //when debugger stops at the new break point manually change metadata online & resume. diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt index 3ff7a47d90..fd4d702902 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt @@ -42,9 +42,9 @@ class AnalyticsVisualizationRepositoryIntegrationShould : BaseMockIntegrationTes .withVisualization(visualizationUid) .blockingEvaluate() - assertThat(result.dimensions.columns).hasSize(1) - assertThat(result.dimensions.rows).hasSize(1) + assertThat(result.dimensions.columns.size).isEqualTo(1) + assertThat(result.dimensions.rows.size).isEqualTo(1) assertThat(result.metadata).isNotEmpty() - assertThat(result.values).hasSize(3) + assertThat(result.values.size).isEqualTo(3) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt index 688f88f5e1..a79eaa9565 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt @@ -30,7 +30,7 @@ package org.hisp.dhis.android.core.analytics.aggregated data class DimensionalResponse( val metadata: Map, - val dimensions: Set, + val dimensions: List, val filters: List, val values: List ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt index 23cf826fcf..56e5609394 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt @@ -43,7 +43,7 @@ data class GridHeader( data class GridHeaderItem( val id: String, - val width: Int + val weight: Int ) data class GridDimension( diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt index 5ebbe321e5..9085e89e2b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelper.kt @@ -39,13 +39,13 @@ internal class AnalyticsServiceDimensionHelper @Inject constructor( private val analyticsOrganisationUnitHelper: AnalyticsOrganisationUnitHelper ) { - fun getDimensions(params: AnalyticsRepositoryParams): Set { - return params.dimensions.map { it.dimension }.toSet() + fun getDimensions(params: AnalyticsRepositoryParams): List { + return params.dimensions.map { it.dimension }.distinct() } fun getEvaluationItems( params: AnalyticsRepositoryParams, - dimensions: Set + dimensions: List ): List { val absoluteDimensionItemList = dimensions.map { dimension -> params.dimensions diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt index 0c16cb1502..8b31fb5995 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt @@ -146,7 +146,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( values.forEach { val last = groups.lastOrNull() if (last?.id == it) { - groups[groups.lastIndex] = last.copy(width = last.width + 1) + groups[groups.lastIndex] = last.copy(weight = last.weight + 1) } else { groups.add(GridHeaderItem(it, 1)) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt index acf323e973..343ded8b4e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -55,7 +55,7 @@ object DimensionalResponseSamples { orgunit1.uid() to MetadataItem.OrganisationUnitItem(orgunit1), orgunit2.uid() to MetadataItem.OrganisationUnitItem(orgunit2) ), - dimensions = setOf(Dimension.Data, Dimension.Category(cc1.uid()), Dimension.Period), + dimensions = listOf(Dimension.Data, Dimension.Category(cc1.uid()), Dimension.Period), filters = listOf(orgunit1.uid(), orgunit2.uid()), values = listOf( DimensionalValue( diff --git a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt index 5b4db61a75..097c61374b 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsServiceDimensionHelperShould.kt @@ -96,7 +96,7 @@ class AnalyticsServiceDimensionHelperShould { ), filters = listOf() ) - val dimensions = setOf( + val dimensions = listOf( Dimension.Period, Dimension.Data, Dimension.OrganisationUnit, Dimension.Category(s.categoryItem1_1.uid) ) @@ -126,7 +126,7 @@ class AnalyticsServiceDimensionHelperShould { ), filters = listOf() ) - val dimensions = setOf(Dimension.Period, Dimension.Data, Dimension.Category(s.categoryItem1_1.uid)) + val dimensions = listOf(Dimension.Period, Dimension.Data, Dimension.Category(s.categoryItem1_1.uid)) val items = helper.getEvaluationItems(params, dimensions) @@ -154,7 +154,7 @@ class AnalyticsServiceDimensionHelperShould { ), filters = listOf() ) - val dimensions = setOf(Dimension.Data, Dimension.Period, Dimension.OrganisationUnit) + val dimensions = listOf(Dimension.Data, Dimension.Period, Dimension.OrganisationUnit) val items = helper.getEvaluationItems(params, dimensions) @@ -178,7 +178,7 @@ class AnalyticsServiceDimensionHelperShould { ), filters = listOf() ) - val dimensions = setOf(Dimension.Data, Dimension.Period, Dimension.OrganisationUnit) + val dimensions = listOf(Dimension.Data, Dimension.Period, Dimension.OrganisationUnit) val items = helper.getEvaluationItems(params, dimensions) From 837bd5c759d113110dafd972665c7f46ee79f88c Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 23 Jul 2021 10:13:13 +0200 Subject: [PATCH 224/308] [ANDROSDK-1312-2] Tracker importer: manage deleted items --- .../internal/EnrollmentImportHandler.kt | 28 ++++--------------- .../internal/JobReportEnrollmentHandler.kt | 26 ++++++++++++++++- .../internal/JobReportEventHandler.kt | 8 ++++-- .../internal/JobReportTrackedEntityHandler.kt | 2 +- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt index c77f33ebe9..8b94bd0efa 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt @@ -28,14 +28,8 @@ package org.hisp.dhis.android.core.enrollment.internal import dagger.Reusable -import java.util.* -import javax.inject.Inject -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper -import org.hisp.dhis.android.core.common.DataColumns import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.common.internal.DataStatePropagator import org.hisp.dhis.android.core.enrollment.Enrollment @@ -48,16 +42,17 @@ import org.hisp.dhis.android.core.imports.internal.BaseImportSummaryHelper.getRe import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore -import org.hisp.dhis.android.core.note.Note -import org.hisp.dhis.android.core.note.NoteTableInfo +import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEnrollmentHandler +import java.util.* +import javax.inject.Inject @Reusable internal class EnrollmentImportHandler @Inject constructor( private val enrollmentStore: EnrollmentStore, - private val noteStore: IdentifiableObjectStore, private val eventImportHandler: EventImportHandler, private val trackerImportConflictStore: TrackerImportConflictStore, private val trackerImportConflictParser: TrackerImportConflictParser, + private val jobReportEnrollmentHandler: JobReportEnrollmentHandler, private val dataStatePropagator: DataStatePropagator ) { @@ -80,7 +75,7 @@ internal class EnrollmentImportHandler @Inject constructor( } if (handleAction !== HandleAction.Delete) { - handleNoteImportSummary(enrollmentUid, syncState) + jobReportEnrollmentHandler.handleEnrollmentNotes(enrollmentUid, syncState) storeEnrollmentImportConflicts(enrollmentImportSummary, teiUid) handleEventImportSummaries(enrollmentImportSummary, enrollments, teiUid) @@ -116,19 +111,6 @@ internal class EnrollmentImportHandler @Inject constructor( } } - private fun handleNoteImportSummary(enrollmentUid: String, state: State) { - val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST - val whereClause = WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.SYNC_STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError().toList()) - ) - .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build() - val notes = noteStore.selectWhere(whereClause) - for (note in notes) { - noteStore.update(note.toBuilder().syncState(newNoteState).build()) - } - } - private fun storeEnrollmentImportConflicts( enrollmentImportSummary: EnrollmentImportSummary, teiUid: String diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt index ad4ef00fd9..1d2a94479b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt @@ -28,22 +28,46 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper +import org.hisp.dhis.android.core.common.DataColumns import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore +import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.note.NoteTableInfo @Reusable internal class JobReportEnrollmentHandler @Inject internal constructor( + private val noteStore: IdentifiableObjectStore, private val enrollmentStore: EnrollmentStore, private val conflictStore: TrackerImportConflictStore, private val conflictHelper: TrackerConflictHelper ) : JobReportTypeHandler() { + fun handleEnrollmentNotes(enrollmentUid: String, state: State) { + val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST + val whereClause = WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } + ) + .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build() + for (note in noteStore.selectWhere(whereClause)) { + noteStore.update(note.toBuilder().syncState(newNoteState).build()) + } + } + override fun handleObject(uid: String, state: State) { - enrollmentStore.setSyncState(uid, state) conflictStore.deleteEnrollmentConflicts(uid) + val handleAction = enrollmentStore.setSyncStateOrDelete(uid, state) + + if (handleAction !== HandleAction.Delete) { + handleEnrollmentNotes(uid, state) + } } override fun storeConflict(errorReport: JobValidationError) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index 8e1e215c54..fb90ba60f2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -31,6 +31,7 @@ import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.DataColumns import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore @@ -62,9 +63,12 @@ internal class JobReportEventHandler @Inject internal constructor( } override fun handleObject(uid: String, state: State) { - eventStore.setSyncState(uid, state) conflictStore.deleteEventConflicts(uid) - handleEventNotes(uid, state) + val handleAction = eventStore.setSyncStateOrDelete(uid, state) + + if (handleAction !== HandleAction.Delete) { + handleEventNotes(uid, state) + } } override fun storeConflict(errorReport: JobValidationError) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt index b701d317b5..fc984e6ce1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -42,8 +42,8 @@ internal class JobReportTrackedEntityHandler @Inject internal constructor( ) : JobReportTypeHandler() { override fun handleObject(uid: String, state: State) { - trackedEntityStore.setSyncState(uid, state) conflictStore.deleteTrackedEntityConflicts(uid) + trackedEntityStore.setSyncStateOrDelete(uid, state) } override fun storeConflict(errorReport: JobValidationError) { From c1571cb2470321ab5292f5e35325227ce17bb4d4 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 23 Jul 2021 10:23:13 +0200 Subject: [PATCH 225/308] [ANDROSDK-1312-2] Adapt unit tests --- .../enrollment/internal/EnrollmentImportHandler.kt | 4 ++-- .../importer/internal/JobReportEnrollmentHandler.kt | 3 +-- .../internal/EnrollmentImportHandlerShould.java | 12 +++++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt index 8b94bd0efa..85f025b8f1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.enrollment.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State @@ -43,8 +45,6 @@ import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEnrollmentHandler -import java.util.* -import javax.inject.Inject @Reusable internal class EnrollmentImportHandler @Inject constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt index 1d2a94479b..9102a6f84f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt @@ -28,12 +28,11 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper import org.hisp.dhis.android.core.common.DataColumns -import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore diff --git a/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java index c846f3e79f..00cc31b67d 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandlerShould.java @@ -40,6 +40,7 @@ import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.note.Note; +import org.hisp.dhis.android.core.tracker.importer.internal.JobReportEnrollmentHandler; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -66,9 +67,6 @@ public class EnrollmentImportHandlerShould { @Mock private EnrollmentStore enrollmentStore; - @Mock - private IdentifiableObjectStore noteStore; - @Mock private EventImportHandler eventImportHandler; @@ -87,6 +85,9 @@ public class EnrollmentImportHandlerShould { @Mock private TrackerImportConflictParser trackerImportConflictParser; + @Mock + private JobReportEnrollmentHandler jobReportEnrollmentHandler; + @Mock private DataStatePropagator dataStatePropagator; @@ -102,8 +103,9 @@ public class EnrollmentImportHandlerShould { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - enrollmentImportHandler = new EnrollmentImportHandler(enrollmentStore, noteStore, - eventImportHandler, trackerImportConflictStore, trackerImportConflictParser, dataStatePropagator); + enrollmentImportHandler = new EnrollmentImportHandler(enrollmentStore, eventImportHandler, + trackerImportConflictStore, trackerImportConflictParser, + jobReportEnrollmentHandler, dataStatePropagator); } @Test From 8aff9cc14e9d252af28b1e3559bbc88c047da1db Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 23 Jul 2021 11:43:58 +0200 Subject: [PATCH 226/308] Refresh aggregatedSyncStatus when deleting TEIs --- .../common/internal/DataStatePropagator.kt | 3 + .../internal/DataStatePropagatorImpl.kt | 63 +++++++++---------- ...kedEntityInstanceCollectionRepository.java | 16 ++++- ...TrackedEntityInstanceObjectRepository.java | 14 ++++- 4 files changed, 57 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index 112a9cc290..f964752f1f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -33,10 +33,13 @@ import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance @Suppress("TooManyFunctions") internal interface DataStatePropagator { + fun propagateTrackedEntityInstanceUpdate(tei: TrackedEntityInstance?) + fun propagateEnrollmentUpdate(enrollment: Enrollment?) fun propagateEventUpdate(event: Event?) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index e6701801d8..7315184bbd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -28,8 +28,6 @@ package org.hisp.dhis.android.core.common.internal import dagger.Reusable -import java.util.* -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment @@ -42,7 +40,10 @@ import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore +import java.util.* +import javax.inject.Inject @Reusable @Suppress("TooManyFunctions") @@ -52,25 +53,31 @@ internal class DataStatePropagatorImpl @Inject internal constructor( private val eventStore: EventStore ) : DataStatePropagator { + override fun propagateTrackedEntityInstanceUpdate(tei: TrackedEntityInstance?) { + tei?.let { + refreshTrackedEntityInstanceAggregatedSyncState(it.uid()) + refreshTrackedEntityInstanceLastUpdated(it.uid()) + } + } + override fun propagateEnrollmentUpdate(enrollment: Enrollment?) { enrollment?.let { - refreshTrackedEntityInstanceAggregatedSyncState(it.trackedEntityInstance()!!) - refreshTrackedEntityInstanceLastUpdated(it.trackedEntityInstance()!!) + refreshEnrollmentAggregatedSyncState(it.uid()) + refreshEnrollmentLastUpdated(it.uid()) + val tei = trackedEntityInstanceStore.selectByUid(it.trackedEntityInstance()!!) + propagateTrackedEntityInstanceUpdate(tei) } } override fun propagateEventUpdate(event: Event?) { event?.enrollment()?.let { enrollmentUid -> - refreshEnrollmentAggregatedSyncState(enrollmentUid) - refreshEnrollmentLastUpdated(enrollmentUid) val enrollment = enrollmentStore.selectByUid(enrollmentUid) propagateEnrollmentUpdate(enrollment) } } override fun propagateTrackedEntityDataValueUpdate(dataValue: TrackedEntityDataValue?) { - val event = setEventSyncState(dataValue!!.event(), getStateForUpdate) - propagateEventUpdate(event) + setEventSyncState(dataValue!!.event(), getStateForUpdate) } override fun propagateTrackedEntityAttributeUpdate(trackedEntityAttributeValue: TrackedEntityAttributeValue?) { @@ -80,11 +87,8 @@ internal class DataStatePropagatorImpl @Inject internal constructor( override fun propagateNoteCreation(note: Note?) { if (note!!.noteType() == Note.NoteType.ENROLLMENT_NOTE) { setEnrollmentSyncState(note.enrollment()!!, getStateForUpdate) - val enrollment = enrollmentStore.selectByUid(note.enrollment()!!) - propagateEnrollmentUpdate(enrollment) } else if (note.noteType() == Note.NoteType.EVENT_NOTE) { - val event = setEventSyncState(note.event(), getStateForUpdate) - propagateEventUpdate(event) + setEventSyncState(note.event(), getStateForUpdate) } } @@ -94,36 +98,28 @@ internal class DataStatePropagatorImpl @Inject internal constructor( setTeiSyncState(item.trackedEntityInstance()!!.trackedEntityInstance(), getStateForUpdate) } else if (item.hasEnrollment()) { setEnrollmentSyncState(item.enrollment()!!.enrollment(), getStateForUpdate) - val enrollment = enrollmentStore.selectByUid(item.enrollment()!!.enrollment()) - propagateEnrollmentUpdate(enrollment) } else if (item.hasEvent()) { - val event = setEventSyncState(item.event()!!.event(), getStateForUpdate) - propagateEventUpdate(event) + setEventSyncState(item.event()!!.event(), getStateForUpdate) } } } private fun setTeiSyncState(trackedEntityInstanceUid: String?, getState: (State?) -> State) { - val instance = trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid!!) - if (instance != null) { + trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid!!)?.let { instance -> trackedEntityInstanceStore.setSyncState(trackedEntityInstanceUid, getState(instance.syncState())) - refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid) - refreshTrackedEntityInstanceLastUpdated(trackedEntityInstanceUid) + propagateTrackedEntityInstanceUpdate(instance) } } private fun setEnrollmentSyncState(enrollmentUid: String, getState: (State?) -> State) { - val enrollment = enrollmentStore.selectByUid(enrollmentUid) - if (enrollment != null) { - enrollmentStore.setSyncState(enrollmentUid, getState(enrollment.aggregatedSyncState())) - refreshEnrollmentAggregatedSyncState(enrollmentUid) - refreshEnrollmentLastUpdated(enrollmentUid) + enrollmentStore.selectByUid(enrollmentUid)?.let { enrollment -> + enrollmentStore.setSyncState(enrollmentUid, getState(enrollment.syncState())) + propagateEnrollmentUpdate(enrollment) } } - private fun setEventSyncState(eventUid: String?, getState: (State?) -> State): Event? { - var event = eventStore.selectByUid(eventUid!!) - if (event != null) { + private fun setEventSyncState(eventUid: String?, getState: (State?) -> State) { + eventStore.selectByUid(eventUid!!)?.let { event -> val now = Date() val updatedEvent = event.toBuilder() .syncState(getState(event.syncState())) @@ -131,9 +127,8 @@ internal class DataStatePropagatorImpl @Inject internal constructor( .lastUpdatedAtClient(getMaxDate(event.lastUpdatedAtClient(), now)) .build() eventStore.update(updatedEvent) - event = updatedEvent + propagateEventUpdate(updatedEvent) } - return event } private fun refreshEnrollmentLastUpdated(enrollmentUid: String) { @@ -255,10 +250,10 @@ internal class DataStatePropagatorImpl @Inject internal constructor( states.contains(State.ERROR) -> State.ERROR states.contains(State.WARNING) -> State.WARNING states.contains(State.UPLOADING) || - states.contains(State.SENT_VIA_SMS) || - states.contains(State.SYNCED_VIA_SMS) || - states.contains(State.TO_POST) || - states.contains(State.TO_UPDATE) -> State.TO_UPDATE + states.contains(State.SENT_VIA_SMS) || + states.contains(State.SYNCED_VIA_SMS) || + states.contains(State.TO_POST) || + states.contains(State.TO_UPDATE) -> State.TO_UPDATE else -> State.SYNCED } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java index 35485b51e7..b10246f37a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceCollectionRepository.java @@ -42,6 +42,7 @@ import org.hisp.dhis.android.core.arch.repositories.scope.internal.RepositoryScopeHelper; import org.hisp.dhis.android.core.common.FeatureType; import org.hisp.dhis.android.core.common.State; +import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo.Columns; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceFields; @@ -66,6 +67,7 @@ public final class TrackedEntityInstanceCollectionRepository private final TrackedEntityInstancePostParentCall postCall; private final TrackedEntityInstanceStore store; + private final DataStatePropagator dataStatePropagator; private final JobQueryCall jobQueryCall; @Inject @@ -74,16 +76,23 @@ public final class TrackedEntityInstanceCollectionRepository final Map> childrenAppenders, final RepositoryScope scope, final Transformer transformer, + final DataStatePropagator dataStatePropagator, final TrackedEntityInstancePostParentCall postCall, final JobQueryCall jobQueryCall) { super(store, childrenAppenders, scope, transformer, new FilterConnectorFactory<>(scope, s -> - new TrackedEntityInstanceCollectionRepository(store, childrenAppenders, s, transformer, postCall, - jobQueryCall))); + new TrackedEntityInstanceCollectionRepository(store, childrenAppenders, s, transformer, + dataStatePropagator, postCall, jobQueryCall))); this.postCall = postCall; this.store = store; + this.dataStatePropagator = dataStatePropagator; this.jobQueryCall = jobQueryCall; } + @Override + protected void propagateState(TrackedEntityInstance trackedEntityInstance) { + dataStatePropagator.propagateTrackedEntityInstanceUpdate(trackedEntityInstance); + } + @Override public Observable upload() { return Observable.concat( @@ -102,7 +111,8 @@ public void blockingUpload() { @Override public TrackedEntityInstanceObjectRepository uid(String uid) { RepositoryScope updatedScope = RepositoryScopeHelper.withUidFilterItem(scope, uid); - return new TrackedEntityInstanceObjectRepository(store, uid, childrenAppenders, updatedScope); + return new TrackedEntityInstanceObjectRepository(store, uid, childrenAppenders, updatedScope, + dataStatePropagator); } public StringFilterConnector byUid() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java index 167677072a..e8365cfbcd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstanceObjectRepository.java @@ -35,6 +35,7 @@ import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.Unit; +import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.maintenance.D2Error; import org.hisp.dhis.android.core.maintenance.D2ErrorCode; import org.hisp.dhis.android.core.maintenance.D2ErrorComponent; @@ -46,12 +47,16 @@ public final class TrackedEntityInstanceObjectRepository extends ReadWriteWithUidDataObjectRepositoryImpl { + private final DataStatePropagator dataStatePropagator; + TrackedEntityInstanceObjectRepository(final TrackedEntityInstanceStore store, final String uid, final Map> childrenAppenders, - final RepositoryScope scope) { + final RepositoryScope scope, + final DataStatePropagator dataStatePropagator) { super(store, childrenAppenders, scope, - s -> new TrackedEntityInstanceObjectRepository(store, uid, childrenAppenders, s)); + s -> new TrackedEntityInstanceObjectRepository(store, uid, childrenAppenders, s, dataStatePropagator)); + this.dataStatePropagator = dataStatePropagator; } public Unit setOrganisationUnitUid(String organisationUnitUid) throws D2Error { @@ -83,4 +88,9 @@ private TrackedEntityInstance.Builder updateBuilder() throws D2Error { .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } + + @Override + protected void propagateState(TrackedEntityInstance trackedEntityInstance) { + dataStatePropagator.propagateTrackedEntityInstanceUpdate(trackedEntityInstance); + } } \ No newline at end of file From 13bc22229e9aa1a8644295fa63b4314a16b5c756 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 23 Jul 2021 13:08:45 +0200 Subject: [PATCH 227/308] [ANDROSDK-1312-2] Checkstyle --- .../core/common/internal/DataStatePropagatorImpl.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 7315184bbd..8c18cb8e39 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.common.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment @@ -42,8 +44,6 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore -import java.util.* -import javax.inject.Inject @Reusable @Suppress("TooManyFunctions") @@ -250,10 +250,10 @@ internal class DataStatePropagatorImpl @Inject internal constructor( states.contains(State.ERROR) -> State.ERROR states.contains(State.WARNING) -> State.WARNING states.contains(State.UPLOADING) || - states.contains(State.SENT_VIA_SMS) || - states.contains(State.SYNCED_VIA_SMS) || - states.contains(State.TO_POST) || - states.contains(State.TO_UPDATE) -> State.TO_UPDATE + states.contains(State.SENT_VIA_SMS) || + states.contains(State.SYNCED_VIA_SMS) || + states.contains(State.TO_POST) || + states.contains(State.TO_UPDATE) -> State.TO_UPDATE else -> State.SYNCED } } From 7cb4c6c5024f16aab5d54b44b5de08152742c47f Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 27 Jul 2021 09:03:36 +0200 Subject: [PATCH 228/308] [ANDROSDK-1344] Add NewTrackerImporterRelationship model --- ...rackerImporterRelationshipItemAdapter.java | 35 +++++ .../NewTrackerImporterRelationship.java | 122 ++++++++++++++++++ .../NewTrackerImporterRelationshipItem.java | 98 ++++++++++++++ ...wTrackerImporterRelationshipTransformer.kt | 62 +++++++++ 4 files changed, 317 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreNewTrackerImporterRelationshipItemAdapter.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationship.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipItem.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipTransformer.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreNewTrackerImporterRelationshipItemAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreNewTrackerImporterRelationshipItemAdapter.java new file mode 100644 index 0000000000..4559d186fb --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/ignore/internal/IgnoreNewTrackerImporterRelationshipItemAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.ignore.internal; + +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationshipItem; + +public final class IgnoreNewTrackerImporterRelationshipItemAdapter + extends IgnoreColumnAdapter { +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationship.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationship.java new file mode 100644 index 0000000000..be6137df6c --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationship.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; +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.ignore.internal.IgnoreNewTrackerImporterRelationshipItemAdapter; +import org.hisp.dhis.android.core.common.BaseDeletableDataObject; +import org.hisp.dhis.android.core.common.ObjectWithUidInterface; + +import java.util.Date; + +@AutoValue +@JsonDeserialize(builder = AutoValue_NewTrackerImporterRelationship.Builder.class) +public abstract class NewTrackerImporterRelationship extends BaseDeletableDataObject implements ObjectWithUidInterface { + + @Override + @JsonProperty("relationship") + public abstract String uid(); + + @Nullable + @JsonProperty() + public abstract String relationshipType(); + + @Nullable + @JsonProperty() + public abstract String relationshipName(); + + @Nullable + @JsonProperty() + @ColumnAdapter(DbDateColumnAdapter.class) + public abstract Date createdAt(); + + @Nullable + @JsonProperty() + @ColumnAdapter(DbDateColumnAdapter.class) + public abstract Date updatedAt(); + + @Nullable + @JsonProperty() + public abstract Boolean bidirectional(); + + @Nullable + @JsonProperty() + @ColumnAdapter(IgnoreNewTrackerImporterRelationshipItemAdapter.class) + public abstract NewTrackerImporterRelationshipItem from(); + + @Nullable + @JsonProperty() + @ColumnAdapter(IgnoreNewTrackerImporterRelationshipItemAdapter.class) + public abstract NewTrackerImporterRelationshipItem to(); + + public static Builder builder() { + return new $$AutoValue_NewTrackerImporterRelationship.Builder(); + } + + public static NewTrackerImporterRelationship create(Cursor cursor) { + return $AutoValue_NewTrackerImporterRelationship.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public abstract static class Builder extends BaseDeletableDataObject.Builder { + public abstract Builder id(Long id); + + @JsonProperty("relationship") + public abstract Builder uid(String uid); + + public abstract Builder relationshipType(String relationshipType); + + public abstract Builder relationshipName(String relationshipName); + + public abstract Builder createdAt(Date createdAt); + + public abstract Builder updatedAt(Date lastUpdatedAt); + + public abstract Builder bidirectional(Boolean bidirectional); + + public abstract Builder from(NewTrackerImporterRelationshipItem from); + + public abstract Builder to(NewTrackerImporterRelationshipItem to); + + public abstract NewTrackerImporterRelationship build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipItem.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipItem.java new file mode 100644 index 0000000000..4151ea1200 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipItem.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.gabrielittner.auto.value.cursor.ColumnAdapter; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.RelationshipConstraintTypeColumnAdapter; +import org.hisp.dhis.android.core.common.CoreObject; + +@AutoValue +@JsonDeserialize(builder = AutoValue_NewTrackerImporterRelationshipItem.Builder.class) +public abstract class NewTrackerImporterRelationshipItem implements CoreObject { + + @Nullable + @JsonIgnore() + public abstract String relationship(); + + @Nullable + @JsonIgnore() + @ColumnAdapter(RelationshipConstraintTypeColumnAdapter.class) + public abstract RelationshipConstraintType relationshipItemType(); + + @Nullable + @JsonProperty() + public abstract String trackedEntity(); + + @Nullable + @JsonProperty() + public abstract String enrollment(); + + @Nullable + @JsonProperty() + public abstract String event(); + + public static Builder builder() { + return new $$AutoValue_NewTrackerImporterRelationshipItem.Builder(); + } + + public static NewTrackerImporterRelationshipItem create(Cursor cursor) { + return $AutoValue_NewTrackerImporterRelationshipItem.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public abstract static class Builder { + + public abstract Builder id(Long id); + + public abstract Builder relationship(String relationship); + + public abstract Builder relationshipItemType(RelationshipConstraintType relationshipItemType); + + public abstract Builder trackedEntity(String relationship); + + public abstract Builder enrollment(String relationship); + + public abstract Builder event(String relationship); + + public abstract NewTrackerImporterRelationshipItem build(); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipTransformer.kt new file mode 100644 index 0000000000..b263e396f2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/NewTrackerImporterRelationshipTransformer.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship + +import org.hisp.dhis.android.core.arch.handlers.internal.Transformer + +internal class NewTrackerImporterRelationshipTransformer : Transformer { + override fun transform(o: Relationship): NewTrackerImporterRelationship { + return NewTrackerImporterRelationship.builder() + .id(o.id()) + .uid(o.uid()) + .relationshipType(o.relationshipType()) + .relationshipName(o.name()) + .createdAt(o.created()) + .updatedAt(o.lastUpdated()) + .from(getRelationshipItem(o.from())) + .to(getRelationshipItem(o.to())) + .deleted(o.deleted()) + .syncState(o.syncState()) + .build() + } + + private fun getRelationshipItem(item: RelationshipItem?): NewTrackerImporterRelationshipItem? { + return item?.let { + val builder = NewTrackerImporterRelationshipItem.builder() + .relationship(item.relationship()?.uid()) + .relationshipItemType(item.relationshipItemType()) + + when { + item.hasTrackedEntityInstance() -> builder.trackedEntity(item.elementUid()).build() + item.hasEnrollment() -> builder.enrollment(item.elementUid()).build() + item.hasEvent() -> builder.event(item.elementUid()).build() + else -> null + } + } + } +} From c1a779b98bde0af81fb49cef0199f66c888d23f9 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 27 Jul 2021 10:59:18 +0200 Subject: [PATCH 229/308] [ANDROSDK-1344] Implement Relationship handling; create enum for TrackerImportObjectType --- .../TrackerImporterObjectTypeColumnAdapter.kt | 36 ++++++++++++++ .../internal/EventTrackerImporterPostCall.kt | 2 +- .../internal/NewTrackerImporterPayload.kt | 4 +- ...porterTrackedEntityPostPayloadGenerator.kt | 22 ++++++++- ...erTrackedEntityPostPayloadGeneratorTask.kt | 34 ++++++++++++-- ...erImporterTrackedEntityPostStateManager.kt | 9 +++- .../tracker/importer/internal/JobReport.kt | 4 +- .../importer/internal/JobReportHandler.kt | 46 ++++++++++-------- .../internal/JobReportRelationshipHandler.kt | 47 +++++++++++++++++++ ...edEntityInstanceTrackerImporterPostCall.kt | 21 ++++----- ...tTypes.kt => TrackerImporterObjectType.kt} | 10 ++-- .../importer/internal/TrackerJobObject.java | 8 ++-- .../internal/TrackerJobObjectSamples.java | 2 +- ...kedEntityPostPayloadGeneratorTaskShould.kt | 45 ++++++++++++++++-- .../tracker/importer/JobReportErrorShould.kt | 3 +- .../importer/JobReportSuccessShould.kt | 7 +-- 16 files changed, 239 insertions(+), 61 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/TrackerImporterObjectTypeColumnAdapter.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt rename core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/{TrackerImporterObjectTypes.kt => TrackerImporterObjectType.kt} (88%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/TrackerImporterObjectTypeColumnAdapter.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/TrackerImporterObjectTypeColumnAdapter.kt new file mode 100644 index 0000000000..dcb71df9cd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/adapters/enums/internal/TrackerImporterObjectTypeColumnAdapter.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.db.adapters.enums.internal + +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType + +internal class TrackerImporterObjectTypeColumnAdapter : EnumColumnAdapter() { + override fun getEnumClass(): Class { + return TrackerImporterObjectType::class.java + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt index 29d4108458..e19ee5ee0b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventTrackerImporterPostCall.kt @@ -42,7 +42,7 @@ import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterPayload import org.hisp.dhis.android.core.tracker.importer.internal.* import org.hisp.dhis.android.core.tracker.importer.internal.JobQueryCall -import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterService @Reusable diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt index a78d8e2628..01fb74cb3a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt @@ -29,12 +29,14 @@ package org.hisp.dhis.android.core.trackedentity.internal import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.event.NewTrackerImporterEvent +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationship import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntity internal data class NewTrackerImporterPayload( val trackedEntities: MutableList = mutableListOf(), val enrollments: MutableList = mutableListOf(), - val events: MutableList = mutableListOf() + val events: MutableList = mutableListOf(), + val relationships: MutableList = mutableListOf() ) { fun isEmpty(): Boolean { return trackedEntities.isEmpty() && enrollments.isEmpty() && events.isEmpty() diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index e1745f7076..0925ceff64 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Transformer @@ -41,9 +40,13 @@ import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.note.NewTrackerImporterNote import org.hisp.dhis.android.core.note.NewTrackerImporterNoteTransformer import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationship +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationshipTransformer +import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityAttributeValueTransformer import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityDataValueTransformer import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject internal constructor( @@ -51,7 +54,8 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter private val eventStore: EventStore, private val trackedEntityDataValueStore: TrackedEntityDataValueStore, private val trackedEntityAttributeValueStore: TrackedEntityAttributeValueStore, - private val noteStore: IdentifiableObjectStore + private val noteStore: IdentifiableObjectStore, + private val relationshipRepository: RelationshipCollectionRepository ) { fun getTrackedEntities( @@ -74,6 +78,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter NewTrackerImporterTrackedEntityAttributeValueTransformer() ) val notes = getNotes() + val relationships = getRelationships() return NewTrackerImporterTrackedEntityPostPayloadGeneratorTask( filteredTrackedEntityInstances, @@ -81,6 +86,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter eventMap, enrollmentMap, attributeValueMap, + relationships, notes ).generate() } @@ -95,6 +101,18 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter return noteStore.selectWhere(whereNotesClause).map { notesTransformer.transform(it) } } + private fun getRelationships(): Map> { + val relationships = relationshipRepository.bySyncState() + .`in`(State.uploadableStatesIncludingError().toList()) + .withItems() + .blockingGet() + + val relationshipsTransformer = NewTrackerImporterRelationshipTransformer() + return relationships + .filter { it.from()?.elementUid() != null } + .groupBy( { it.from()?.elementUid()!! }, { relationshipsTransformer.transform(it) }) + } + private fun transformMap( map: Map>, transformer: Transformer diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt index 484a2a2800..abc9e1fb27 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt @@ -28,12 +28,13 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.note.NewTrackerImporterNote +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationship import org.hisp.dhis.android.core.trackedentity.* +import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject internal constructor( @@ -42,6 +43,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i private val eventMap: Map>, private val enrollmentMap: Map>, private val attributeValueMap: Map>, + private val relationshipMap: Map>, private val notes: List ) { @@ -63,6 +65,8 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i wrapper.updated.trackedEntities.add(entity) } + addRelationshipsToWrapper(wrapper, relationshipMap[entity.uid()]) + val partitionedEnrollments = getEnrollments(entity.uid()) .partition { it.deleted()!! } @@ -75,12 +79,21 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i wrapper.updated.enrollments.add(enrollment) } + addRelationshipsToWrapper(wrapper, relationshipMap[enrollment.uid()]) + val partitionedEvents = getEvents(enrollment.uid()) .filter { it.syncState() != State.SYNCED } .partition { it.deleted()!! } - wrapper.deleted.events.addAll(partitionedEvents.first) - wrapper.updated.events.addAll(partitionedEvents.second) + partitionedEvents.first.forEach { + wrapper.deleted.events.add(it) + } + + partitionedEvents.second.forEach { event -> + wrapper.updated.events.add(event) + + addRelationshipsToWrapper(wrapper, relationshipMap[event.uid()]) + } } } @@ -137,4 +150,19 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject i eventBuilder.build() } ?: emptyList() } + + private fun addRelationshipsToWrapper( + wrapper: NewTrackerImporterPayloadWrapper, + relationships: List? + ) { + val partitionedRelationships = relationships?.partition { it.deleted()!! } + + partitionedRelationships?.first?.let { deleted -> + wrapper.deleted.relationships.addAll(deleted) + } + + partitionedRelationships?.second?.let { updated -> + wrapper.updated.relationships.addAll(updated) + } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt index 18c2742aed..26b29763b2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt @@ -28,16 +28,18 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable -import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore +import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostStateManager @Inject internal constructor( private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentStore: EnrollmentStore, private val eventStore: EventStore, + private val relationshipStore: RelationshipStore, private val h: StatePersistorHelper ) { @@ -45,22 +47,25 @@ internal class NewTrackerImporterTrackedEntityPostStateManager @Inject internal setStates(payload, null) } - @Suppress("NestedBlockDepth") fun setStates(payload: NewTrackerImporterPayload, forcedState: State?) { val teiMap = mutableMapOf>() val enrollmentMap = mutableMapOf>() val eventMap = mutableMapOf>() + val relationshipMap = mutableMapOf>() val trackedEntities = payload.trackedEntities val enrollments = trackedEntities.flatMap { it.enrollments() ?: emptyList() } + payload.enrollments val events = enrollments.flatMap { it.events() ?: emptyList() } + payload.events + val relationships = payload.relationships trackedEntities.forEach { h.addState(teiMap, it, forcedState) } enrollments.forEach { h.addState(enrollmentMap, it, forcedState) } events.forEach { h.addState(eventMap, it, forcedState) } + relationships.forEach { h.addState(relationshipMap, it, forcedState) } h.persistStates(teiMap, trackedEntityInstanceStore) h.persistStates(enrollmentMap, enrollmentStore) h.persistStates(eventMap, eventStore) + h.persistStates(relationshipMap, relationshipStore) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReport.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReport.kt index 373b20a61b..0a3406395f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReport.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReport.kt @@ -39,7 +39,7 @@ internal data class JobImportCount( internal data class JobValidationError( val uid: String, - val trackerType: String, + val trackerType: TrackerImporterObjectType, val errorCode: String, val message: String ) @@ -51,7 +51,7 @@ internal data class JobValidationReport( internal data class JobObjectReport( val errorReports: List, val index: Int, - val trackerType: String, + val trackerType: TrackerImporterObjectType, val uid: String ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 13e97ac608..c6a8542f5c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -31,15 +31,17 @@ import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.common.internal.DataStatePropagator -import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.ENROLLMENT -import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT -import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.TRACKED_ENTITY +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.ENROLLMENT +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.EVENT +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.RELATIONSHIP +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.TRACKED_ENTITY @Reusable internal class JobReportHandler @Inject internal constructor( private val eventHandler: JobReportEventHandler, private val enrollmentHandler: JobReportEnrollmentHandler, private val trackedEntityHandler: JobReportTrackedEntityHandler, + private val relationshipHandler: JobReportRelationshipHandler, private val dataStatePropagator: DataStatePropagator ) { @@ -53,25 +55,27 @@ internal class JobReportHandler @Inject internal constructor( refreshAggregatedSyncStates(jobObjects) } - private fun handleErrors(o: JobReport, jobObjectsMap: Map, List>) { + private fun handleErrors( + o: JobReport, + jobObjectsMap: Map, List> + ) { o.validationReport.errorReports.forEach { errorReport -> if (jobObjectsMap.containsKey(Pair(errorReport.trackerType, errorReport.uid))) { - when (errorReport.trackerType) { - EVENT -> eventHandler.handleError(errorReport) - ENROLLMENT -> enrollmentHandler.handleError(errorReport) - TRACKED_ENTITY -> trackedEntityHandler.handleError(errorReport) - else -> println("Unsupported type") // TODO - } + getHandler(errorReport.trackerType).handleError(errorReport) } } } - private fun handleSuccesses(o: JobReport, jobObjectsMap: Map, List>) { + private fun handleSuccesses( + o: JobReport, + jobObjectsMap: Map, List> + ) { if (o.bundleReport != null) { val typeMap = o.bundleReport.typeReportMap applySuccess(typeMap.event, jobObjectsMap, eventHandler) applySuccess(typeMap.enrollment, jobObjectsMap, enrollmentHandler) applySuccess(typeMap.trackedEntity, jobObjectsMap, trackedEntityHandler) + applySuccess(typeMap.relationship, jobObjectsMap, relationshipHandler) } } @@ -79,7 +83,7 @@ internal class JobReportHandler @Inject internal constructor( o: JobReport, jobObjectsMap: List ) { - val presentSuccesses = if (o.bundleReport == null) emptySet>() else { + val presentSuccesses = if (o.bundleReport == null) emptySet>() else { val tm = o.bundleReport.typeReportMap setOf(tm.event, tm.trackedEntity, tm.enrollment, tm.relationship).flatMap { it.objectReports @@ -95,18 +99,13 @@ internal class JobReportHandler @Inject internal constructor( val notPresentObjects = expectedObjects - presentSuccesses - presentErrors for (p in notPresentObjects) { - when (p.first) { - EVENT -> eventHandler.handleObject(p.second, State.TO_UPDATE) - ENROLLMENT -> enrollmentHandler.handleObject(p.second, State.TO_UPDATE) - TRACKED_ENTITY -> trackedEntityHandler.handleObject(p.second, State.TO_UPDATE) - else -> println("Unsupported type") // TODO - } + getHandler(p.first).handleObject(p.second, State.TO_UPDATE) } } private fun applySuccess( typeReport: JobTypeReport, - jobObjects: Map, List>, + jobObjects: Map, List>, typeHandler: JobReportTypeHandler ) { typeReport.objectReports @@ -121,4 +120,13 @@ internal class JobReportHandler @Inject internal constructor( jobObjects.filter { it.trackerType() == EVENT }.map { it.objectUid() } ) } + + private fun getHandler(type: TrackerImporterObjectType): JobReportTypeHandler { + return when (type) { + EVENT -> eventHandler + ENROLLMENT -> enrollmentHandler + TRACKED_ENTITY -> trackedEntityHandler + RELATIONSHIP -> relationshipHandler + } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt new file mode 100644 index 0000000000..735c8c6a77 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore +import javax.inject.Inject + +@Reusable +internal class JobReportRelationshipHandler @Inject internal constructor( + private val relationshipStore: RelationshipStore +) : JobReportTypeHandler() { + + override fun handleObject(uid: String, state: State) { + relationshipStore.setSyncStateOrDelete(uid, state) + } + + override fun storeConflict(errorReport: JobValidationError) { + + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 3dac0a0d85..25f505ddf2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -30,18 +30,17 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single -import java.util.* -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.common.ObjectWithUidInterface import org.hisp.dhis.android.core.common.State -import org.hisp.dhis.android.core.relationship.internal.RelationshipDeleteCall import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostPayloadGenerator import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostStateManager +import java.util.* +import javax.inject.Inject @Reusable internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal constructor( @@ -50,8 +49,7 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con private val service: TrackerImporterService, private val apiCallExecutor: APICallExecutor, private val jobQueryCall: JobQueryCall, - private val jobObjectHandler: Handler, - private val relationshipDeleteCall: RelationshipDeleteCall + private val jobObjectHandler: Handler ) { fun uploadTrackedEntityInstances( filteredTrackedEntityInstances: List @@ -59,10 +57,6 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con return Observable.defer { val payloadWrapper = payloadGenerator.getTrackedEntities(filteredTrackedEntityInstances) - // TODO HANDLE DELETIONS - // TODO HANDLE RELATIONSHIPS - // TODO HANDLE DELETED RELATIONSHIPS - // relationshipDeleteCall.postDeletedRelationships(partition) Observable.concat( doPostCall(payloadWrapper.deleted, IMPORT_STRATEGY_DELETE), doPostCall(payloadWrapper.updated, IMPORT_STRATEGY_CREATE_AND_UPDATE) @@ -112,14 +106,15 @@ internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal con val enrollments = payload.trackedEntities.flatMap { it.enrollments() ?: emptyList() } + payload.enrollments val events = enrollments.flatMap { it.events() ?: emptyList() } + payload.events - return generateTypeObjects(builder, TrackerImporterObjectTypes.TRACKED_ENTITY, payload.trackedEntities) + - generateTypeObjects(builder, TrackerImporterObjectTypes.ENROLLMENT, enrollments) + - generateTypeObjects(builder, TrackerImporterObjectTypes.EVENT, events) + return generateTypeObjects(builder, TrackerImporterObjectType.TRACKED_ENTITY, payload.trackedEntities) + + generateTypeObjects(builder, TrackerImporterObjectType.ENROLLMENT, enrollments) + + generateTypeObjects(builder, TrackerImporterObjectType.EVENT, events) + + generateTypeObjects(builder, TrackerImporterObjectType.RELATIONSHIP, payload.relationships) } private fun generateTypeObjects( builder: TrackerJobObject.Builder, - objectType: String, + objectType: TrackerImporterObjectType, objects: List ): List { return objects.map { diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectType.kt similarity index 88% rename from core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt rename to core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectType.kt index 952a119cad..e60663b2cd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectTypes.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerImporterObjectType.kt @@ -27,9 +27,9 @@ */ package org.hisp.dhis.android.core.tracker.importer.internal -internal object TrackerImporterObjectTypes { - const val EVENT = "EVENT" - const val TRACKED_ENTITY = "TRACKED_ENTITY" - const val ENROLLMENT = "ENROLLMENT" - const val RELATIONSHIP = "RELATIONSHIP" +internal enum class TrackerImporterObjectType { + EVENT, + TRACKED_ENTITY, + ENROLLMENT, + RELATIONSHIP } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java index 66dd59b4ab..b2f3f8ab2c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackerJobObject.java @@ -38,6 +38,7 @@ 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.enums.internal.TrackerImporterObjectTypeColumnAdapter; import org.hisp.dhis.android.core.common.BaseObject; import java.util.Date; @@ -47,7 +48,8 @@ public abstract class TrackerJobObject extends BaseObject { @NonNull - public abstract String trackerType(); + @ColumnAdapter(TrackerImporterObjectTypeColumnAdapter.class) + public abstract TrackerImporterObjectType trackerType(); @NonNull public abstract String objectUid(); @@ -67,7 +69,7 @@ public static TrackerJobObject create(Cursor cursor) { public static Builder builder() { - return new AutoValue_TrackerJobObject.Builder(); + return new $$AutoValue_TrackerJobObject.Builder(); } abstract Builder toBuilder(); @@ -75,7 +77,7 @@ public static Builder builder() { @AutoValue.Builder @JsonPOJOBuilder(withPrefix = "") public abstract static class Builder extends BaseObject.Builder { - public abstract Builder trackerType(String trackerType); + public abstract Builder trackerType(TrackerImporterObjectType trackerType); public abstract Builder objectUid(String objectUid); diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java index c8d5417b9a..8f2f88f40f 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/tracker/importer/internal/TrackerJobObjectSamples.java @@ -31,7 +31,7 @@ import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject; import static org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils.parseDate; -import static org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectTypes.EVENT; +import static org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.EVENT; public class TrackerJobObjectSamples { diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt index 32e84667f3..c9ff20fda0 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt @@ -33,6 +33,8 @@ import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.event.NewTrackerImporterEvent +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationship +import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationshipItem import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.junit.Test import org.junit.runner.RunWith @@ -52,7 +54,8 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { val wrapper = getTaskFor( listOf(syncedTei), mapOf(updatedEnrollment.uid()!! to listOf(updatedEvent)), - mapOf(syncedTei.uid()!! to listOf(updatedEnrollment)) + mapOf(syncedTei.uid()!! to listOf(updatedEnrollment)), + emptyMap() ).generate() assertThat(wrapper.deleted.isEmpty()).isTrue() @@ -71,7 +74,8 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { val wrapper = getTaskFor( listOf(syncedTei), mapOf(syncedEnrollment.uid()!! to listOf(deletedEvent)), - mapOf(syncedTei.uid()!! to listOf(syncedEnrollment)) + mapOf(syncedTei.uid()!! to listOf(syncedEnrollment)), + emptyMap() ).generate() assertThat(wrapper.deleted.trackedEntities).isEmpty() @@ -81,6 +85,28 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { assertThat(wrapper.updated.isEmpty()).isTrue() } + @Test + fun should_generate_granular_payload_for_relationships() { + val syncedTei = generateTEI() + val relationship = generateRelationship( + NewTrackerImporterRelationshipItem.builder().trackedEntity(syncedTei.uid()).build() + ) + + val wrapper = getTaskFor( + listOf(syncedTei), + emptyMap(), + emptyMap(), + mapOf(syncedTei.uid() to listOf(relationship)) + ).generate() + + assertThat(wrapper.deleted.isEmpty()).isTrue() + + assertThat(wrapper.updated.trackedEntities).isEmpty() + assertThat(wrapper.updated.enrollments).isEmpty() + assertThat(wrapper.updated.events).isEmpty() + assertThat(wrapper.updated.relationships).hasSize(1) + } + private fun generateTEI( synState: State = State.SYNCED, deleted: Boolean = false @@ -119,10 +145,22 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { .build() } + private fun generateRelationship( + from: NewTrackerImporterRelationshipItem + ): NewTrackerImporterRelationship { + return NewTrackerImporterRelationship.builder() + .uid(uidGenerator.generate()) + .from(from) + .syncState(State.TO_UPDATE) + .deleted(false) + .build() + } + private fun getTaskFor( trackedEntities: List, eventMap: Map>, - enrollmentMap: Map> + enrollmentMap: Map>, + relationshipMap: Map> ): NewTrackerImporterTrackedEntityPostPayloadGeneratorTask { return NewTrackerImporterTrackedEntityPostPayloadGeneratorTask( trackedEntities, @@ -130,6 +168,7 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { eventMap, enrollmentMap, mapOf(), + relationshipMap, listOf() ) } diff --git a/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportErrorShould.kt b/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportErrorShould.kt index 3ad66fa510..02fa4516f7 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportErrorShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportErrorShould.kt @@ -36,6 +36,7 @@ import org.hisp.dhis.android.core.common.ObjectShould import org.hisp.dhis.android.core.tracker.importer.internal.JobImportCount import org.hisp.dhis.android.core.tracker.importer.internal.JobReport import org.hisp.dhis.android.core.tracker.importer.internal.JobValidationError +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType import org.junit.Test class JobReportErrorShould : BaseObjectShould("tracker/importer/jobreport-error.json"), ObjectShould { @@ -55,7 +56,7 @@ class JobReportErrorShould : BaseObjectShould("tracker/importer/jobreport-error. assertThat(error).isEqualTo( JobValidationError( "PXi7gfVIk1p", - "EVENT", + TrackerImporterObjectType.EVENT, "E1033", "Event: `PXi7gfVIk1p`, Enrollment value is NULL." ) diff --git a/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportSuccessShould.kt b/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportSuccessShould.kt index 026801bc95..4df5bea9a4 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportSuccessShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/tracker/importer/JobReportSuccessShould.kt @@ -33,10 +33,7 @@ import java.text.ParseException import org.hisp.dhis.android.core.Inject import org.hisp.dhis.android.core.common.BaseObjectShould import org.hisp.dhis.android.core.common.ObjectShould -import org.hisp.dhis.android.core.tracker.importer.internal.JobImportCount -import org.hisp.dhis.android.core.tracker.importer.internal.JobObjectReport -import org.hisp.dhis.android.core.tracker.importer.internal.JobReport -import org.hisp.dhis.android.core.tracker.importer.internal.JobTypeReport +import org.hisp.dhis.android.core.tracker.importer.internal.* import org.junit.Test class JobReportSuccessShould : BaseObjectShould("tracker/importer/jobreport-success.json"), ObjectShould { @@ -68,7 +65,7 @@ class JobReportSuccessShould : BaseObjectShould("tracker/importer/jobreport-succ JobTypeReport( "EVENT", JobImportCount(2, 2, 2, 2, 8), - listOf(JobObjectReport(emptyList(), 0, "EVENT", "UavzrupW3lZ")) + listOf(JobObjectReport(emptyList(), 0, TrackerImporterObjectType.EVENT, "UavzrupW3lZ")) ) ) assertThat(bundleReport.typeReportMap.relationship).isEqualTo( From 5c8a0da138c625576dad90a55816d455b2104eab Mon Sep 17 00:00:00 2001 From: Pablo Date: Tue, 27 Jul 2021 13:07:54 +0200 Subject: [PATCH 230/308] feat: [ANDROAPP-2275] Display and create event to tei relationships --- .../RelationshipCollectionRepository.java | 2 +- .../core/relationship/RelationshipHelper.java | 9 +++++ .../RelationshipTypeCollectionRepository.java | 34 +++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 61200edb63..16f27417ad 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -115,7 +115,7 @@ public String blockingAdd(Relationship relationship) throws D2Error { .errorCode(D2ErrorCode.CANT_CREATE_EXISTING_OBJECT) .errorDescription("Tried to create already existing Relationship: " + relationship) .build(); - } else if (from == null || !from.hasTrackedEntityInstance() || to == null || !to.hasTrackedEntityInstance()) { + } else if (from == null || to == null || !to.hasTrackedEntityInstance()) { throw D2Error .builder() .errorComponent(D2ErrorComponent.SDK) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java index b8b286bdb8..38de86a49e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java @@ -77,6 +77,15 @@ public static Relationship teiToTeiRelationship(String fromUid, String toUid, St .build(); } + public static Relationship eventToTeiRelationship(String fromEventUid, String toTeiUid, String relationshipTypeUid){ + return Relationship.builder() + .uid(new UidGeneratorImpl().generate()) + .from(RelationshipHelper.eventItem(fromEventUid)) + .to(RelationshipHelper.teiItem(toTeiUid)) + .relationshipType(relationshipTypeUid) + .build(); + } + public static boolean areItemsEqual(RelationshipItem a, RelationshipItem b) { return equalsConsideringNull(a.event(), b.event()) && equalsConsideringNull(a.enrollment(), b.enrollment()) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java index 2267d1ee38..40e058a26d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java @@ -36,6 +36,10 @@ import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; import org.hisp.dhis.android.core.common.IdentifiableColumns; +import org.hisp.dhis.android.core.event.Event; +import org.hisp.dhis.android.core.event.EventCollectionRepository; +import org.hisp.dhis.android.core.program.ProgramStage; +import org.hisp.dhis.android.core.program.ProgramStageCollectionRepository; import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields; import java.util.Map; @@ -48,12 +52,15 @@ public final class RelationshipTypeCollectionRepository extends ReadOnlyIdentifiableCollectionRepositoryImpl { + private EventCollectionRepository eventCollectionRepository; @Inject RelationshipTypeCollectionRepository(final IdentifiableObjectStore store, + final EventCollectionRepository eventCollectionRepository, final Map> childrenAppenders, final RepositoryScope scope) { super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, - s -> new RelationshipTypeCollectionRepository(store, childrenAppenders, s))); + s -> new RelationshipTypeCollectionRepository(store,eventCollectionRepository, childrenAppenders, s))); + this.eventCollectionRepository = eventCollectionRepository; } public RelationshipTypeCollectionRepository byConstraint(@NonNull RelationshipEntityType relationshipEntityType, @@ -75,6 +82,19 @@ public RelationshipTypeCollectionRepository byConstraint( RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, relationshipConstraintType)); } + public RelationshipTypeCollectionRepository byConstraint( + @NonNull String eventUid + ) { + Event event = eventCollectionRepository.uid(eventUid).blockingGet(); + String programStageUid = event.programStage(); + String programUid = event.program(); + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + constraintClauseBuilder(programUid, programStageUid) + ); + } + public RelationshipTypeCollectionRepository withConstraints() { return cf.withChild(RelationshipTypeFields.CONSTRAINTS); } @@ -86,7 +106,17 @@ private WhereClauseBuilder constraintClauseBuilder(RelationshipEntityType relati RelationshipConstraintTableInfo.Columns.RELATIONSHIP_ENTITY, relationshipEntityType) .appendKeyStringValue(getRelationshipEntityColumn(relationshipEntityType), relationshipEntityUid); } - + + private WhereClauseBuilder constraintClauseBuilder(String programUid, String programStageUid) { + return new WhereClauseBuilder() + .appendComplexQuery( + new WhereClauseBuilder() + .appendOrKeyStringValue(RelationshipConstraintTableInfo.Columns.PROGRAM, programUid) + .appendOrKeyStringValue(RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE, programStageUid) + .build() + ); + } + private String getRelationshipEntityColumn(@NonNull RelationshipEntityType relationshipEntityType) { switch (relationshipEntityType) { case TRACKED_ENTITY_INSTANCE: From b4225bec4dde3b6e585916b390c6e177d18c987d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 27 Jul 2021 13:36:29 +0200 Subject: [PATCH 231/308] [ANDROSDK-1344] Add AggregatedSyncState in Events --- .../DataStatePropagatorIntegrationShould.kt | 8 +- .../EventEndpointCallMockIntegrationShould.kt | 4 +- ...PayloadGeneratorMockIntegrationShould.java | 8 + .../internal/EventStoreIntegrationShould.java | 2 + ...stPayloadGeneratorMockIntegrationShould.kt | 4 + core/src/main/assets/migrations/104.sql | 4 +- core/src/main/assets/snapshots/106.sql | 2 +- .../common/internal/DataStatePropagator.kt | 2 + .../internal/DataStatePropagatorImpl.kt | 82 +++++-- .../internal/EnrollmentHandler.java | 1 + .../hisp/dhis/android/core/event/Event.java | 30 +++ .../core/event/EventCollectionRepository.java | 6 +- .../core/event/EventObjectRepository.java | 1 + .../android/core/event/EventTableInfo.java | 1 + .../core/event/NewTrackerImporterEvent.java | 11 + .../NewTrackerImporterEventTransformer.kt | 1 + .../core/event/internal/EventHandler.java | 4 +- .../core/event/internal/EventImportHandler.kt | 3 + .../internal/EventProjectionTransformer.java | 1 + .../{EventStore.java => EventStore.kt} | 35 +-- .../core/event/internal/EventStoreImpl.java | 202 ------------------ .../core/event/internal/EventStoreImpl.kt | 198 +++++++++++++++++ ...ionshipStore.java => RelationshipStore.kt} | 16 +- .../internal/RelationshipStoreImpl.java | 84 -------- .../internal/RelationshipStoreImpl.kt | 116 ++++++++++ .../core/data/trackedentity/EventSamples.java | 1 + ...kedEntityPostPayloadGeneratorTaskShould.kt | 1 + 27 files changed, 491 insertions(+), 337 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/event/internal/{EventStore.java => EventStore.kt} (64%) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt rename core/src/main/java/org/hisp/dhis/android/core/relationship/internal/{RelationshipStore.java => RelationshipStore.kt} (72%) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt index 7c130239b3..80da3055e0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt @@ -43,6 +43,8 @@ import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.event.internal.EventStoreImpl import org.hisp.dhis.android.core.maintenance.D2Error import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore +import org.hisp.dhis.android.core.relationship.internal.RelationshipStoreImpl import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceCreateProjection import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore @@ -58,6 +60,7 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch private lateinit var trackedEntityInstanceStore: TrackedEntityInstanceStore private lateinit var enrollmentStore: EnrollmentStore private lateinit var eventStore: EventStore + private lateinit var relationshipStore: RelationshipStore @Before @Throws(IOException::class) @@ -65,7 +68,9 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch trackedEntityInstanceStore = TrackedEntityInstanceStoreImpl.create(d2.databaseAdapter()) enrollmentStore = create(d2.databaseAdapter()) eventStore = EventStoreImpl.create(d2.databaseAdapter()) - propagator = DataStatePropagatorImpl(trackedEntityInstanceStore, enrollmentStore, eventStore) + relationshipStore = RelationshipStoreImpl.create(d2.databaseAdapter()) + propagator = DataStatePropagatorImpl(trackedEntityInstanceStore, enrollmentStore, + eventStore, relationshipStore) } @Test @@ -359,6 +364,7 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch val eventUid = d2.eventModule().events().blockingAdd(sampleEventProjection(enrolmentUid)) eventStore.setSyncState(eventUid, state) + eventStore.setAggregatedSyncState(eventUid, state) return eventUid } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt index 3b22ec3190..c0765343a8 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventEndpointCallMockIntegrationShould.kt @@ -83,7 +83,9 @@ class EventEndpointCallMockIntegrationShould : BaseMockIntegrationTestMetadataEn assertThat(events.size).isEqualTo(1) EventStoreImpl.create(d2.databaseAdapter()).update( event.toBuilder() - .syncState(state).status(EventStatus.SKIPPED).build() + .syncState(state) + .aggregatedSyncState(state) + .status(EventStatus.SKIPPED).build() ) enqueue("event/events_1.json") diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java index 42718494be..2c8580db34 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventPostPayloadGeneratorMockIntegrationShould.java @@ -113,6 +113,9 @@ public void delete_old_import_conflicts() { eventStore.setSyncState(event1Id, State.TO_POST); eventStore.setSyncState(event2Id, State.TO_POST); eventStore.setSyncState(event3Id, State.TO_POST); + eventStore.setAggregatedSyncState(event1Id, State.TO_POST); + eventStore.setAggregatedSyncState(event2Id, State.TO_POST); + eventStore.setAggregatedSyncState(event3Id, State.TO_POST); dhis2MockServer.enqueueMockResponse("imports/web_response_with_event_import_conflicts2.json"); d2.eventModule().events().blockingUpload(); @@ -190,6 +193,7 @@ private void storeEvents() { .program(program.uid()) .programStage(programStage.uid()) .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .trackedEntityDataValues(Collections.singletonList(dataValue1)) .build(); @@ -201,6 +205,7 @@ private void storeEvents() { .program(program.uid()) .programStage(programStage.uid()) .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .trackedEntityDataValues(Collections.singletonList(dataValue2)) .build(); @@ -212,6 +217,7 @@ private void storeEvents() { .program(program.uid()) .programStage(programStage.uid()) .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .trackedEntityDataValues(Collections.singletonList(dataValue3)) .build(); @@ -223,6 +229,7 @@ private void storeEvents() { .program(program.uid()) .programStage(programStage.uid()) .syncState(State.ERROR) + .aggregatedSyncState(State.ERROR) .trackedEntityDataValues(Collections.singletonList(dataValue4)) .build(); @@ -251,6 +258,7 @@ private void storeSingleEvent(String eventUid, Program program, State state, Boo .program(program.uid()) .programStage(programStage.uid()) .syncState(state) + .aggregatedSyncState(state) .deleted(deleted) .build()); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java index 54c3c37504..1ee55ca73f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/event/internal/EventStoreIntegrationShould.java @@ -62,6 +62,7 @@ protected Event buildObjectToUpdate() { protected Event buildObjectWithToDeleteState() { return EventSamples.get().toBuilder() .syncState(State.TO_UPDATE) + .aggregatedSyncState(State.TO_UPDATE) .deleted(true) .build(); } @@ -70,6 +71,7 @@ protected Event buildObjectWithToDeleteState() { protected Event buildObjectWithSyncedState() { return EventSamples.get().toBuilder() .syncState(State.SYNCED) + .aggregatedSyncState(State.SYNCED) .build(); } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt index 1397915057..738524cfd3 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt @@ -346,6 +346,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI // Only enrollment1 and event1 are TO_UPDATE enrollmentStore.setAggregatedSyncState(enrollment2Id, State.SYNCED) enrollmentStore.setSyncState(enrollment2Id, State.SYNCED) + eventStore.setAggregatedSyncState(event2Id, State.SYNCED) eventStore.setSyncState(event2Id, State.SYNCED) dhis2MockServer.enqueueMockResponse("imports/web_response_with_empty_events.json") @@ -379,6 +380,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .program(program.uid()) .programStage(programStage!!.uid()) .syncState(State.TO_UPDATE) + .aggregatedSyncState(State.TO_UPDATE) .trackedEntityDataValues(listOf(dataValue1)) .build() @@ -399,6 +401,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .program(program.uid()) .programStage(programStage.uid()) .syncState(State.SYNCED_VIA_SMS) + .aggregatedSyncState(State.SYNCED_VIA_SMS) .trackedEntityDataValues(listOf(dataValue2)) .build() @@ -420,6 +423,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI .program(program.uid()) .programStage(programStage.uid()) .syncState(State.ERROR) + .aggregatedSyncState(State.ERROR) .trackedEntityDataValues(listOf(dataValue3)) .build() diff --git a/core/src/main/assets/migrations/104.sql b/core/src/main/assets/migrations/104.sql index 2b90b5118d..449eac0e68 100644 --- a/core/src/main/assets/migrations/104.sql +++ b/core/src/main/assets/migrations/104.sql @@ -37,6 +37,6 @@ INSERT INTO Enrollment (_id, uid, created, lastUpdated, createdAtClient, lastUpd DROP TABLE Enrollment_Old; ALTER TABLE Event RENAME TO Event_Old; -CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -INSERT INTO Event (_id, uid, enrollment, created, lastUpdated, createdAtClient, lastUpdatedAtClient, status, geometryType, geometryCoordinates, program, programStage, organisationUnit, eventDate, completedDate, dueDate, syncState, attributeOptionCombo, deleted, assignedUser) SELECT _id, uid, enrollment, created, lastUpdated, createdAtClient, lastUpdatedAtClient, status, geometryType, geometryCoordinates, program, programStage, organisationUnit, eventDate, completedDate, dueDate, state, attributeOptionCombo, deleted, assignedUser FROM Event_Old; +CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, aggregatedSyncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +INSERT INTO Event (_id, uid, enrollment, created, lastUpdated, createdAtClient, lastUpdatedAtClient, status, geometryType, geometryCoordinates, program, programStage, organisationUnit, eventDate, completedDate, dueDate, syncState, aggregatedSyncState, attributeOptionCombo, deleted, assignedUser) SELECT _id, uid, enrollment, created, lastUpdated, createdAtClient, lastUpdatedAtClient, status, geometryType, geometryCoordinates, program, programStage, organisationUnit, eventDate, completedDate, dueDate, state, state, attributeOptionCombo, deleted, assignedUser FROM Event_Old; DROP TABLE Event_Old; \ No newline at end of file diff --git a/core/src/main/assets/snapshots/106.sql b/core/src/main/assets/snapshots/106.sql index d6964e170e..63314fc6e9 100644 --- a/core/src/main/assets/snapshots/106.sql +++ b/core/src/main/assets/snapshots/106.sql @@ -70,7 +70,7 @@ CREATE TABLE ProgramStage (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT N CREATE TABLE Program (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, shortName TEXT, displayShortName TEXT, description TEXT, displayDescription TEXT, version INTEGER, onlyEnrollOnce INTEGER, enrollmentDateLabel TEXT, displayIncidentDate INTEGER, incidentDateLabel TEXT, registration INTEGER, selectEnrollmentDatesInFuture INTEGER, dataEntryMethod INTEGER, ignoreOverdueEvents INTEGER, selectIncidentDatesInFuture INTEGER, useFirstStageDuringRegistration INTEGER, displayFrontPageList INTEGER, programType TEXT, relatedProgram TEXT, trackedEntityType TEXT, categoryCombo TEXT, accessDataWrite INTEGER, expiryDays INTEGER, completeEventsExpiryDays INTEGER, expiryPeriodType TEXT, minAttributesRequiredToSearch INTEGER, maxTeiCountToReturn INTEGER, featureType TEXT, accessLevel TEXT, color TEXT, icon TEXT, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryCombo) REFERENCES CategoryCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE TrackedEntityInstance (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT, trackedEntityType TEXT, geometryType TEXT, geometryCoordinates TEXT, syncState TEXT, aggregatedSyncState TEXT, deleted INTEGER, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityType) REFERENCES TrackedEntityType (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Enrollment (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, organisationUnit TEXT NOT NULL, program TEXT NOT NULL, enrollmentDate TEXT, incidentDate TEXT, followup INTEGER, status TEXT, trackedEntityInstance TEXT NOT NULL, syncState TEXT, aggregatedSyncState TEXT, geometryType TEXT, geometryCoordinates TEXT, deleted INTEGER, completedDate TEXT, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); -CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE Event (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, enrollment TEXT, created TEXT, lastUpdated TEXT, createdAtClient TEXT, lastUpdatedAtClient TEXT, status TEXT, geometryType TEXT, geometryCoordinates TEXT, program TEXT NOT NULL, programStage TEXT NOT NULL, organisationUnit TEXT NOT NULL, eventDate TEXT, completedDate TEXT, dueDate TEXT, syncState TEXT, aggregatedSyncState TEXT, attributeOptionCombo TEXT, deleted INTEGER, assignedUser TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (programStage) REFERENCES ProgramStage (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (enrollment) REFERENCES Enrollment (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataElement TEXT NOT NULL, period TEXT NOT NULL, organisationUnit TEXT NOT NULL, categoryOptionCombo TEXT NOT NULL, attributeOptionCombo TEXT NOT NULL, value TEXT, storedBy TEXT, created TEXT, lastUpdated TEXT, comment TEXT, followUp INTEGER, syncState TEXT, deleted INTEGER, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (period) REFERENCES Period (periodId), FOREIGN KEY (organisationUnit) REFERENCES OrganisationUnit (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attributeOptionCombo) REFERENCES CategoryOptionCombo (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (dataElement, period, organisationUnit, categoryOptionCombo, attributeOptionCombo)); CREATE TABLE TrackedEntityDataValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, event TEXT NOT NULL, dataElement TEXT NOT NULL, storedBy TEXT, value TEXT, created TEXT, lastUpdated TEXT, providedElsewhere INTEGER, FOREIGN KEY (event) REFERENCES Event (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (dataElement) REFERENCES DataElement (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE TrackedEntityAttributeValue (_id INTEGER PRIMARY KEY AUTOINCREMENT, created TEXT, lastUpdated TEXT, value TEXT, trackedEntityAttribute TEXT NOT NULL, trackedEntityInstance TEXT NOT NULL, FOREIGN KEY (trackedEntityAttribute) REFERENCES trackedEntityAttribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (trackedEntityInstance) REFERENCES TrackedEntityInstance (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index f964752f1f..f1878b4448 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -60,6 +60,8 @@ internal interface DataStatePropagator { fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) + fun refreshEventAggregatedSyncState(eventUid: String) + fun refreshAggregatedSyncStatesCausedBy( trackedEntityInstanceUids: List, enrollmentUids: List, diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 8c18cb8e39..d741d0e2e5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -39,7 +39,10 @@ import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.EventTableInfo import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType +import org.hisp.dhis.android.core.relationship.RelationshipHelper import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance @@ -50,7 +53,8 @@ import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceSt internal class DataStatePropagatorImpl @Inject internal constructor( private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentStore: EnrollmentStore, - private val eventStore: EventStore + private val eventStore: EventStore, + private val relationshipStore: RelationshipStore ) : DataStatePropagator { override fun propagateTrackedEntityInstanceUpdate(tei: TrackedEntityInstance?) { @@ -64,20 +68,26 @@ internal class DataStatePropagatorImpl @Inject internal constructor( enrollment?.let { refreshEnrollmentAggregatedSyncState(it.uid()) refreshEnrollmentLastUpdated(it.uid()) + val tei = trackedEntityInstanceStore.selectByUid(it.trackedEntityInstance()!!) propagateTrackedEntityInstanceUpdate(tei) } } override fun propagateEventUpdate(event: Event?) { - event?.enrollment()?.let { enrollmentUid -> - val enrollment = enrollmentStore.selectByUid(enrollmentUid) - propagateEnrollmentUpdate(enrollment) + event?.let { + refreshEventAggregatedSyncState(it.uid()) + refreshEventLastUpdated(it.uid()) + + it.enrollment()?.let { enrollmentUid -> + val enrollment = enrollmentStore.selectByUid(enrollmentUid) + propagateEnrollmentUpdate(enrollment) + } } } override fun propagateTrackedEntityDataValueUpdate(dataValue: TrackedEntityDataValue?) { - setEventSyncState(dataValue!!.event(), getStateForUpdate) + setEventSyncState(dataValue!!.event()!!, getStateForUpdate) } override fun propagateTrackedEntityAttributeUpdate(trackedEntityAttributeValue: TrackedEntityAttributeValue?) { @@ -88,7 +98,7 @@ internal class DataStatePropagatorImpl @Inject internal constructor( if (note!!.noteType() == Note.NoteType.ENROLLMENT_NOTE) { setEnrollmentSyncState(note.enrollment()!!, getStateForUpdate) } else if (note.noteType() == Note.NoteType.EVENT_NOTE) { - setEventSyncState(note.event(), getStateForUpdate) + setEventSyncState(note.event()!!, getStateForUpdate) } } @@ -118,16 +128,21 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } } - private fun setEventSyncState(eventUid: String?, getState: (State?) -> State) { - eventStore.selectByUid(eventUid!!)?.let { event -> + private fun setEventSyncState(eventUid: String, getState: (State?) -> State) { + eventStore.selectByUid(eventUid)?.let { event -> + eventStore.setSyncState(eventUid, getState(event.syncState())) + propagateEventUpdate(event) + } + } + + private fun refreshEventLastUpdated(eventUid: String) { + eventStore.selectByUid(eventUid)?.let { event -> val now = Date() val updatedEvent = event.toBuilder() - .syncState(getState(event.syncState())) .lastUpdated(getMaxDate(event.lastUpdated(), now)) .lastUpdatedAtClient(getMaxDate(event.lastUpdatedAtClient(), now)) .build() eventStore.update(updatedEvent) - propagateEventUpdate(updatedEvent) } } @@ -202,27 +217,54 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } } + override fun refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid: String) { + trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid)?.let { instance -> + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, trackedEntityInstanceUid) + .build() + val enrollmentStates = enrollmentStore.selectAggregatedSyncStateWhere(whereClause) + + val relationships = relationshipStore.getRelationshipsByItem( + RelationshipHelper.teiItem(trackedEntityInstanceUid), + RelationshipConstraintType.FROM + ) + val relationshipStates = relationships.map { it.syncState()!! } + + val teiAggregatedSyncState = + getAggregatedSyncState(enrollmentStates + relationshipStates + instance.syncState()!!) + trackedEntityInstanceStore.setAggregatedSyncState(trackedEntityInstanceUid, teiAggregatedSyncState) + } + } + override fun refreshEnrollmentAggregatedSyncState(enrollmentUid: String) { enrollmentStore.selectByUid(enrollmentUid)?.let { enrollment -> val whereClause = WhereClauseBuilder() .appendKeyStringValue(EventTableInfo.Columns.ENROLLMENT, enrollmentUid) .build() - val eventStates = eventStore.selectSyncStateWhere(whereClause) + val eventStates = eventStore.selectAggregatedSyncStateWhere(whereClause) + + val relationships = relationshipStore.getRelationshipsByItem( + RelationshipHelper.enrollmentItem(enrollmentUid), + RelationshipConstraintType.FROM + ) + val relationshipStates = relationships.map { it.syncState()!! } - val enrollmentAggregatedSyncState = getAggregatedSyncState(eventStates + enrollment.syncState()!!) + val enrollmentAggregatedSyncState = + getAggregatedSyncState(eventStates + relationshipStates + enrollment.syncState()!!) enrollmentStore.setAggregatedSyncState(enrollmentUid, enrollmentAggregatedSyncState) } } - override fun refreshTrackedEntityInstanceAggregatedSyncState(trackedEntityInstanceUid: String) { - trackedEntityInstanceStore.selectByUid(trackedEntityInstanceUid)?.let { trackedEntityInstance -> - val whereClause = WhereClauseBuilder() - .appendKeyStringValue(EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, trackedEntityInstanceUid) - .build() - val enrollmentStates = enrollmentStore.selectAggregatedSyncStateWhere(whereClause) + override fun refreshEventAggregatedSyncState(eventUid: String) { + eventStore.selectByUid(eventUid)?.let { event -> + val relationships = relationshipStore.getRelationshipsByItem( + RelationshipHelper.eventItem(eventUid), + RelationshipConstraintType.FROM + ) + val relationshipStates = relationships.map { it.syncState()!! } - val teiAggregatedSyncState = getAggregatedSyncState(enrollmentStates + trackedEntityInstance.syncState()!!) - trackedEntityInstanceStore.setAggregatedSyncState(trackedEntityInstanceUid, teiAggregatedSyncState) + val eventAggregatedSyncState = getAggregatedSyncState(relationshipStates + event.syncState()!!) + eventStore.setAggregatedSyncState(eventUid, eventAggregatedSyncState) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java index bab0d18072..e0f15aaad0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentHandler.java @@ -122,6 +122,7 @@ protected void afterObjectHandled(Enrollment enrollment, HandleAction action, Bo eventHandler.handleMany(EnrollmentInternalAccessor.accessEvents(enrollment), event -> event.toBuilder() .syncState(State.SYNCED) + .aggregatedSyncState(State.SYNCED) .build(), overwrite); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java index 8c0e2ecbcd..768e03c091 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java @@ -37,20 +37,25 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.gabrielittner.auto.value.cursor.ColumnAdapter; +import com.gabrielittner.auto.value.cursor.ColumnName; 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.DbGeometryColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.EventStatusColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreCoordinatesColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNoteListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreRelationshipListColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreStateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreTrackedEntityDataValueListColumnAdapter; import org.hisp.dhis.android.core.arch.helpers.CoordinateHelper; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; import org.hisp.dhis.android.core.common.Coordinates; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.event.internal.EventFields; import org.hisp.dhis.android.core.note.Note; import org.hisp.dhis.android.core.relationship.Relationship; @@ -161,6 +166,21 @@ public abstract class Event extends BaseDeletableDataObject implements ObjectWit @ColumnAdapter(IgnoreRelationshipListColumnAdapter.class) abstract List relationships(); + @Nullable + @ColumnName(DataColumns.AGGREGATED_SYNC_STATE) + @ColumnAdapter(StateColumnAdapter.class) + public abstract State aggregatedSyncState(); + + /** + * @deprecated Use {@link #aggregatedSyncState()} instead. + */ + @Deprecated + @Nullable + @ColumnAdapter(IgnoreStateColumnAdapter.class) + public State state() { + return aggregatedSyncState(); + } + public static Builder builder() { return new $$AutoValue_Event.Builder(); } @@ -222,6 +242,16 @@ public abstract static class Builder extends BaseDeletableDataObject.Builder relationships); + public abstract Builder aggregatedSyncState(State aggregatedSyncState); + + /** + * @deprecated Use {@link #aggregatedSyncState(State)} and {@link #syncState(State)} instead. + */ + @Deprecated + public Builder state(State state) { + return aggregatedSyncState(state).syncState(state); + } + abstract Event autoBuild(); // Auxiliary fields to access values diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java index 22359cd2e6..d4fa80a083 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventCollectionRepository.java @@ -96,7 +96,7 @@ public final class EventCollectionRepository public Observable upload() { return Observable.concat( jobQueryCall.queryPendingJobs(), - Observable.fromCallable(() -> bySyncState().in(State.uploadableStates()) + Observable.fromCallable(() -> byAggregatedSyncState().in(State.uploadableStates()) .byEnrollmentUid().isNull() .blockingGetWithoutChildren()) .flatMap(postCall::uploadEvents) @@ -193,6 +193,10 @@ public EnumFilterConnector bySyncState() { return cf.enumC(Columns.SYNC_STATE); } + public EnumFilterConnector byAggregatedSyncState() { + return cf.enumC(Columns.AGGREGATED_SYNC_STATE); + } + public StringFilterConnector byAttributeOptionComboUid() { return cf.string(Columns.ATTRIBUTE_OPTION_COMBO); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java index eee16c9fd8..7322afe8f5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventObjectRepository.java @@ -99,6 +99,7 @@ private Event.Builder updateBuilder() { return event.toBuilder() .syncState(state) + .aggregatedSyncState(state) .lastUpdated(updateDate) .lastUpdatedAtClient(updateDate); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java index 5c237e6c56..189546edd9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/EventTableInfo.java @@ -88,6 +88,7 @@ public String[] all() { COMPLETE_DATE, DUE_DATE, SYNC_STATE, + AGGREGATED_SYNC_STATE, ATTRIBUTE_OPTION_COMBO, DELETED, ASSIGNED_USER diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java index 85dadcde56..c265975d36 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java @@ -37,17 +37,21 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.gabrielittner.auto.value.cursor.ColumnAdapter; +import com.gabrielittner.auto.value.cursor.ColumnName; 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.DbGeometryColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.EventStatusColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.enums.internal.StateColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNewTackerImporterTrackedEntityDataValueListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreNewTrackerImporterNoteListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreRelationshipListColumnAdapter; import org.hisp.dhis.android.core.common.BaseDeletableDataObject; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.Geometry; import org.hisp.dhis.android.core.common.ObjectWithUidInterface; +import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.event.internal.EventFields; import org.hisp.dhis.android.core.note.NewTrackerImporterNote; import org.hisp.dhis.android.core.relationship.Relationship; @@ -149,6 +153,11 @@ public abstract class NewTrackerImporterEvent extends BaseDeletableDataObject im @ColumnAdapter(IgnoreRelationshipListColumnAdapter.class) abstract List relationships(); + @Nullable + @ColumnName(DataColumns.AGGREGATED_SYNC_STATE) + @ColumnAdapter(StateColumnAdapter.class) + public abstract State aggregatedSyncState(); + public static Builder builder() { return new $$AutoValue_NewTrackerImporterEvent.Builder(); } @@ -206,6 +215,8 @@ public abstract Builder trackedEntityDataValues( public abstract Builder relationships(List relationships); + public abstract Builder aggregatedSyncState(State aggregatedSyncState); + public abstract Geometry geometry(); public abstract NewTrackerImporterEvent build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt index 8e80ac223d..bd5c5687bb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEventTransformer.kt @@ -51,6 +51,7 @@ internal class NewTrackerImporterEventTransformer : Transformer val state = State.TO_UPDATE trackerImportConflictStore.deleteEventConflicts(event.uid()) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java index 1d5d68415a..7806841a55 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventProjectionTransformer.java @@ -46,6 +46,7 @@ public Event transform(EventCreateProjection projection) { return Event.builder() .uid(generatedUid) + .aggregatedSyncState(State.TO_POST) .syncState(State.TO_POST) .created(creationDate) .lastUpdated(creationDate) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt similarity index 64% rename from core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.java rename to core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt index 3b711d880a..91fd4c1e2d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt @@ -25,30 +25,33 @@ * (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.event.internal -package org.hisp.dhis.android.core.event.internal; +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.event.Event -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore; -import org.hisp.dhis.android.core.event.Event; +internal interface EventStore : IdentifiableDeletableDataObjectStore { + fun queryEventsAttachedToEnrollmentToPost(): Map> -import java.util.List; -import java.util.Map; + fun querySingleEventsToPost(): List -public interface EventStore extends IdentifiableDeletableDataObjectStore { + fun querySingleEvents(): List - Map> queryEventsAttachedToEnrollmentToPost(); + fun queryOrderedForEnrollmentAndProgramStage( + enrollmentUid: String, + programStageUid: String, + includeDeleted: Boolean + ): List - List querySingleEventsToPost(); - List querySingleEvents(); + fun countEventsForEnrollment(enrollmentUid: String, includeDeleted: Boolean): Int - List queryOrderedForEnrollmentAndProgramStage(String enrollmentUid, - String programStageUid, - Boolean includeDeleted); + fun countTeisWhereEvents(whereClause: String): Int - Integer countEventsForEnrollment(String enrollmentUid, Boolean includeDeleted); + fun queryMissingRelationshipsUids(): List - int countTeisWhereEvents(String whereClause); + fun setAggregatedSyncState(uid: String, state: State): Int - List queryMissingRelationshipsUids(); -} + fun selectAggregatedSyncStateWhere(whereClause: String): List +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java deleted file mode 100644 index 05f0c94c2c..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.event.internal; - -import android.database.Cursor; - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStoreImpl; -import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; -import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; -import org.hisp.dhis.android.core.common.DataColumns; -import org.hisp.dhis.android.core.common.IdentifiableColumns; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.EventTableInfo; -import org.hisp.dhis.android.core.event.EventTableInfo.Columns; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import kotlin.jvm.functions.Function1; - -public final class EventStoreImpl extends IdentifiableDeletableDataObjectStoreImpl implements EventStore { - - private static final String QUERY_SINGLE_EVENTS = "SELECT Event.* FROM Event WHERE Event.enrollment IS NULL"; - - private static final StatementBinder BINDER = (o, w) -> { - w.bind(1, o.uid()); - w.bind(2, o.enrollment()); - w.bind(3, o.created()); - w.bind(4, o.lastUpdated()); - w.bind(5, o.createdAtClient()); - w.bind(6, o.lastUpdatedAtClient()); - w.bind(7, o.status()); - w.bind(8, o.geometry() == null ? null : o.geometry().type()); - w.bind(9, o.geometry() == null ? null : o.geometry().coordinates()); - w.bind(10, o.program()); - w.bind(11, o.programStage()); - w.bind(12, o.organisationUnit()); - w.bind(13, o.eventDate()); - w.bind(14, o.completedDate()); - w.bind(15, o.dueDate()); - w.bind(16, o.syncState()); - w.bind(17, o.attributeOptionCombo()); - w.bind(18, o.deleted()); - w.bind(19, o.assignedUser()); - }; - - private EventStoreImpl(DatabaseAdapter databaseAdapter, - SQLStatementBuilderImpl builder, - StatementBinder binder, - Function1 objectFactory) { - super(databaseAdapter, builder, binder, objectFactory); - } - - @Override - public Map> queryEventsAttachedToEnrollmentToPost() { - String eventsAttachedToEnrollmentsQuery = new WhereClauseBuilder() - .appendIsNotNullValue(Columns.ENROLLMENT) - .appendInKeyStringValues(Columns.SYNC_STATE, EnumHelper.asStringList(State.uploadableStates())).build(); - - List eventList = selectWhere(eventsAttachedToEnrollmentsQuery); - - Map> eventsMap = new HashMap<>(); - for (Event event : eventList) { - addEventsToMap(eventsMap, event); - } - - return eventsMap; - } - - @Override - public List querySingleEventsToPost() { - String states = CollectionsHelper.commaAndSpaceSeparatedArrayValues( - CollectionsHelper.withSingleQuotationMarksArray(EnumHelper.asStringList(State.uploadableStates()))); - String singleEventsToPostQuery = QUERY_SINGLE_EVENTS + - " AND (" + Columns.SYNC_STATE + " IN (" + states + "))"; - return eventListFromQuery(singleEventsToPostQuery); - } - - @Override - public List querySingleEvents() { - return eventListFromQuery(QUERY_SINGLE_EVENTS); - } - - @Override - public List queryOrderedForEnrollmentAndProgramStage(String enrollmentUid, String programStageUid, - Boolean includeDeleted) { - WhereClauseBuilder whereClause = new WhereClauseBuilder() - .appendKeyStringValue(Columns.ENROLLMENT, enrollmentUid) - .appendKeyStringValue(Columns.PROGRAM_STAGE, programStageUid); - - if (!includeDeleted) { - whereClause.appendIsNullOrValue(Columns.DELETED, "0"); - } - - String query = "SELECT * FROM " + EventTableInfo.TABLE_INFO.name() + " " + - "WHERE " + whereClause.build() + - "ORDER BY " + Columns.EVENT_DATE + ", " + Columns.LAST_UPDATED; - - return eventListFromQuery(query); - } - - @Override - public Integer countEventsForEnrollment(String enrollmentUid, Boolean includeDeleted) { - WhereClauseBuilder whereClause = new WhereClauseBuilder() - .appendKeyStringValue(Columns.ENROLLMENT, enrollmentUid); - - if (!includeDeleted) { - whereClause.appendIsNullOrValue(Columns.DELETED, "0"); - } - - String query = "SELECT * FROM " + EventTableInfo.TABLE_INFO.name() + " " + - "WHERE " + whereClause.build(); - - List events = eventListFromQuery(query); - return events.size(); - } - - @Override - public int countTeisWhereEvents(String whereClause) { - String whereStatement = whereClause == null ? "" : " WHERE " + whereClause; - String query = "SELECT COUNT(DISTINCT a." + EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE + ") " + - "FROM " + EnrollmentTableInfo.TABLE_INFO.name() + " a " + - "INNER JOIN " + - "(SELECT DISTINCT " + Columns.ENROLLMENT + - " FROM " + EventTableInfo.TABLE_INFO.name() + whereStatement + ") b " + - "ON a." + IdentifiableColumns.UID + " = b." + Columns.ENROLLMENT; - - return processCount(getDatabaseAdapter().rawQuery(query)); - } - - @Override - public List queryMissingRelationshipsUids() { - String whereRelationshipsClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.SYNC_STATE, State.RELATIONSHIP) - .appendIsNullValue(EventTableInfo.Columns.ORGANISATION_UNIT) - .build(); - - return selectUidsWhere(whereRelationshipsClause); - } - - private List eventListFromQuery(String query) { - List eventList = new ArrayList<>(); - Cursor cursor = getDatabaseAdapter().rawQuery(query); - addObjectsToCollection(cursor, eventList); - return eventList; - } - - private void addEventsToMap(Map> eventsMap, Event event) { - if (eventsMap.get(event.enrollment()) == null) { - eventsMap.put(event.enrollment(), new ArrayList<>()); - } - - eventsMap.get(event.enrollment()).add(event); - } - - public static EventStore create(DatabaseAdapter databaseAdapter) { - SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl( - EventTableInfo.TABLE_INFO.name(), - EventTableInfo.TABLE_INFO.columns()); - - return new EventStoreImpl( - databaseAdapter, - statementBuilder, - BINDER, - Event::create - ); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt new file mode 100644 index 0000000000..f191d40faa --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2004-2021, 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.core.event.internal + +import android.content.ContentValues +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +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.internal.IdentifiableDeletableDataObjectStoreImpl +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper.asStringList +import org.hisp.dhis.android.core.common.DataColumns +import org.hisp.dhis.android.core.common.IdentifiableColumns +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.State.Companion.uploadableStates +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.EventTableInfo +import java.util.* + +internal class EventStoreImpl private constructor( + databaseAdapter: DatabaseAdapter, + builder: SQLStatementBuilderImpl, + binder: StatementBinder, + objectFactory: Function1 +) : IdentifiableDeletableDataObjectStoreImpl(databaseAdapter, builder, binder, objectFactory), EventStore { + + override fun queryEventsAttachedToEnrollmentToPost(): Map> { + val eventsAttachedToEnrollmentsQuery = WhereClauseBuilder() + .appendIsNotNullValue(EventTableInfo.Columns.ENROLLMENT) + .appendInKeyStringValues(EventTableInfo.Columns.SYNC_STATE, asStringList(*uploadableStates())).build() + val eventList = selectWhere(eventsAttachedToEnrollmentsQuery) + val eventsMap: MutableMap> = HashMap() + for (event in eventList) { + addEventsToMap(eventsMap, event) + } + return eventsMap + } + + override fun querySingleEventsToPost(): List { + val states = CollectionsHelper.commaAndSpaceSeparatedArrayValues( + CollectionsHelper.withSingleQuotationMarksArray(asStringList(*uploadableStates())) + ) + val singleEventsToPostQuery = QUERY_SINGLE_EVENTS + + " AND (" + EventTableInfo.Columns.SYNC_STATE + " IN (" + states + "))" + return eventListFromQuery(singleEventsToPostQuery) + } + + override fun querySingleEvents(): List { + return eventListFromQuery(QUERY_SINGLE_EVENTS) + } + + override fun queryOrderedForEnrollmentAndProgramStage( + enrollmentUid: String, programStageUid: String, + includeDeleted: Boolean + ): List { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EventTableInfo.Columns.ENROLLMENT, enrollmentUid) + .appendKeyStringValue(EventTableInfo.Columns.PROGRAM_STAGE, programStageUid) + if (!includeDeleted) { + whereClause.appendIsNullOrValue(EventTableInfo.Columns.DELETED, "0") + } + val query = "SELECT * FROM " + EventTableInfo.TABLE_INFO.name() + " " + + "WHERE " + whereClause.build() + + "ORDER BY " + EventTableInfo.Columns.EVENT_DATE + ", " + EventTableInfo.Columns.LAST_UPDATED + return eventListFromQuery(query) + } + + override fun countEventsForEnrollment(enrollmentUid: String, includeDeleted: Boolean): Int { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EventTableInfo.Columns.ENROLLMENT, enrollmentUid) + if (!includeDeleted) { + whereClause.appendIsNullOrValue(EventTableInfo.Columns.DELETED, "0") + } + val query = "SELECT * FROM " + EventTableInfo.TABLE_INFO.name() + " " + + "WHERE " + whereClause.build() + val events = eventListFromQuery(query) + return events.size + } + + override fun countTeisWhereEvents(whereClause: String): Int { + val whereStatement = if (whereClause == null) "" else " WHERE $whereClause" + val query = "SELECT COUNT(DISTINCT a." + EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE + ") " + + "FROM " + EnrollmentTableInfo.TABLE_INFO.name() + " a " + + "INNER JOIN " + + "(SELECT DISTINCT " + EventTableInfo.Columns.ENROLLMENT + + " FROM " + EventTableInfo.TABLE_INFO.name() + whereStatement + ") b " + + "ON a." + IdentifiableColumns.UID + " = b." + EventTableInfo.Columns.ENROLLMENT + return processCount(databaseAdapter.rawQuery(query)) + } + + override fun queryMissingRelationshipsUids(): List { + val whereRelationshipsClause = WhereClauseBuilder() + .appendKeyStringValue(DataColumns.SYNC_STATE, State.RELATIONSHIP) + .appendIsNullValue(EventTableInfo.Columns.ORGANISATION_UNIT) + .build() + return selectUidsWhere(whereRelationshipsClause) + } + + override fun setAggregatedSyncState(uid: String, state: State): Int { + val updates = ContentValues() + updates.put(DataColumns.AGGREGATED_SYNC_STATE, state.toString()) + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(IdentifiableColumns.UID, uid) + .build() + + return updateWhere(updates, whereClause) + } + + override fun selectAggregatedSyncStateWhere(whereClause: String): List { + val statesStr = selectStringColumnsWhereClause(DataColumns.AGGREGATED_SYNC_STATE, whereClause) + + return statesStr.map { State.valueOf(it) } + } + + private fun eventListFromQuery(query: String): List { + val eventList: MutableList = ArrayList() + val cursor = databaseAdapter.rawQuery(query) + addObjectsToCollection(cursor, eventList) + return eventList + } + + private fun addEventsToMap(eventsMap: MutableMap>, event: Event) { + event.enrollment()?.let { enrollmentUid -> + if (eventsMap[enrollmentUid] == null) { + eventsMap[enrollmentUid] = ArrayList() + } + eventsMap[enrollmentUid]!!.add(event) + } + } + + companion object { + private const val QUERY_SINGLE_EVENTS = "SELECT Event.* FROM Event WHERE Event.enrollment IS NULL" + private val BINDER = StatementBinder { o: Event, w: StatementWrapper -> + w.bind(1, o.uid()) + w.bind(2, o.enrollment()) + w.bind(3, o.created()) + w.bind(4, o.lastUpdated()) + w.bind(5, o.createdAtClient()) + w.bind(6, o.lastUpdatedAtClient()) + w.bind(7, o.status()) + w.bind(8, if (o.geometry() == null) null else o.geometry()!!.type()) + w.bind(9, if (o.geometry() == null) null else o.geometry()!!.coordinates()) + w.bind(10, o.program()) + w.bind(11, o.programStage()) + w.bind(12, o.organisationUnit()) + w.bind(13, o.eventDate()) + w.bind(14, o.completedDate()) + w.bind(15, o.dueDate()) + w.bind(16, o.syncState()) + w.bind(17, o.aggregatedSyncState()) + w.bind(18, o.attributeOptionCombo()) + w.bind(19, o.deleted()) + w.bind(20, o.assignedUser()) + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): EventStore { + val statementBuilder = SQLStatementBuilderImpl( + EventTableInfo.TABLE_INFO.name(), + EventTableInfo.TABLE_INFO.columns() + ) + return EventStoreImpl( + databaseAdapter, + statementBuilder, + BINDER + ) { cursor: Cursor? -> Event.create(cursor) } + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt similarity index 72% rename from core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.java rename to core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt index d8a6500b01..7acf940d66 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt @@ -25,15 +25,17 @@ * (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.relationship.internal -package org.hisp.dhis.android.core.relationship.internal; +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore +import org.hisp.dhis.android.core.relationship.Relationship +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType +import org.hisp.dhis.android.core.relationship.RelationshipItem -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStore; -import org.hisp.dhis.android.core.relationship.Relationship; -import org.hisp.dhis.android.core.relationship.RelationshipItem; +internal interface RelationshipStore : IdentifiableDeletableDataObjectStore { -import java.util.List; + fun getRelationshipsByItem(relationshipItem: RelationshipItem): List -public interface RelationshipStore extends IdentifiableDeletableDataObjectStore { - List getRelationshipsByItem(RelationshipItem relationshipItem); + fun getRelationshipsByItem(relationshipItem: RelationshipItem, + type: RelationshipConstraintType?): List } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java deleted file mode 100644 index 2a397799bf..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.relationship.internal; - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStoreImpl; -import org.hisp.dhis.android.core.relationship.Relationship; -import org.hisp.dhis.android.core.relationship.RelationshipItem; -import org.hisp.dhis.android.core.relationship.RelationshipTableInfo; - -import java.util.ArrayList; -import java.util.List; - -public final class RelationshipStoreImpl extends IdentifiableDeletableDataObjectStoreImpl - implements RelationshipStore { - - private static StatementBinder BINDER = (o, w) -> { - w.bind(1, o.uid()); - w.bind(2, o.name()); - w.bind(3, o.created()); - w.bind(4, o.lastUpdated()); - w.bind(5, o.relationshipType()); - w.bind(6, o.syncState()); - w.bind(7, o.deleted()); - }; - - private RelationshipStoreImpl(DatabaseAdapter databaseAdapter, - SQLStatementBuilderImpl statementBuilder) { - super(databaseAdapter, statementBuilder, BINDER, Relationship::create); - } - - @Override - public List getRelationshipsByItem(RelationshipItem relationshipItem) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue("RelationshipItem." + relationshipItem.elementType(), - relationshipItem.elementUid()) - .build(); - - String queryStatement = - "SELECT DISTINCT Relationship.* " + - "FROM (Relationship INNER JOIN RelationshipItem " + - "ON Relationship.uid = RelationshipItem.relationship) " + - "WHERE " + whereClause + ";"; - - List relationships = new ArrayList<>(); - addObjectsToCollection(getDatabaseAdapter().rawQuery(queryStatement), relationships); - - return relationships; - } - - public static RelationshipStore create(DatabaseAdapter databaseAdapter) { - SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl(RelationshipTableInfo.TABLE_INFO); - return new RelationshipStoreImpl(databaseAdapter, statementBuilder); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt new file mode 100644 index 0000000000..a93392ce49 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +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.internal.IdentifiableDeletableDataObjectStoreImpl +import org.hisp.dhis.android.core.relationship.* +import java.util.* + +internal class RelationshipStoreImpl private constructor( + databaseAdapter: DatabaseAdapter, + statementBuilder: SQLStatementBuilderImpl +) : IdentifiableDeletableDataObjectStoreImpl( + databaseAdapter, + statementBuilder, + BINDER, + { cursor: Cursor -> Relationship.create(cursor) }), RelationshipStore { + + override fun getRelationshipsByItem(relationshipItem: RelationshipItem): List { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue( + "RelationshipItem." + relationshipItem.elementType(), + relationshipItem.elementUid() + ) + .build() + + val queryStatement = "SELECT DISTINCT Relationship.* " + + "FROM (Relationship INNER JOIN RelationshipItem " + + "ON Relationship.uid = RelationshipItem.relationship) " + + "WHERE " + whereClause + ";" + + val relationships: MutableList = ArrayList() + addObjectsToCollection(databaseAdapter.rawQuery(queryStatement), relationships) + return relationships + } + + override fun getRelationshipsByItem(relationshipItem: RelationshipItem, + type: RelationshipConstraintType?): List { + val relationshipTable = RelationshipTableInfo.TABLE_INFO.name() + val itemTable = RelationshipItemTableInfo.TABLE_INFO.name() + + val builder = WhereClauseBuilder() + .appendKeyStringValue( + "${itemTable}.${relationshipItem.elementType()}", + relationshipItem.elementUid() + ) + + val whereClause = + if (type == null) { + builder.build() + } else { + builder.appendKeyStringValue( + "${itemTable}.${RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE}", + type.name + ).build() + } + + val queryStatement = "SELECT DISTINCT $relationshipTable.* " + + "FROM ($relationshipTable INNER JOIN $itemTable " + + "ON $relationshipTable.${RelationshipTableInfo.Columns.UID} = " + + "$itemTable.${RelationshipItemTableInfo.Columns.RELATIONSHIP}) " + + "WHERE " + whereClause + ";" + + val relationships: MutableList = ArrayList() + addObjectsToCollection(databaseAdapter.rawQuery(queryStatement), relationships) + return relationships + } + + companion object { + private val BINDER = StatementBinder { o: Relationship, w: StatementWrapper -> + w.bind(1, o.uid()) + w.bind(2, o.name()) + w.bind(3, o.created()) + w.bind(4, o.lastUpdated()) + w.bind(5, o.relationshipType()) + w.bind(6, o.syncState()) + w.bind(7, o.deleted()) + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): RelationshipStore { + val statementBuilder = SQLStatementBuilderImpl(RelationshipTableInfo.TABLE_INFO) + return RelationshipStoreImpl(databaseAdapter, statementBuilder) + } + } +} \ No newline at end of file diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java index 8f22db7505..fb90f48ac6 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/trackedentity/EventSamples.java @@ -65,6 +65,7 @@ public static Event get(String uid, String enrollment, String organisationUnit, .dueDate(getDate("2014-08-20T12:28:56.409")) .attributeOptionCombo(attributeOptionCombo) .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) .deleted(false) .build(); } diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt index c9ff20fda0..97334e3dd3 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould.kt @@ -141,6 +141,7 @@ class NewTrackerImporterTrackedEntityPostPayloadGeneratorTaskShould { .uid(uidGenerator.generate()) .enrollment(enrollmentUid) .syncState(State.TO_UPDATE) + .aggregatedSyncState(State.TO_UPDATE) .deleted(deleted) .build() } From 6bc6fb5702172fe75aa899a6bffd08034dd1cdc9 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 27 Jul 2021 14:24:13 +0200 Subject: [PATCH 232/308] [ANDROSDK-1344] Manage relationship propagation --- .../DataStatePropagatorIntegrationShould.kt | 47 +++++++++++++++---- .../wipe/WipeDBCallMockIntegrationShould.java | 3 +- .../common/internal/DataStatePropagator.kt | 3 +- .../internal/DataStatePropagatorImpl.kt | 29 ++++++++++-- .../RelationshipCollectionRepository.java | 7 --- .../importer/internal/JobReportHandler.kt | 3 +- 6 files changed, 67 insertions(+), 25 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt index 80da3055e0..2650832e0d 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt @@ -42,7 +42,10 @@ import org.hisp.dhis.android.core.event.EventCreateProjection import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.event.internal.EventStoreImpl import org.hisp.dhis.android.core.maintenance.D2Error +import org.hisp.dhis.android.core.relationship.Relationship import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStore +import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStoreImpl import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.relationship.internal.RelationshipStoreImpl import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue @@ -61,6 +64,9 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch private lateinit var enrollmentStore: EnrollmentStore private lateinit var eventStore: EventStore private lateinit var relationshipStore: RelationshipStore + private lateinit var relationshipItemStore: RelationshipItemStore + + private val relationshipType = "WiH6923nMtb" @Before @Throws(IOException::class) @@ -69,8 +75,10 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch enrollmentStore = create(d2.databaseAdapter()) eventStore = EventStoreImpl.create(d2.databaseAdapter()) relationshipStore = RelationshipStoreImpl.create(d2.databaseAdapter()) + relationshipItemStore = RelationshipItemStoreImpl.create(d2.databaseAdapter()) + propagator = DataStatePropagatorImpl(trackedEntityInstanceStore, enrollmentStore, - eventStore, relationshipStore) + eventStore, relationshipStore, relationshipItemStore) } @Test @@ -204,14 +212,20 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch @Throws(D2Error::class) fun propagate_tei_relationship_update() { val teiUid = createTEIWithState(State.SYNCED) - val fromItem = RelationshipHelper.teiItem(teiUid) - propagator.propagateRelationshipUpdate(fromItem) + val relationshipUid = d2.relationshipModule().relationships().blockingAdd( + Relationship.builder() + .relationshipType(relationshipType) + .from(RelationshipHelper.teiItem(teiUid)) + .to(RelationshipHelper.teiItem(teiUid)) + .build() + ) - assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.TO_UPDATE) + assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.SYNCED) assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) trackedEntityInstanceStore.delete(teiUid) + relationshipStore.delete(relationshipUid) } @Test @@ -219,16 +233,22 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch fun propagate_enrollment_relationship_update() { val teiUid = createTEIWithState(State.SYNCED) val enrollmentUid = createEnrollmentWithState(State.SYNCED, teiUid) - val fromItem = RelationshipHelper.enrollmentItem(enrollmentUid) - propagator.propagateRelationshipUpdate(fromItem) + val relationshipUid = d2.relationshipModule().relationships().blockingAdd( + Relationship.builder() + .relationshipType(relationshipType) + .from(RelationshipHelper.enrollmentItem(enrollmentUid)) + .to(RelationshipHelper.enrollmentItem(enrollmentUid)) + .build() + ) assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.SYNCED) assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) - assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.syncState()).isEqualTo(State.TO_UPDATE) + assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.syncState()).isEqualTo(State.SYNCED) assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) trackedEntityInstanceStore.delete(teiUid) + relationshipStore.delete(relationshipUid) } @Test @@ -237,17 +257,24 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch val teiUid = createTEIWithState(State.SYNCED) val enrollmentUid = createEnrollmentWithState(State.SYNCED, teiUid) val eventUid = createEventWithState(State.SYNCED, enrollmentUid) - val fromItem = RelationshipHelper.eventItem(eventUid) - propagator.propagateRelationshipUpdate(fromItem) + val relationshipUid = d2.relationshipModule().relationships().blockingAdd( + Relationship.builder() + .relationshipType(relationshipType) + .from(RelationshipHelper.eventItem(eventUid)) + .to(RelationshipHelper.eventItem(eventUid)) + .build() + ) assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.syncState()).isEqualTo(State.SYNCED) assertThat(trackedEntityInstanceStore.selectByUid(teiUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.syncState()).isEqualTo(State.SYNCED) assertThat(enrollmentStore.selectByUid(enrollmentUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) - assertThat(eventStore.selectByUid(eventUid)!!.syncState()).isEqualTo(State.TO_UPDATE) + assertThat(eventStore.selectByUid(eventUid)!!.syncState()).isEqualTo(State.SYNCED) + assertThat(eventStore.selectByUid(eventUid)!!.aggregatedSyncState()).isEqualTo(State.TO_UPDATE) trackedEntityInstanceStore.delete(teiUid) + relationshipStore.delete(relationshipUid) } @Throws(D2Error::class) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index 5a2666e66e..60850631b0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -38,6 +38,7 @@ import org.hisp.dhis.android.core.maintenance.D2Error; import org.hisp.dhis.android.core.maintenance.D2ErrorCode; import org.hisp.dhis.android.core.maintenance.internal.D2ErrorStore; +import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType; import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObject; import org.hisp.dhis.android.core.tracker.importer.internal.TrackerJobObjectStore; import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyDispatcher; @@ -95,7 +96,7 @@ private void givenOthersInDatabase() { TrackerJobObjectStore.create(databaseAdapter).insert( TrackerJobObject.builder() .jobUid("uid") - .trackerType("type") + .trackerType(TrackerImporterObjectType.EVENT) .objectUid("oUid") .lastUpdated(new Date()) .build() diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index f1878b4448..56085d0bb2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -65,6 +65,7 @@ internal interface DataStatePropagator { fun refreshAggregatedSyncStatesCausedBy( trackedEntityInstanceUids: List, enrollmentUids: List, - eventUids: List + eventUids: List, + relationshipUids: List ) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index d741d0e2e5..a003872c49 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -42,6 +42,7 @@ import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.relationship.RelationshipConstraintType import org.hisp.dhis.android.core.relationship.RelationshipHelper import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStore import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue @@ -54,7 +55,8 @@ internal class DataStatePropagatorImpl @Inject internal constructor( private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentStore: EnrollmentStore, private val eventStore: EventStore, - private val relationshipStore: RelationshipStore + private val relationshipStore: RelationshipStore, + private val relationshipItemStore: RelationshipItemStore ) : DataStatePropagator { override fun propagateTrackedEntityInstanceUpdate(tei: TrackedEntityInstance?) { @@ -105,11 +107,14 @@ internal class DataStatePropagatorImpl @Inject internal constructor( override fun propagateRelationshipUpdate(item: RelationshipItem?) { if (item != null) { if (item.hasTrackedEntityInstance()) { - setTeiSyncState(item.trackedEntityInstance()!!.trackedEntityInstance(), getStateForUpdate) + val tei = trackedEntityInstanceStore.selectByUid(item.elementUid()) + propagateTrackedEntityInstanceUpdate(tei) } else if (item.hasEnrollment()) { - setEnrollmentSyncState(item.enrollment()!!.enrollment(), getStateForUpdate) + val enrollment = enrollmentStore.selectByUid(item.elementUid()) + propagateEnrollmentUpdate(enrollment) } else if (item.hasEvent()) { - setEventSyncState(item.event()!!.event(), getStateForUpdate) + val event = eventStore.selectByUid(item.elementUid()) + propagateEventUpdate(event) } } } @@ -271,8 +276,13 @@ internal class DataStatePropagatorImpl @Inject internal constructor( override fun refreshAggregatedSyncStatesCausedBy( trackedEntityInstanceUids: List, enrollmentUids: List, - eventUids: List + eventUids: List, + relationshipUids: List ) { + eventUids.forEach { + refreshEventAggregatedSyncState(it) + } + val enrollmentsFromEvents = eventStore.selectByUids(eventUids).mapNotNull { it.enrollment() } val enrollments = enrollmentStore.selectByUids(enrollmentUids + enrollmentsFromEvents) @@ -284,6 +294,15 @@ internal class DataStatePropagatorImpl @Inject internal constructor( teiUids.forEach { refreshTrackedEntityInstanceAggregatedSyncState(it) } + + relationshipUids.forEach { + val item = relationshipItemStore.getForRelationshipUidAndConstraintType(it, RelationshipConstraintType.FROM) + when { + item.hasEvent() -> refreshEventAggregatedSyncState(item.elementUid()) + item.hasEnrollment() -> refreshEnrollmentAggregatedSyncState(item.elementUid()) + item.hasTrackedEntityInstance() -> refreshTrackedEntityInstanceAggregatedSyncState(item.elementUid()) + } + } } private fun getAggregatedSyncState(states: List): State { diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 61200edb63..09634a5701 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -115,13 +115,6 @@ public String blockingAdd(Relationship relationship) throws D2Error { .errorCode(D2ErrorCode.CANT_CREATE_EXISTING_OBJECT) .errorDescription("Tried to create already existing Relationship: " + relationship) .build(); - } else if (from == null || !from.hasTrackedEntityInstance() || to == null || !to.hasTrackedEntityInstance()) { - throw D2Error - .builder() - .errorComponent(D2ErrorComponent.SDK) - .errorCode(D2ErrorCode.CANT_CREATE_EXISTING_OBJECT) - .errorDescription("Only TEI-TEI relationships creation supported") - .build(); } else { if (relationship.uid() == null) { String generatedUid = new UidGeneratorImpl().generate(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index c6a8542f5c..821ac3cd73 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -117,7 +117,8 @@ internal class JobReportHandler @Inject internal constructor( dataStatePropagator.refreshAggregatedSyncStatesCausedBy( jobObjects.filter { it.trackerType() == TRACKED_ENTITY }.map { it.objectUid() }, jobObjects.filter { it.trackerType() == ENROLLMENT }.map { it.objectUid() }, - jobObjects.filter { it.trackerType() == EVENT }.map { it.objectUid() } + jobObjects.filter { it.trackerType() == EVENT }.map { it.objectUid() }, + jobObjects.filter { it.trackerType() == RELATIONSHIP }.map { it.objectUid() } ) } From 8e8bacbc161ba44541e231f68df8b0c391fa05d4 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 27 Jul 2021 14:37:25 +0200 Subject: [PATCH 233/308] [ANDROSDK-1344] Remove related relationships on manage --- .../internal/JobReportEnrollmentHandler.kt | 15 ++++++++++++--- .../importer/internal/JobReportEventHandler.kt | 15 ++++++++++++--- .../internal/JobReportRelationshipHandler.kt | 15 +++++++++++---- .../internal/JobReportTrackedEntityHandler.kt | 18 +++++++++++++----- .../importer/internal/JobReportTypeHandler.kt | 15 ++++++++++++--- 5 files changed, 60 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt index 9102a6f84f..6ec77f754f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEnrollmentHandler.kt @@ -39,14 +39,17 @@ import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.note.NoteTableInfo +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore @Reusable internal class JobReportEnrollmentHandler @Inject internal constructor( private val noteStore: IdentifiableObjectStore, private val enrollmentStore: EnrollmentStore, private val conflictStore: TrackerImportConflictStore, - private val conflictHelper: TrackerConflictHelper -) : JobReportTypeHandler() { + private val conflictHelper: TrackerConflictHelper, + relationshipStore: RelationshipStore +) : JobReportTypeHandler(relationshipStore) { fun handleEnrollmentNotes(enrollmentUid: String, state: State) { val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST @@ -60,13 +63,15 @@ internal class JobReportEnrollmentHandler @Inject internal constructor( } } - override fun handleObject(uid: String, state: State) { + override fun handleObject(uid: String, state: State): HandleAction { conflictStore.deleteEnrollmentConflicts(uid) val handleAction = enrollmentStore.setSyncStateOrDelete(uid, state) if (handleAction !== HandleAction.Delete) { handleEnrollmentNotes(uid, state) } + + return handleAction } override fun storeConflict(errorReport: JobValidationError) { @@ -79,4 +84,8 @@ internal class JobReportEnrollmentHandler @Inject internal constructor( .build() ) } + + override fun getRelatedRelationships(uid: String): List { + return relationshipStore.getRelationshipsByItem(RelationshipHelper.enrollmentItem(uid)).mapNotNull { it.uid() } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt index fb90ba60f2..60fcbaa82c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportEventHandler.kt @@ -40,6 +40,8 @@ import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.note.NoteTableInfo +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore @Reusable internal class JobReportEventHandler @Inject internal constructor( @@ -47,8 +49,9 @@ internal class JobReportEventHandler @Inject internal constructor( private val conflictStore: TrackerImportConflictStore, private val eventStore: EventStore, private val enrollmentStore: EnrollmentStore, - private val conflictHelper: TrackerConflictHelper -) : JobReportTypeHandler() { + private val conflictHelper: TrackerConflictHelper, + relationshipStore: RelationshipStore +) : JobReportTypeHandler(relationshipStore) { fun handleEventNotes(eventUid: String, state: State) { val newNoteState = if (state == State.SYNCED) State.SYNCED else State.TO_POST @@ -62,13 +65,15 @@ internal class JobReportEventHandler @Inject internal constructor( } } - override fun handleObject(uid: String, state: State) { + override fun handleObject(uid: String, state: State): HandleAction { conflictStore.deleteEventConflicts(uid) val handleAction = eventStore.setSyncStateOrDelete(uid, state) if (handleAction !== HandleAction.Delete) { handleEventNotes(uid, state) } + + return handleAction } override fun storeConflict(errorReport: JobValidationError) { @@ -85,4 +90,8 @@ internal class JobReportEventHandler @Inject internal constructor( .build() ) } + + override fun getRelatedRelationships(uid: String): List { + return relationshipStore.getRelationshipsByItem(RelationshipHelper.eventItem(uid)).mapNotNull { it.uid() } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt index 735c8c6a77..fb737e4a2e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt @@ -28,20 +28,27 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.relationship.RelationshipHelper import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import javax.inject.Inject @Reusable internal class JobReportRelationshipHandler @Inject internal constructor( - private val relationshipStore: RelationshipStore -) : JobReportTypeHandler() { + relationshipStore: RelationshipStore +) : JobReportTypeHandler(relationshipStore) { - override fun handleObject(uid: String, state: State) { - relationshipStore.setSyncStateOrDelete(uid, state) + override fun handleObject(uid: String, state: State): HandleAction { + return relationshipStore.setSyncStateOrDelete(uid, state) } override fun storeConflict(errorReport: JobValidationError) { } + + override fun getRelatedRelationships(uid: String): List { + return emptyList() + } + } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt index fc984e6ce1..0f84879d36 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -28,22 +28,26 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable -import javax.inject.Inject +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore +import javax.inject.Inject @Reusable internal class JobReportTrackedEntityHandler @Inject internal constructor( private val conflictStore: TrackerImportConflictStore, private val trackedEntityStore: TrackedEntityInstanceStore, - private val conflictHelper: TrackerConflictHelper -) : JobReportTypeHandler() { + private val conflictHelper: TrackerConflictHelper, + relationshipStore: RelationshipStore +) : JobReportTypeHandler(relationshipStore) { - override fun handleObject(uid: String, state: State) { + override fun handleObject(uid: String, state: State): HandleAction { conflictStore.deleteTrackedEntityConflicts(uid) - trackedEntityStore.setSyncStateOrDelete(uid, state) + return trackedEntityStore.setSyncStateOrDelete(uid, state) } override fun storeConflict(errorReport: JobValidationError) { @@ -53,4 +57,8 @@ internal class JobReportTrackedEntityHandler @Inject internal constructor( .trackedEntityInstance(errorReport.uid).build() ) } + + override fun getRelatedRelationships(uid: String): List { + return relationshipStore.getRelationshipsByItem(RelationshipHelper.teiItem(uid)).mapNotNull { it.uid() } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt index de8bf9ef90..1b6c18aea0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTypeHandler.kt @@ -27,12 +27,20 @@ */ package org.hisp.dhis.android.core.tracker.importer.internal +import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore -internal abstract class JobReportTypeHandler { +internal abstract class JobReportTypeHandler constructor( + protected val relationshipStore: RelationshipStore +) { fun handleSuccess(uid: String) { - handleObject(uid, State.SYNCED) + val handleAction = handleObject(uid, State.SYNCED) + + if (handleAction === HandleAction.Delete) { + getRelatedRelationships(uid).forEach { relationshipStore.delete(it) } + } } fun handleError(errorReport: JobValidationError) { @@ -40,6 +48,7 @@ internal abstract class JobReportTypeHandler { storeConflict(errorReport) } - abstract fun handleObject(uid: String, state: State) + abstract fun handleObject(uid: String, state: State): HandleAction abstract fun storeConflict(errorReport: JobValidationError) + abstract fun getRelatedRelationships(uid: String): List } From 596809cfb98a4c074025b01e8a86d5051e5ef2a3 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 29 Jul 2021 13:40:05 +0200 Subject: [PATCH 234/308] [ANDROSDK-1344] Ktlin, PMD --- .../DataStatePropagatorIntegrationShould.kt | 6 ++-- .../hisp/dhis/android/core/event/Event.java | 2 +- .../core/event/NewTrackerImporterEvent.java | 2 +- .../android/core/event/internal/EventStore.kt | 3 +- .../core/event/internal/EventStoreImpl.kt | 32 +++++++++++-------- .../RelationshipCollectionRepository.java | 1 - .../internal/RelationshipStore.kt | 8 +++-- .../internal/RelationshipStoreImpl.kt | 32 +++++++++++-------- ...porterTrackedEntityPostPayloadGenerator.kt | 4 +-- ...erTrackedEntityPostPayloadGeneratorTask.kt | 2 +- ...erImporterTrackedEntityPostStateManager.kt | 2 +- .../internal/JobReportRelationshipHandler.kt | 6 ++-- .../internal/JobReportTrackedEntityHandler.kt | 2 +- ...edEntityInstanceTrackerImporterPostCall.kt | 4 +-- 14 files changed, 57 insertions(+), 49 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt index 2650832e0d..a58e57d75c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorIntegrationShould.kt @@ -77,8 +77,10 @@ class DataStatePropagatorIntegrationShould : BaseMockIntegrationTestFullDispatch relationshipStore = RelationshipStoreImpl.create(d2.databaseAdapter()) relationshipItemStore = RelationshipItemStoreImpl.create(d2.databaseAdapter()) - propagator = DataStatePropagatorImpl(trackedEntityInstanceStore, enrollmentStore, - eventStore, relationshipStore, relationshipItemStore) + propagator = DataStatePropagatorImpl( + trackedEntityInstanceStore, enrollmentStore, + eventStore, relationshipStore, relationshipItemStore + ) } @Test diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java index 768e03c091..8206ad33e5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java @@ -66,7 +66,7 @@ @AutoValue @JsonDeserialize(builder = AutoValue_Event.Builder.class) -@SuppressWarnings({"PMD.GodClass"}) +@SuppressWarnings({"PMD.GodClass", "PMD.ExcessivePublicCount", "PMD.ExcessiveImports"}) public abstract class Event extends BaseDeletableDataObject implements ObjectWithUidInterface { @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java index c265975d36..68888ff487 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java @@ -62,7 +62,7 @@ @AutoValue @JsonDeserialize(builder = AutoValue_NewTrackerImporterEvent.Builder.class) -@SuppressWarnings({"PMD.GodClass"}) +@SuppressWarnings({"PMD.GodClass", "PMD.ExcessivePublicCount"}) public abstract class NewTrackerImporterEvent extends BaseDeletableDataObject implements ObjectWithUidInterface { @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt index 91fd4c1e2d..b2d2fac0c6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStore.kt @@ -44,7 +44,6 @@ internal interface EventStore : IdentifiableDeletableDataObjectStore { includeDeleted: Boolean ): List - fun countEventsForEnrollment(enrollmentUid: String, includeDeleted: Boolean): Int fun countTeisWhereEvents(whereClause: String): Int @@ -54,4 +53,4 @@ internal interface EventStore : IdentifiableDeletableDataObjectStore { fun setAggregatedSyncState(uid: String, state: State): Int fun selectAggregatedSyncStateWhere(whereClause: String): List -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt index f191d40faa..6bddf81a30 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventStoreImpl.kt @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.event.internal import android.content.ContentValues import android.database.Cursor +import java.util.* import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -44,8 +45,8 @@ import org.hisp.dhis.android.core.common.State.Companion.uploadableStates import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.EventTableInfo -import java.util.* +@Suppress("TooManyFunctions") internal class EventStoreImpl private constructor( databaseAdapter: DatabaseAdapter, builder: SQLStatementBuilderImpl, @@ -56,7 +57,9 @@ internal class EventStoreImpl private constructor( override fun queryEventsAttachedToEnrollmentToPost(): Map> { val eventsAttachedToEnrollmentsQuery = WhereClauseBuilder() .appendIsNotNullValue(EventTableInfo.Columns.ENROLLMENT) - .appendInKeyStringValues(EventTableInfo.Columns.SYNC_STATE, asStringList(*uploadableStates())).build() + .appendInKeyStringValues( + EventTableInfo.Columns.SYNC_STATE, asStringList(uploadableStates().toList()) + ).build() val eventList = selectWhere(eventsAttachedToEnrollmentsQuery) val eventsMap: MutableMap> = HashMap() for (event in eventList) { @@ -67,10 +70,10 @@ internal class EventStoreImpl private constructor( override fun querySingleEventsToPost(): List { val states = CollectionsHelper.commaAndSpaceSeparatedArrayValues( - CollectionsHelper.withSingleQuotationMarksArray(asStringList(*uploadableStates())) + CollectionsHelper.withSingleQuotationMarksArray(asStringList(uploadableStates().toList())) ) val singleEventsToPostQuery = QUERY_SINGLE_EVENTS + - " AND (" + EventTableInfo.Columns.SYNC_STATE + " IN (" + states + "))" + " AND (" + EventTableInfo.Columns.SYNC_STATE + " IN (" + states + "))" return eventListFromQuery(singleEventsToPostQuery) } @@ -79,7 +82,8 @@ internal class EventStoreImpl private constructor( } override fun queryOrderedForEnrollmentAndProgramStage( - enrollmentUid: String, programStageUid: String, + enrollmentUid: String, + programStageUid: String, includeDeleted: Boolean ): List { val whereClause = WhereClauseBuilder() @@ -89,8 +93,8 @@ internal class EventStoreImpl private constructor( whereClause.appendIsNullOrValue(EventTableInfo.Columns.DELETED, "0") } val query = "SELECT * FROM " + EventTableInfo.TABLE_INFO.name() + " " + - "WHERE " + whereClause.build() + - "ORDER BY " + EventTableInfo.Columns.EVENT_DATE + ", " + EventTableInfo.Columns.LAST_UPDATED + "WHERE " + whereClause.build() + + "ORDER BY " + EventTableInfo.Columns.EVENT_DATE + ", " + EventTableInfo.Columns.LAST_UPDATED return eventListFromQuery(query) } @@ -101,7 +105,7 @@ internal class EventStoreImpl private constructor( whereClause.appendIsNullOrValue(EventTableInfo.Columns.DELETED, "0") } val query = "SELECT * FROM " + EventTableInfo.TABLE_INFO.name() + " " + - "WHERE " + whereClause.build() + "WHERE " + whereClause.build() val events = eventListFromQuery(query) return events.size } @@ -109,11 +113,11 @@ internal class EventStoreImpl private constructor( override fun countTeisWhereEvents(whereClause: String): Int { val whereStatement = if (whereClause == null) "" else " WHERE $whereClause" val query = "SELECT COUNT(DISTINCT a." + EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE + ") " + - "FROM " + EnrollmentTableInfo.TABLE_INFO.name() + " a " + - "INNER JOIN " + - "(SELECT DISTINCT " + EventTableInfo.Columns.ENROLLMENT + - " FROM " + EventTableInfo.TABLE_INFO.name() + whereStatement + ") b " + - "ON a." + IdentifiableColumns.UID + " = b." + EventTableInfo.Columns.ENROLLMENT + "FROM " + EnrollmentTableInfo.TABLE_INFO.name() + " a " + + "INNER JOIN " + + "(SELECT DISTINCT " + EventTableInfo.Columns.ENROLLMENT + + " FROM " + EventTableInfo.TABLE_INFO.name() + whereStatement + ") b " + + "ON a." + IdentifiableColumns.UID + " = b." + EventTableInfo.Columns.ENROLLMENT return processCount(databaseAdapter.rawQuery(query)) } @@ -195,4 +199,4 @@ internal class EventStoreImpl private constructor( ) { cursor: Cursor? -> Event.create(cursor) } } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 09634a5701..d27485ff0c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -107,7 +107,6 @@ public Single add(Relationship relationship) { public String blockingAdd(Relationship relationship) throws D2Error { Relationship relationshipWithUid; RelationshipItem from = relationship.from(); - RelationshipItem to = relationship.to(); if (relationshipHandler.doesRelationshipExist(relationship)) { throw D2Error .builder() diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt index 7acf940d66..174349b413 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStore.kt @@ -36,6 +36,8 @@ internal interface RelationshipStore : IdentifiableDeletableDataObjectStore - fun getRelationshipsByItem(relationshipItem: RelationshipItem, - type: RelationshipConstraintType?): List -} \ No newline at end of file + fun getRelationshipsByItem( + relationshipItem: RelationshipItem, + type: RelationshipConstraintType? + ): List +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt index a93392ce49..411c22dad7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipStoreImpl.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.relationship.internal import android.database.Cursor +import java.util.* import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -35,7 +36,6 @@ import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinde import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableDeletableDataObjectStoreImpl import org.hisp.dhis.android.core.relationship.* -import java.util.* internal class RelationshipStoreImpl private constructor( databaseAdapter: DatabaseAdapter, @@ -44,7 +44,9 @@ internal class RelationshipStoreImpl private constructor( databaseAdapter, statementBuilder, BINDER, - { cursor: Cursor -> Relationship.create(cursor) }), RelationshipStore { + { cursor: Cursor -> Relationship.create(cursor) } +), + RelationshipStore { override fun getRelationshipsByItem(relationshipItem: RelationshipItem): List { val whereClause = WhereClauseBuilder() @@ -55,23 +57,25 @@ internal class RelationshipStoreImpl private constructor( .build() val queryStatement = "SELECT DISTINCT Relationship.* " + - "FROM (Relationship INNER JOIN RelationshipItem " + - "ON Relationship.uid = RelationshipItem.relationship) " + - "WHERE " + whereClause + ";" + "FROM (Relationship INNER JOIN RelationshipItem " + + "ON Relationship.uid = RelationshipItem.relationship) " + + "WHERE " + whereClause + ";" val relationships: MutableList = ArrayList() addObjectsToCollection(databaseAdapter.rawQuery(queryStatement), relationships) return relationships } - override fun getRelationshipsByItem(relationshipItem: RelationshipItem, - type: RelationshipConstraintType?): List { + override fun getRelationshipsByItem( + relationshipItem: RelationshipItem, + type: RelationshipConstraintType? + ): List { val relationshipTable = RelationshipTableInfo.TABLE_INFO.name() val itemTable = RelationshipItemTableInfo.TABLE_INFO.name() val builder = WhereClauseBuilder() .appendKeyStringValue( - "${itemTable}.${relationshipItem.elementType()}", + "$itemTable.${relationshipItem.elementType()}", relationshipItem.elementUid() ) @@ -80,16 +84,16 @@ internal class RelationshipStoreImpl private constructor( builder.build() } else { builder.appendKeyStringValue( - "${itemTable}.${RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE}", + "$itemTable.${RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE}", type.name ).build() } val queryStatement = "SELECT DISTINCT $relationshipTable.* " + - "FROM ($relationshipTable INNER JOIN $itemTable " + - "ON $relationshipTable.${RelationshipTableInfo.Columns.UID} = " + - "$itemTable.${RelationshipItemTableInfo.Columns.RELATIONSHIP}) " + - "WHERE " + whereClause + ";" + "FROM ($relationshipTable INNER JOIN $itemTable " + + "ON $relationshipTable.${RelationshipTableInfo.Columns.UID} = " + + "$itemTable.${RelationshipItemTableInfo.Columns.RELATIONSHIP}) " + + "WHERE " + whereClause + ";" val relationships: MutableList = ArrayList() addObjectsToCollection(databaseAdapter.rawQuery(queryStatement), relationships) @@ -113,4 +117,4 @@ internal class RelationshipStoreImpl private constructor( return RelationshipStoreImpl(databaseAdapter, statementBuilder) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt index 0925ceff64..747bfe0df1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGenerator.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Transformer @@ -46,7 +47,6 @@ import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityAttributeValueTransformer import org.hisp.dhis.android.core.trackedentity.NewTrackerImporterTrackedEntityDataValueTransformer import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject internal constructor( @@ -110,7 +110,7 @@ internal class NewTrackerImporterTrackedEntityPostPayloadGenerator @Inject inter val relationshipsTransformer = NewTrackerImporterRelationshipTransformer() return relationships .filter { it.from()?.elementUid() != null } - .groupBy( { it.from()?.elementUid()!! }, { relationshipsTransformer.transform(it) }) + .groupBy({ it.from()?.elementUid()!! }, { relationshipsTransformer.transform(it) }) } private fun transformMap( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt index abc9e1fb27..04340b5522 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostPayloadGeneratorTask.kt @@ -28,13 +28,13 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.NewTrackerImporterEnrollment import org.hisp.dhis.android.core.event.NewTrackerImporterEvent import org.hisp.dhis.android.core.note.NewTrackerImporterNote import org.hisp.dhis.android.core.relationship.NewTrackerImporterRelationship import org.hisp.dhis.android.core.trackedentity.* -import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostPayloadGeneratorTask @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt index 26b29763b2..86c3160813 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterTrackedEntityPostStateManager.kt @@ -28,11 +28,11 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.event.internal.EventStore import org.hisp.dhis.android.core.relationship.internal.RelationshipStore -import javax.inject.Inject @Reusable internal class NewTrackerImporterTrackedEntityPostStateManager @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt index fb737e4a2e..b0af70a89a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportRelationshipHandler.kt @@ -28,11 +28,10 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State -import org.hisp.dhis.android.core.relationship.RelationshipHelper import org.hisp.dhis.android.core.relationship.internal.RelationshipStore -import javax.inject.Inject @Reusable internal class JobReportRelationshipHandler @Inject internal constructor( @@ -43,12 +42,11 @@ internal class JobReportRelationshipHandler @Inject internal constructor( return relationshipStore.setSyncStateOrDelete(uid, state) } + @Suppress("EmptyFunctionBlock") override fun storeConflict(errorReport: JobValidationError) { - } override fun getRelatedRelationships(uid: String): List { return emptyList() } - } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt index 0f84879d36..307f0e5e1b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportTrackedEntityHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore @@ -35,7 +36,6 @@ import org.hisp.dhis.android.core.relationship.RelationshipHelper import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore -import javax.inject.Inject @Reusable internal class JobReportTrackedEntityHandler @Inject internal constructor( diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt index 25f505ddf2..4ef21386b4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/TrackedEntityInstanceTrackerImporterPostCall.kt @@ -30,6 +30,8 @@ package org.hisp.dhis.android.core.tracker.importer.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.Single +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.handlers.internal.Handler @@ -39,8 +41,6 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterPayload import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostPayloadGenerator import org.hisp.dhis.android.core.trackedentity.internal.NewTrackerImporterTrackedEntityPostStateManager -import java.util.* -import javax.inject.Inject @Reusable internal class TrackedEntityInstanceTrackerImporterPostCall @Inject internal constructor( From b7dfd11040450966156b086b14c7117aadd7fd0d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 29 Jul 2021 14:47:28 +0200 Subject: [PATCH 235/308] [ANDROSDK-1344] Notifiy deleted objects properly --- .../common/internal/DataStatePropagator.kt | 6 ++- .../internal/DataStatePropagatorImpl.kt | 54 +++++++++++-------- .../common/internal/DataStateUidHolder.kt | 7 +++ .../importer/internal/JobReportHandler.kt | 8 +-- 4 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStateUidHolder.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt index 56085d0bb2..b6fbff7b19 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagator.kt @@ -62,10 +62,12 @@ internal interface DataStatePropagator { fun refreshEventAggregatedSyncState(eventUid: String) - fun refreshAggregatedSyncStatesCausedBy( + fun refreshAggregatedSyncStates(uidHolder: DataStateUidHolder) + + fun getRelatedUids( trackedEntityInstanceUids: List, enrollmentUids: List, eventUids: List, relationshipUids: List - ) + ): DataStateUidHolder } diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index a003872c49..190cd5ec51 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -28,8 +28,6 @@ package org.hisp.dhis.android.core.common.internal import dagger.Reusable -import java.util.* -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment @@ -48,6 +46,8 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore +import java.util.* +import javax.inject.Inject @Reusable @Suppress("TooManyFunctions") @@ -273,36 +273,46 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } } - override fun refreshAggregatedSyncStatesCausedBy( + override fun refreshAggregatedSyncStates(uidHolder: DataStateUidHolder) { + uidHolder.events.forEach { + refreshEventAggregatedSyncState(it) + } + + uidHolder.enrollments.forEach { + refreshEnrollmentAggregatedSyncState(it) + } + + uidHolder.trackedEntities.forEach { + refreshTrackedEntityInstanceAggregatedSyncState(it) + } + } + + override fun getRelatedUids( trackedEntityInstanceUids: List, enrollmentUids: List, eventUids: List, relationshipUids: List - ) { - eventUids.forEach { - refreshEventAggregatedSyncState(it) - } - + ): DataStateUidHolder { val enrollmentsFromEvents = eventStore.selectByUids(eventUids).mapNotNull { it.enrollment() } val enrollments = enrollmentStore.selectByUids(enrollmentUids + enrollmentsFromEvents) - enrollments.forEach { - refreshEnrollmentAggregatedSyncState(it.uid()) - } - val teiUids = trackedEntityInstanceUids + enrollments.mapNotNull { it.trackedEntityInstance() } - teiUids.forEach { - refreshTrackedEntityInstanceAggregatedSyncState(it) - } + val trackedEntitiesFromEnrollments = enrollments.mapNotNull { it.trackedEntityInstance() } - relationshipUids.forEach { - val item = relationshipItemStore.getForRelationshipUidAndConstraintType(it, RelationshipConstraintType.FROM) - when { - item.hasEvent() -> refreshEventAggregatedSyncState(item.elementUid()) - item.hasEnrollment() -> refreshEnrollmentAggregatedSyncState(item.elementUid()) - item.hasTrackedEntityInstance() -> refreshTrackedEntityInstanceAggregatedSyncState(item.elementUid()) - } + val relationshipItems = relationshipUids.map { + relationshipItemStore.getForRelationshipUidAndConstraintType(it, RelationshipConstraintType.FROM) } + + return DataStateUidHolder( + events = eventUids + + relationshipItems.filter { it.hasEvent() }.map { it.elementUid() }, + enrollments = enrollmentUids + + enrollmentsFromEvents + + relationshipItems.filter { it.hasEnrollment() }.map { it.elementUid() }, + trackedEntities = trackedEntityInstanceUids + + trackedEntitiesFromEnrollments + + relationshipItems.filter { it.hasTrackedEntityInstance() }.map { it.elementUid() } + ) } private fun getAggregatedSyncState(states: List): State { diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStateUidHolder.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStateUidHolder.kt new file mode 100644 index 0000000000..1870b270ad --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStateUidHolder.kt @@ -0,0 +1,7 @@ +package org.hisp.dhis.android.core.common.internal + +data class DataStateUidHolder( + val trackedEntities: List, + val enrollments: List, + val events: List +) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt index 821ac3cd73..870fbea159 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobReportHandler.kt @@ -31,6 +31,7 @@ import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.common.internal.DataStateUidHolder import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.ENROLLMENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.EVENT import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterObjectType.RELATIONSHIP @@ -47,12 +48,13 @@ internal class JobReportHandler @Inject internal constructor( fun handle(o: JobReport, jobObjects: List) { val jobObjectsMap = jobObjects.groupBy { jo -> Pair(jo.trackerType(), jo.objectUid()) } + val relatedUids = getRelatedUids(jobObjects) handleErrors(o, jobObjectsMap) handleSuccesses(o, jobObjectsMap) handleNotPresentObjects(o, jobObjects) - refreshAggregatedSyncStates(jobObjects) + dataStatePropagator.refreshAggregatedSyncStates(relatedUids) } private fun handleErrors( @@ -113,8 +115,8 @@ internal class JobReportHandler @Inject internal constructor( .forEach { typeHandler.handleSuccess(it.uid) } } - private fun refreshAggregatedSyncStates(jobObjects: List) { - dataStatePropagator.refreshAggregatedSyncStatesCausedBy( + private fun getRelatedUids(jobObjects: List): DataStateUidHolder { + return dataStatePropagator.getRelatedUids( jobObjects.filter { it.trackerType() == TRACKED_ENTITY }.map { it.objectUid() }, jobObjects.filter { it.trackerType() == ENROLLMENT }.map { it.objectUid() }, jobObjects.filter { it.trackerType() == EVENT }.map { it.objectUid() }, From 928f7fb0b44b90d36b57de8b68f5cf5604d9537b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 29 Jul 2021 14:49:58 +0200 Subject: [PATCH 236/308] [DEVELOP] Revert "feat: [ANDROAPP-2275] Display and create event to tei relationships" This reverts commit 5c8a0da138c625576dad90a55816d455b2104eab. --- .../RelationshipCollectionRepository.java | 2 +- .../core/relationship/RelationshipHelper.java | 9 ----- .../RelationshipTypeCollectionRepository.java | 34 ++----------------- 3 files changed, 3 insertions(+), 42 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 16f27417ad..61200edb63 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -115,7 +115,7 @@ public String blockingAdd(Relationship relationship) throws D2Error { .errorCode(D2ErrorCode.CANT_CREATE_EXISTING_OBJECT) .errorDescription("Tried to create already existing Relationship: " + relationship) .build(); - } else if (from == null || to == null || !to.hasTrackedEntityInstance()) { + } else if (from == null || !from.hasTrackedEntityInstance() || to == null || !to.hasTrackedEntityInstance()) { throw D2Error .builder() .errorComponent(D2ErrorComponent.SDK) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java index 38de86a49e..b8b286bdb8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java @@ -77,15 +77,6 @@ public static Relationship teiToTeiRelationship(String fromUid, String toUid, St .build(); } - public static Relationship eventToTeiRelationship(String fromEventUid, String toTeiUid, String relationshipTypeUid){ - return Relationship.builder() - .uid(new UidGeneratorImpl().generate()) - .from(RelationshipHelper.eventItem(fromEventUid)) - .to(RelationshipHelper.teiItem(toTeiUid)) - .relationshipType(relationshipTypeUid) - .build(); - } - public static boolean areItemsEqual(RelationshipItem a, RelationshipItem b) { return equalsConsideringNull(a.event(), b.event()) && equalsConsideringNull(a.enrollment(), b.enrollment()) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java index 40e058a26d..2267d1ee38 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java @@ -36,10 +36,6 @@ import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; import org.hisp.dhis.android.core.common.IdentifiableColumns; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.EventCollectionRepository; -import org.hisp.dhis.android.core.program.ProgramStage; -import org.hisp.dhis.android.core.program.ProgramStageCollectionRepository; import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields; import java.util.Map; @@ -52,15 +48,12 @@ public final class RelationshipTypeCollectionRepository extends ReadOnlyIdentifiableCollectionRepositoryImpl { - private EventCollectionRepository eventCollectionRepository; @Inject RelationshipTypeCollectionRepository(final IdentifiableObjectStore store, - final EventCollectionRepository eventCollectionRepository, final Map> childrenAppenders, final RepositoryScope scope) { super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, - s -> new RelationshipTypeCollectionRepository(store,eventCollectionRepository, childrenAppenders, s))); - this.eventCollectionRepository = eventCollectionRepository; + s -> new RelationshipTypeCollectionRepository(store, childrenAppenders, s))); } public RelationshipTypeCollectionRepository byConstraint(@NonNull RelationshipEntityType relationshipEntityType, @@ -82,19 +75,6 @@ public RelationshipTypeCollectionRepository byConstraint( RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, relationshipConstraintType)); } - public RelationshipTypeCollectionRepository byConstraint( - @NonNull String eventUid - ) { - Event event = eventCollectionRepository.uid(eventUid).blockingGet(); - String programStageUid = event.programStage(); - String programUid = event.program(); - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - constraintClauseBuilder(programUid, programStageUid) - ); - } - public RelationshipTypeCollectionRepository withConstraints() { return cf.withChild(RelationshipTypeFields.CONSTRAINTS); } @@ -106,17 +86,7 @@ private WhereClauseBuilder constraintClauseBuilder(RelationshipEntityType relati RelationshipConstraintTableInfo.Columns.RELATIONSHIP_ENTITY, relationshipEntityType) .appendKeyStringValue(getRelationshipEntityColumn(relationshipEntityType), relationshipEntityUid); } - - private WhereClauseBuilder constraintClauseBuilder(String programUid, String programStageUid) { - return new WhereClauseBuilder() - .appendComplexQuery( - new WhereClauseBuilder() - .appendOrKeyStringValue(RelationshipConstraintTableInfo.Columns.PROGRAM, programUid) - .appendOrKeyStringValue(RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE, programStageUid) - .build() - ); - } - + private String getRelationshipEntityColumn(@NonNull RelationshipEntityType relationshipEntityType) { switch (relationshipEntityType) { case TRACKED_ENTITY_INSTANCE: From 9cc3e340eacf0eb77e057bce06cfbdac12f7d208 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 29 Jul 2021 14:47:56 +0200 Subject: [PATCH 237/308] [ANDROSDK-1344] Fix emptyness of NewTrackerImporterPayload --- .../core/trackedentity/internal/NewTrackerImporterPayload.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt index 01fb74cb3a..6c84b61668 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/NewTrackerImporterPayload.kt @@ -39,6 +39,6 @@ internal data class NewTrackerImporterPayload( val relationships: MutableList = mutableListOf() ) { fun isEmpty(): Boolean { - return trackedEntities.isEmpty() && enrollments.isEmpty() && events.isEmpty() + return trackedEntities.isEmpty() && enrollments.isEmpty() && events.isEmpty() && relationships.isEmpty() } } From 46fce856f0b93c64d26947d6f0b1f851a82398dd Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 30 Jul 2021 10:56:16 +0200 Subject: [PATCH 238/308] [androsdk-1406] Add FK between Visualization and AnalyticsDhisVisualization tables --- core/src/main/assets/migrations/107.sql | 6 ++++++ core/src/main/assets/snapshots/{106.sql => 107.sql} | 2 +- .../arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 core/src/main/assets/migrations/107.sql rename core/src/main/assets/snapshots/{106.sql => 107.sql} (99%) diff --git a/core/src/main/assets/migrations/107.sql b/core/src/main/assets/migrations/107.sql new file mode 100644 index 0000000000..b616f6627b --- /dev/null +++ b/core/src/main/assets/migrations/107.sql @@ -0,0 +1,6 @@ +# Add foreign key for visualization(uid) + +ALTER TABLE AnalyticsDhisVisualization RENAME TO AnalyticsDhisVisualization_Old; +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT, FOREIGN KEY (uid) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +INSERT INTO AnalyticsDhisVisualization (_id, uid, scopeUid, scope, groupUid, groupName, timestamp) SELECT _id, uid, scopeUid, scope, groupUid, groupName, timestamp FROM AnalyticsDhisVisualization_Old; +DROP TABLE IF EXISTS AnalyticsDhisVisualization_Old; \ No newline at end of file diff --git a/core/src/main/assets/snapshots/106.sql b/core/src/main/assets/snapshots/107.sql similarity index 99% rename from core/src/main/assets/snapshots/106.sql rename to core/src/main/assets/snapshots/107.sql index d6964e170e..03995c4234 100644 --- a/core/src/main/assets/snapshots/106.sql +++ b/core/src/main/assets/snapshots/107.sql @@ -111,7 +111,7 @@ CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMEN CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); -CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT); +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT, FOREIGN KEY (uid) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index a5251c21c5..a1344e8626 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 106; + static final int VERSION = 107; private final AssetManager assetManager; private final int targetVersion; From 449e11bd2fb3b7501f49322dd698b7f273b4ca87 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 30 Jul 2021 10:58:36 +0200 Subject: [PATCH 239/308] [androsdk-1406] Add FK between Visualization and AnalyticsDhisVisualization tables --- core/src/main/assets/migrations/107.sql | 2 +- core/src/main/assets/snapshots/107.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/assets/migrations/107.sql b/core/src/main/assets/migrations/107.sql index b616f6627b..f4453f5c59 100644 --- a/core/src/main/assets/migrations/107.sql +++ b/core/src/main/assets/migrations/107.sql @@ -1,6 +1,6 @@ # Add foreign key for visualization(uid) ALTER TABLE AnalyticsDhisVisualization RENAME TO AnalyticsDhisVisualization_Old; -CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT, FOREIGN KEY (uid) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT, FOREIGN KEY (uid) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); INSERT INTO AnalyticsDhisVisualization (_id, uid, scopeUid, scope, groupUid, groupName, timestamp) SELECT _id, uid, scopeUid, scope, groupUid, groupName, timestamp FROM AnalyticsDhisVisualization_Old; DROP TABLE IF EXISTS AnalyticsDhisVisualization_Old; \ No newline at end of file diff --git a/core/src/main/assets/snapshots/107.sql b/core/src/main/assets/snapshots/107.sql index 03995c4234..a7f205dfcd 100644 --- a/core/src/main/assets/snapshots/107.sql +++ b/core/src/main/assets/snapshots/107.sql @@ -111,7 +111,7 @@ CREATE TABLE DataElementAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMEN CREATE TABLE ProgramAttributeValueLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, program TEXT NOT NULL, attribute TEXT NOT NULL, value TEXT, FOREIGN KEY (program) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (attribute) REFERENCES Attribute (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, UNIQUE (program, attribute)); CREATE TABLE TrackerJobObject (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackerType TEXT NOT NULL, objectUid TEXT NOT NULL, jobUid TEXT NOT NULL, lastUpdated TEXT NOT NULL); CREATE TABLE DataValueConflict (_id INTEGER PRIMARY KEY AUTOINCREMENT, conflict TEXT, value TEXT, attributeOptionCombo TEXT, categoryOptionCombo TEXT, dataElement TEXT, period TEXT, orgUnit TEXT, errorCode TEXT, status TEXT, created TEXT, displayDescription TEXT); -CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT, FOREIGN KEY (uid) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL, scopeUid TEXT, scope TEXT, groupUid TEXT, groupName TEXT, timestamp TEXT, FOREIGN KEY (uid) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); From 4963062f48dbecb8c30bbcebbd6bc69a931ce1ba Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 30 Jul 2021 10:59:19 +0200 Subject: [PATCH 240/308] [ANDROSDK-1410] Silent Job report NOT_FOUND error --- .../android/core/maintenance/D2ErrorCode.java | 1 + .../tracker/importer/internal/JobQueryCall.kt | 5 +- .../importer/internal/JobQueryErrorCatcher.kt | 46 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java b/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java index f631587fe9..2e55cbff7a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java +++ b/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java @@ -50,6 +50,7 @@ public enum D2ErrorCode { FILE_NOT_FOUND, FAIL_RESIZING_IMAGE, IMPOSSIBLE_TO_GENERATE_COORDINATES, + JOB_REPORT_NOT_AVAILABLE, LOGIN_USERNAME_NULL, LOGIN_PASSWORD_NULL, MIGHT_BE_RUNNING_LOW_ON_AVAILABLE_VALUES, diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt index c0904aa48d..20eef19d96 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryCall.kt @@ -95,7 +95,10 @@ internal class JobQueryCall @Inject internal constructor( } private fun downloadAndHandle(jobId: String, jobObjects: List) { - val jobReport = apiCallExecutor.executeObjectCall(service.getJobReport(jobId)) + val jobReport = apiCallExecutor.executeObjectCallWithErrorCatcher( + service.getJobReport(jobId), + JobQueryErrorCatcher() + ) trackerJobObjectStore.deleteWhere(byJobIdClause(jobId)) handler.handle(jobReport, jobObjects) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt new file mode 100644 index 0000000000..13d01bf289 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2021, 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.core.tracker.importer.internal + +import org.hisp.dhis.android.core.arch.api.executors.internal.APICallErrorCatcher +import org.hisp.dhis.android.core.maintenance.D2ErrorCode +import retrofit2.Response + +class JobQueryErrorCatcher : APICallErrorCatcher { + + override fun mustBeStored(): Boolean = false + + override fun catchError(response: Response<*>): D2ErrorCode? { + return if (response.code() == 404) { + D2ErrorCode.JOB_REPORT_NOT_AVAILABLE + } else { + null + } + } +} \ No newline at end of file From e5890c8fe3ad008bc19f484701401b6f33dfdcff Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 30 Jul 2021 11:29:52 +0200 Subject: [PATCH 241/308] [ANDROSDK-1410] Detekt --- .../core/tracker/importer/internal/JobQueryErrorCatcher.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt index 13d01bf289..22cc4ce936 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/tracker/importer/internal/JobQueryErrorCatcher.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.tracker.importer.internal +import java.net.HttpURLConnection import org.hisp.dhis.android.core.arch.api.executors.internal.APICallErrorCatcher import org.hisp.dhis.android.core.maintenance.D2ErrorCode import retrofit2.Response @@ -37,10 +38,10 @@ class JobQueryErrorCatcher : APICallErrorCatcher { override fun mustBeStored(): Boolean = false override fun catchError(response: Response<*>): D2ErrorCode? { - return if (response.code() == 404) { + return if (response.code() == HttpURLConnection.HTTP_NOT_FOUND) { D2ErrorCode.JOB_REPORT_NOT_AVAILABLE } else { null } } -} \ No newline at end of file +} From ce7778fa6b9215539665880db2357eebb2b726c5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 30 Jul 2021 11:32:28 +0200 Subject: [PATCH 242/308] [ANDROSDK-1344] Ktlint --- .../common/internal/DataStatePropagatorImpl.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 190cd5ec51..f85cd4c8f9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -28,6 +28,8 @@ package org.hisp.dhis.android.core.common.internal import dagger.Reusable +import java.util.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment @@ -46,8 +48,6 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore -import java.util.* -import javax.inject.Inject @Reusable @Suppress("TooManyFunctions") @@ -305,13 +305,13 @@ internal class DataStatePropagatorImpl @Inject internal constructor( return DataStateUidHolder( events = eventUids + - relationshipItems.filter { it.hasEvent() }.map { it.elementUid() }, + relationshipItems.filter { it.hasEvent() }.map { it.elementUid() }, enrollments = enrollmentUids + - enrollmentsFromEvents + - relationshipItems.filter { it.hasEnrollment() }.map { it.elementUid() }, + enrollmentsFromEvents + + relationshipItems.filter { it.hasEnrollment() }.map { it.elementUid() }, trackedEntities = trackedEntityInstanceUids + - trackedEntitiesFromEnrollments + - relationshipItems.filter { it.hasTrackedEntityInstance() }.map { it.elementUid() } + trackedEntitiesFromEnrollments + + relationshipItems.filter { it.hasTrackedEntityInstance() }.map { it.elementUid() } ) } From a338b311b14b39a07518d6d516901557eef9fbee Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 30 Jul 2021 13:58:13 +0200 Subject: [PATCH 243/308] [ANDROSDK-1408] Implement Visualization repository filters --- .../aggregated/AggregatedEntityDIModule.kt | 2 +- .../AnalyticsVisualizationsRepository.kt | 4 ++ .../aggregated/DimensionalResponse.kt | 1 + .../aggregated/GridAnalyticsResponse.kt | 1 + .../aggregated/internal/AnalyticsService.kt | 5 ++- .../AnalyticsVisualizationsRepositoryImpl.kt | 11 +++++ ...AnalyticsVisualizationsRepositoryParams.kt | 6 ++- .../AnalyticsVisualizationsService.kt | 45 ++++++++++++++----- .../mock/DimensionalResponseSamples.kt | 23 ++++++++-- .../mock/GridAnalyticsResponseSamples.kt | 18 ++++++++ .../MockAnalyticsVisualizationsRepository.kt | 11 +++++ 11 files changed, 108 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt index bee9a5b06a..4b52b3cb30 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AggregatedEntityDIModule.kt @@ -59,6 +59,6 @@ internal class AggregatedEntityDIModule { @Provides @Reusable fun emptyAnalyticsVisualizationsParam(): AnalyticsVisualizationsRepositoryParams { - return AnalyticsVisualizationsRepositoryParams(null) + return AnalyticsVisualizationsRepositoryParams(null, null, null) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt index c45b5115bd..04bbf950cb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/AnalyticsVisualizationsRepository.kt @@ -34,6 +34,10 @@ interface AnalyticsVisualizationsRepository { fun withVisualization(visualization: String): AnalyticsVisualizationsRepository + fun withPeriods(periods: List): AnalyticsVisualizationsRepository + + fun withOrganisationUnits(orgUnits: List): AnalyticsVisualizationsRepository + fun evaluate(): Single fun blockingEvaluate(): GridAnalyticsResponse diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt index a79eaa9565..55d84fbb57 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/DimensionalResponse.kt @@ -31,6 +31,7 @@ package org.hisp.dhis.android.core.analytics.aggregated data class DimensionalResponse( val metadata: Map, val dimensions: List, + val dimensionItems: Map>, val filters: List, val values: List ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt index 56e5609394..c352e24f2d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/GridAnalyticsResponse.kt @@ -32,6 +32,7 @@ data class GridAnalyticsResponse( val metadata: Map, val headers: GridHeader, val dimensions: GridDimension, + val dimensionItems: Map>, val filters: List, val values: List> ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt index c0dc1b7eb6..7cc067c9d0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsService.kt @@ -43,7 +43,9 @@ internal class AnalyticsService @Inject constructor( throw AnalyticsException.InvalidArguments("At least one dimension must be specified") } - if ((params.dimensions + params.filters).none { it.dimension == Dimension.Data }) { + val dimensionItems = params.dimensions + params.filters + + if (dimensionItems.none { it.dimension == Dimension.Data }) { throw AnalyticsException.InvalidArguments("At least one data dimension must be specified") } @@ -57,6 +59,7 @@ internal class AnalyticsService @Inject constructor( return DimensionalResponse( metadata = metadata, dimensions = dimensions, + dimensionItems = dimensionItems.groupBy { it.dimension }, filters = params.filters.map { it.id }, values = values ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt index 73d90ce71e..f98ee9af58 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryImpl.kt @@ -31,6 +31,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal import io.reactivex.Single import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse internal class AnalyticsVisualizationsRepositoryImpl @Inject constructor( @@ -42,6 +43,16 @@ internal class AnalyticsVisualizationsRepositoryImpl @Inject constructor( return updateParams { params -> params.copy(visualization = visualization) } } + override fun withPeriods(periods: List): AnalyticsVisualizationsRepository { + return updateParams { params -> params.copy(periods = periods) } + } + + override fun withOrganisationUnits( + orgUnits: List + ): AnalyticsVisualizationsRepository { + return updateParams { params -> params.copy(organisationUnits = orgUnits) } + } + override fun evaluate(): Single { return Single.fromCallable { blockingEvaluate() } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt index 89b39feae0..95f8be516f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsRepositoryParams.kt @@ -28,6 +28,10 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem + internal data class AnalyticsVisualizationsRepositoryParams( - val visualization: String? + val visualization: String?, + val periods: List?, + val organisationUnits: List? ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt index 8b31fb5995..74c5533e5e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/internal/AnalyticsVisualizationsService.kt @@ -45,7 +45,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( } val visualization = getVisualization(params.visualization) - val dimensionalResponse = getDimensionalResponse(visualization) + val dimensionalResponse = getDimensionalResponse(visualization, params) return buildGridResponse(visualization, dimensionalResponse) } @@ -59,27 +59,47 @@ internal class AnalyticsVisualizationsService @Inject constructor( ?: throw AnalyticsException.InvalidArguments("Visualization $visualizationId does not exist") } - private fun getDimensionalResponse(visualization: Visualization): DimensionalResponse { + private fun getDimensionalResponse( + visualization: Visualization, + params: AnalyticsVisualizationsRepositoryParams + ): DimensionalResponse { + var analyticsRepository = analyticsRepository val queryDimensions = (visualization.rowDimensions() ?: emptyList()) + (visualization.columnDimensions() ?: emptyList()) - dimensionHelper.getDimensionItems( - visualization, - queryDimensions - ).forEach { item -> - analyticsRepository = analyticsRepository.withDimension(item) + var queryItems = dimensionHelper.getDimensionItems(visualization, queryDimensions) + var filterItems = dimensionHelper.getDimensionItems(visualization, visualization.filterDimensions()) + + // Overwrite periods + if (!params.periods.isNullOrEmpty()) { + if (queryItems.any { it.dimension == Dimension.Period }) { + queryItems = queryItems.filterNot { it.dimension == Dimension.Period } + params.periods + } else if (filterItems.any { it.dimension == Dimension.Period }) { + filterItems = filterItems.filterNot { it.dimension == Dimension.Period } + params.periods + } else { + filterItems = filterItems + params.periods + } } - dimensionHelper.getDimensionItems( - visualization, - visualization.filterDimensions() - ).forEach { item -> - analyticsRepository = analyticsRepository.withFilter(item) + // Overwrite organisationUnits + if (!params.organisationUnits.isNullOrEmpty()) { + if (queryItems.any { it.dimension == Dimension.OrganisationUnit }) { + queryItems = + queryItems.filterNot { it.dimension == Dimension.OrganisationUnit } + params.organisationUnits + } else if (filterItems.any { it.dimension == Dimension.OrganisationUnit }) { + filterItems = + filterItems.filterNot { it.dimension == Dimension.OrganisationUnit } + params.organisationUnits + } else { + filterItems = filterItems + params.organisationUnits + } } + queryItems.forEach { analyticsRepository = analyticsRepository.withDimension(it) } + filterItems.forEach { analyticsRepository = analyticsRepository.withFilter(it) } + return analyticsRepository.blockingEvaluate() } @@ -112,6 +132,7 @@ internal class AnalyticsVisualizationsService @Inject constructor( metadata = dimensionalResponse.metadata, headers = gridHeader, dimensions = gridDimension, + dimensionItems = dimensionalResponse.dimensionItems, filters = dimensionalResponse.filters, values = gridValues ) diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt index 343ded8b4e..85956ffef9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/DimensionalResponseSamples.kt @@ -28,10 +28,7 @@ package org.hisp.dhis.android.core.analytics.aggregated.mock -import org.hisp.dhis.android.core.analytics.aggregated.Dimension -import org.hisp.dhis.android.core.analytics.aggregated.DimensionalResponse -import org.hisp.dhis.android.core.analytics.aggregated.DimensionalValue -import org.hisp.dhis.android.core.analytics.aggregated.MetadataItem +import org.hisp.dhis.android.core.analytics.aggregated.* import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.cc1 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co11 import org.hisp.dhis.android.core.analytics.aggregated.mock.AggregatedSamples.co12 @@ -56,6 +53,24 @@ object DimensionalResponseSamples { orgunit2.uid() to MetadataItem.OrganisationUnitItem(orgunit2) ), dimensions = listOf(Dimension.Data, Dimension.Category(cc1.uid()), Dimension.Period), + dimensionItems = mapOf( + Dimension.Data to listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), + DimensionItem.DataItem.DataElementItem(dataElement2.uid()) + ), + Dimension.Category(cc1.uid()) to listOf( + DimensionItem.CategoryItem(cc1.uid(), co11.uid()), + DimensionItem.CategoryItem(cc1.uid(), co12.uid()) + ), + Dimension.Period to listOf( + DimensionItem.PeriodItem.Absolute(period1.periodId()!!), + DimensionItem.PeriodItem.Absolute(period2.periodId()!!) + ), + Dimension.OrganisationUnit to listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunit1.uid()), + DimensionItem.OrganisationUnitItem.Absolute(orgunit2.uid()) + ) + ), filters = listOf(orgunit1.uid(), orgunit2.uid()), values = listOf( DimensionalValue( diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt index e5662c0818..037b4e1a34 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/GridAnalyticsResponseSamples.kt @@ -76,6 +76,24 @@ object GridAnalyticsResponseSamples { columns = listOf(Dimension.Data, Dimension.Category(cc1.uid())), rows = listOf(Dimension.Period) ), + dimensionItems = mapOf( + Dimension.Data to listOf( + DimensionItem.DataItem.DataElementItem(dataElement1.uid()), + DimensionItem.DataItem.DataElementItem(dataElement2.uid()) + ), + Dimension.Category(cc1.uid()) to listOf( + DimensionItem.CategoryItem(cc1.uid(), co11.uid()), + DimensionItem.CategoryItem(cc1.uid(), co12.uid()) + ), + Dimension.Period to listOf( + DimensionItem.PeriodItem.Absolute(period1.periodId()!!), + DimensionItem.PeriodItem.Absolute(period2.periodId()!!) + ), + Dimension.OrganisationUnit to listOf( + DimensionItem.OrganisationUnitItem.Absolute(orgunit1.uid()), + DimensionItem.OrganisationUnitItem.Absolute(orgunit2.uid()) + ) + ), filters = listOf(orgunit1.uid(), orgunit2.uid()), values = listOf( listOf( diff --git a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt index 301e8090e7..251455b5d1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/analytics/aggregated/mock/MockAnalyticsVisualizationsRepository.kt @@ -32,6 +32,7 @@ import dagger.Reusable import io.reactivex.Single import javax.inject.Inject import org.hisp.dhis.android.core.analytics.aggregated.AnalyticsVisualizationsRepository +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem import org.hisp.dhis.android.core.analytics.aggregated.GridAnalyticsResponse @Reusable @@ -41,6 +42,16 @@ class MockAnalyticsVisualizationsRepository @Inject constructor() : AnalyticsVis return MockAnalyticsVisualizationsRepository() } + override fun withPeriods(periods: List): AnalyticsVisualizationsRepository { + return MockAnalyticsVisualizationsRepository() + } + + override fun withOrganisationUnits( + orgUnits: List + ): AnalyticsVisualizationsRepository { + return MockAnalyticsVisualizationsRepository() + } + override fun evaluate(): Single { return Single.fromCallable { blockingEvaluate() } } From f3970a7fe62d6e905ab23c058093e13f84b61cc8 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 30 Jul 2021 13:58:30 +0200 Subject: [PATCH 244/308] [ANDROSDK-1408] Add integration test --- ...isualizationRepositoryIntegrationShould.kt | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt index fd4d702902..552579a31a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt @@ -29,6 +29,9 @@ package org.hisp.dhis.android.core.analytics.aggregated.internal.evaluator import com.google.common.truth.Truth.assertThat +import org.hisp.dhis.android.core.analytics.aggregated.Dimension +import org.hisp.dhis.android.core.analytics.aggregated.DimensionItem +import org.hisp.dhis.android.core.common.RelativeOrganisationUnit import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher import org.junit.Test @@ -44,6 +47,49 @@ class AnalyticsVisualizationRepositoryIntegrationShould : BaseMockIntegrationTes assertThat(result.dimensions.columns.size).isEqualTo(1) assertThat(result.dimensions.rows.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.Data]!!.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.OrganisationUnit]!!.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.Period]!!.size).isEqualTo(3) + assertThat(result.metadata).isNotEmpty() + assertThat(result.values.size).isEqualTo(3) + } + + @Test + fun evaluate_visualization_wit_periods() { + val result = d2.analyticsModule().visualizations() + .withVisualization(visualizationUid) + .withPeriods(listOf(DimensionItem.PeriodItem.Absolute("2018"))) + .blockingEvaluate() + + assertThat(result.dimensions.columns.size).isEqualTo(1) + assertThat(result.dimensions.rows.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.Data]!!.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.OrganisationUnit]!!.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.Period]).isEqualTo(listOf( + DimensionItem.PeriodItem.Absolute("2018") + )) + assertThat(result.metadata).isNotEmpty() + assertThat(result.values.size).isEqualTo(1) + } + + @Test + fun evaluate_visualization_wit_organisation_units() { + val result = d2.analyticsModule().visualizations() + .withVisualization(visualizationUid) + .withOrganisationUnits( + listOf( + DimensionItem.OrganisationUnitItem.Relative(RelativeOrganisationUnit.USER_ORGUNIT) + ) + ) + .blockingEvaluate() + + assertThat(result.dimensions.columns.size).isEqualTo(1) + assertThat(result.dimensions.rows.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.Data]!!.size).isEqualTo(1) + assertThat(result.dimensionItems[Dimension.OrganisationUnit]).isEqualTo(listOf( + DimensionItem.OrganisationUnitItem.Relative(RelativeOrganisationUnit.USER_ORGUNIT) + )) + assertThat(result.dimensionItems[Dimension.Period]!!.size).isEqualTo(3) assertThat(result.metadata).isNotEmpty() assertThat(result.values.size).isEqualTo(3) } From a3de5ab8d2b2a712eed345fdb2539e6074095e05 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 30 Jul 2021 14:08:54 +0200 Subject: [PATCH 245/308] [ANDROSDK-1408] Checkstyle --- ...csVisualizationRepositoryIntegrationShould.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt index 552579a31a..ce3ccfe243 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/analytics/aggregated/internal/evaluator/AnalyticsVisualizationRepositoryIntegrationShould.kt @@ -65,9 +65,11 @@ class AnalyticsVisualizationRepositoryIntegrationShould : BaseMockIntegrationTes assertThat(result.dimensions.rows.size).isEqualTo(1) assertThat(result.dimensionItems[Dimension.Data]!!.size).isEqualTo(1) assertThat(result.dimensionItems[Dimension.OrganisationUnit]!!.size).isEqualTo(1) - assertThat(result.dimensionItems[Dimension.Period]).isEqualTo(listOf( - DimensionItem.PeriodItem.Absolute("2018") - )) + assertThat(result.dimensionItems[Dimension.Period]).isEqualTo( + listOf( + DimensionItem.PeriodItem.Absolute("2018") + ) + ) assertThat(result.metadata).isNotEmpty() assertThat(result.values.size).isEqualTo(1) } @@ -86,9 +88,11 @@ class AnalyticsVisualizationRepositoryIntegrationShould : BaseMockIntegrationTes assertThat(result.dimensions.columns.size).isEqualTo(1) assertThat(result.dimensions.rows.size).isEqualTo(1) assertThat(result.dimensionItems[Dimension.Data]!!.size).isEqualTo(1) - assertThat(result.dimensionItems[Dimension.OrganisationUnit]).isEqualTo(listOf( - DimensionItem.OrganisationUnitItem.Relative(RelativeOrganisationUnit.USER_ORGUNIT) - )) + assertThat(result.dimensionItems[Dimension.OrganisationUnit]).isEqualTo( + listOf( + DimensionItem.OrganisationUnitItem.Relative(RelativeOrganisationUnit.USER_ORGUNIT) + ) + ) assertThat(result.dimensionItems[Dimension.Period]!!.size).isEqualTo(3) assertThat(result.metadata).isNotEmpty() assertThat(result.values.size).isEqualTo(3) From 0a1c61fb4c64ec49c0b320a57158b02995d62cfa Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 2 Aug 2021 09:07:44 +0200 Subject: [PATCH 246/308] [androsdk-1406] Update uids to match visualizations --- .../core/data/settings/AnalyticsSettingsSamples.kt | 2 +- .../resources/settings/analytics_settings_v2.json | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt index a3091e18a0..3a0a077e41 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/AnalyticsSettingsSamples.kt @@ -110,6 +110,6 @@ object AnalyticsSettingsSamples { .groupUid("123456") .scope(AnalyticsDhisVisualizationScope.HOME) .timestamp("2021-07-01T02:55:16.8770") - .uid("KgC9TdlpjZC") + .uid("PYBH8ZaAQnC") .build() } diff --git a/core/src/sharedTest/resources/settings/analytics_settings_v2.json b/core/src/sharedTest/resources/settings/analytics_settings_v2.json index 511ac1a307..7eac368845 100644 --- a/core/src/sharedTest/resources/settings/analytics_settings_v2.json +++ b/core/src/sharedTest/resources/settings/analytics_settings_v2.json @@ -68,11 +68,11 @@ "name": "Ejemplo", "visualizations": [ { - "id": "TXcKIg4LuA3", + "id": "FAFa11yFeFe", "timestamp": "2021-07-01T03:01:16.8770" }, { - "id": "eykdwnDx8ie", + "id": "PYBH8ZaAQnC", "timestamp": "2021-07-01T03:02:16.8770" } ] @@ -82,7 +82,7 @@ "name": "Otro ejemplo", "visualizations": [ { - "id": "KgC9TdlpjZC", + "id": "PYBH8ZaAQnC", "timestamp": "2021-07-01T03:04:16.8770" } ] @@ -95,7 +95,7 @@ "name": "default", "visualizations": [ { - "id": "TXcKIg4LuA3", + "id": "FAFa11yFeFe", "timestamp": "2021-07-01T02:55:16.8770" } ] @@ -109,11 +109,11 @@ "name": "default", "visualizations": [ { - "id": "eykdwnDx8ie", + "id": "PYBH8ZaAQnC", "timestamp": "2021-07-01T02:55:16.8770" }, { - "id": "KgC9TdlpjZC", + "id": "PYBH8ZaAQnC", "timestamp": "2021-07-01T02:55:16.8770" } ] From 2767cdfbbe45da16bfed91c007dff9112f0884b2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 4 Aug 2021 16:52:30 +0200 Subject: [PATCH 247/308] [androsdk-1378] Add LocalDataStore --- .../core/datastore/LocalDataStore.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java new file mode 100644 index 0000000000..1bb0606236 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore; + +import android.database.Cursor; + +import androidx.annotation.Nullable; + +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.common.CoreObject; + +@AutoValue +public abstract class LocalDataStore implements CoreObject { + + @Nullable + public abstract String key(); + + @Nullable + public abstract String value(); + + public static LocalDataStore create(Cursor cursor) { + return $AutoValue_LocalDataStore.createFromCursor(cursor); + } + + public abstract Builder toBuilder(); + + public static Builder builder() { + return new AutoValue_LocalDataStore.Builder(); + } + + @AutoValue.Builder + public static abstract class Builder { + public abstract Builder id(Long id); + + public abstract Builder key(String key); + + public abstract Builder value(String value); + + public abstract LocalDataStore build(); + } +} From 69ddb2f944fd50d43f8820ddbf08cefba9f099f7 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 4 Aug 2021 16:52:38 +0200 Subject: [PATCH 248/308] [androsdk-1378] Add LocalDataStore table info --- .../core/datastore/LocalDataStoreTableInfo.kt | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreTableInfo.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreTableInfo.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreTableInfo.kt new file mode 100644 index 0000000000..83ea923fc3 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreTableInfo.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore + +import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns + +object LocalDataStoreTableInfo { + + @JvmField + val TABLE_INFO: TableInfo = object : TableInfo() { + override fun name(): String { + return "LocalDataStore" + } + + override fun columns(): CoreColumns { + return Columns() + } + } + + class Columns : CoreColumns() { + override fun all(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + KEY, + VALUE + ) + } + + override fun whereUpdate(): Array { + return CollectionsHelper.appendInNewArray( + super.all(), + KEY + ) + } + + companion object { + const val KEY = "key" + const val VALUE = "value" + } + } +} From a36a7a03c2e0e66e678b1342564f309f35099ca7 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 4 Aug 2021 16:52:47 +0200 Subject: [PATCH 249/308] [androsdk-1378] Add LocalDataStore store --- .../datastore/internal/LocalDataStoreStore.kt | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt new file mode 100644 index 0000000000..5a633b99f4 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore.internal + +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder +import org.hisp.dhis.android.core.arch.db.stores.binders.internal.WhereStatementBinder +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithoutUidStore +import org.hisp.dhis.android.core.datastore.LocalDataStore +import org.hisp.dhis.android.core.datastore.LocalDataStoreTableInfo + +@Suppress("MagicNumber") +internal object LocalDataStoreStore { + + private val BINDER: StatementBinder = StatementBinder { o, w -> + w.bind(1, o.key()) + w.bind(2, o.value()) + } + + private val WHERE_UPDATE_BINDER = WhereStatementBinder { _: LocalDataStore, _ -> } + private val WHERE_DELETE_BINDER = WhereStatementBinder { _: LocalDataStore, _ -> } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { + return objectWithoutUidStore( + databaseAdapter, + LocalDataStoreTableInfo.TABLE_INFO, + BINDER, + WHERE_UPDATE_BINDER, + WHERE_DELETE_BINDER + ) { cursor: Cursor -> LocalDataStore.create(cursor) } + } +} From adf355a8a958fe89a50bf5b2080690ea42bf82d3 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 4 Aug 2021 16:53:07 +0200 Subject: [PATCH 250/308] [androsdk-1378] Add LocalDataStore table and migration --- core/src/main/assets/migrations/108.sql | 3 +++ core/src/main/assets/snapshots/{107.sql => 108.sql} | 1 + .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 core/src/main/assets/migrations/108.sql rename core/src/main/assets/snapshots/{107.sql => 108.sql} (99%) diff --git a/core/src/main/assets/migrations/108.sql b/core/src/main/assets/migrations/108.sql new file mode 100644 index 0000000000..7994958bf0 --- /dev/null +++ b/core/src/main/assets/migrations/108.sql @@ -0,0 +1,3 @@ +# Add local data store table + +CREATE TABLE LocalDataStore (_id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL UNIQUE, value TEXT); \ No newline at end of file diff --git a/core/src/main/assets/snapshots/107.sql b/core/src/main/assets/snapshots/108.sql similarity index 99% rename from core/src/main/assets/snapshots/107.sql rename to core/src/main/assets/snapshots/108.sql index 10ff1ea658..1e4982bb56 100644 --- a/core/src/main/assets/snapshots/107.sql +++ b/core/src/main/assets/snapshots/108.sql @@ -115,3 +115,4 @@ CREATE TABLE AnalyticsDhisVisualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, CREATE TABLE Visualization (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT NOT NULL UNIQUE, code TEXT, name TEXT, displayName TEXT, created TEXT, lastUpdated TEXT, description TEXT, displayDescription TEXT, displayFormName TEXT, type TEXT, hideTitle INTEGER, hideSubtitle INTEGER, hideEmptyColumns INTEGER, hideEmptyRows INTEGER, hideEmptyRowItems TEXT, hideLegend INTEGER, showHierarchy INTEGER, rowTotals INTEGER, rowSubTotals INTEGER, colTotals INTEGER, colSubTotals INTEGER, showDimensionLabels INTEGER, percentStackedValues INTEGER, noSpaceBetweenColumns INTEGER, skipRounding INTEGER, displayDensity TEXT, digitGroupSeparator TEXT, relativePeriods TEXT, filterDimensions TEXT, rowDimensions TEXT, columnDimensions TEXT, organisationUnitLevels TEXT, userOrganisationUnit INTEGER, userOrganisationUnitChildren INTEGER, userOrganisationUnitGrandChildren INTEGER, organisationUnits TEXT, periods TEXT); CREATE TABLE VisualizationCategoryDimensionLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, category TEXT NOT NULL, categoryOption TEXT NOT NULL, FOREIGN KEY (category) REFERENCES Category (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (categoryOption) REFERENCES CategoryOption (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE DataDimensionItem (_id INTEGER PRIMARY KEY AUTOINCREMENT, visualization TEXT NOT NULL, dataDimensionItemType TEXT, indicator TEXT, dataElement TEXT, dataElementOperand TEXT, reportingRate TEXT, programIndicator TEXT, programDataElement TEXT, programAttribute TEXT, validationRule TEXT, FOREIGN KEY (visualization) REFERENCES Visualization (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); +CREATE TABLE LocalDataStore (_id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT NOT NULL UNIQUE, value TEXT); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index a1344e8626..d9bd3a6106 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 107; + static final int VERSION = 108; private final AssetManager assetManager; private final int targetVersion; From 4cb381e6b3adaa25dc3a876a70b1cfb5e193dca8 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 5 Aug 2021 15:50:52 +0200 Subject: [PATCH 251/308] [androsdk-1378] Add LocalDataStoreEntityDIModule --- .../internal/LocalDataStoreEntityDIModule.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt new file mode 100644 index 0000000000..80e8ac2c35 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore.internal + +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.datastore.LocalDataStore + +@Module +internal class LocalDataStoreEntityDIModule { + + @Provides + @Reusable + fun store(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { + return LocalDataStoreStore.create(databaseAdapter) + } +} From 5869b4b41790b4a3ee3eb007d38cb33a902701ef Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 5 Aug 2021 15:51:17 +0200 Subject: [PATCH 252/308] [androsdk-1378] Add ReadWriteWithoutUidCollectionRepository --- ...adWriteWithoutUidCollectionRepository.java | 56 +++++++++++++ ...iteWithoutUidCollectionRepositoryImpl.java | 79 +++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java new file mode 100644 index 0000000000..a2e0edb6f2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.repositories.collection; + +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.maintenance.D2Error; + +import io.reactivex.Single; + +public interface ReadWriteWithoutUidCollectionRepository + extends ReadOnlyCollectionRepository { + + /** + * Adds a new object to the given collection in an asynchronous way. + * It returns a {@code Single}. + * @param m the object to add + * @return the Single with a Result + */ + Single add(M m); + + /** + * Adds a new object to the given collection in a synchronous way. + * It blocks the current thread and returns the generated UID. + * Adds a new object to the given collection in an asynchronous way. + * It returns a {@code Single}. Important: this is a blocking method + * and it should not be executed in the main thread. Consider the asynchronous version {@link #add}. + * @param m the object to add + * @return the Single with a Result + */ + M blockingAdd(M m) throws D2Error; +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java new file mode 100644 index 0000000000..e2901b75b1 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004-2021, 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.core.arch.repositories.collection.internal; + +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; +import org.hisp.dhis.android.core.arch.repositories.collection.ReadOnlyCollectionRepository; +import org.hisp.dhis.android.core.arch.repositories.collection.ReadWriteWithoutUidCollectionRepository; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; +import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; +import org.hisp.dhis.android.core.common.CoreObject; +import org.hisp.dhis.android.core.maintenance.D2Error; +import org.hisp.dhis.android.core.maintenance.D2ErrorCode; +import org.hisp.dhis.android.core.maintenance.D2ErrorComponent; + +import java.util.Map; + +import io.reactivex.Single; + +public abstract class ReadWriteWithoutUidCollectionRepositoryImpl + > + extends ReadOnlyCollectionRepositoryImpl + implements ReadWriteWithoutUidCollectionRepository { + + private final ObjectWithoutUidStore store; + + public ReadWriteWithoutUidCollectionRepositoryImpl(ObjectWithoutUidStore store, + Map> childrenAppenders, + RepositoryScope scope, + FilterConnectorFactory cf) { + super(store, childrenAppenders, scope, cf); + this.store = store; + } + + public Single add(M model) { + return Single.fromCallable(() -> blockingAdd(model)); + } + + @SuppressWarnings({"PMD.PreserveStackTrace"}) + public M blockingAdd(M object) throws D2Error { + try { + store.insert(object); + return object; + } catch (Exception e) { + throw D2Error + .builder() + .errorComponent(D2ErrorComponent.SDK) + .errorCode(D2ErrorCode.OBJECT_CANT_BE_INSERTED) + .errorDescription("Object can't be inserted") + .originalException(e) + .build(); + } + } +} \ No newline at end of file From 4fe301dc0068599e392680c6e6d362789e809f9a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 5 Aug 2021 15:51:25 +0200 Subject: [PATCH 253/308] [androsdk-1378] Add LocalDataStoreCollectionRepository --- .../LocalDataStoreCollectionRepository.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java new file mode 100644 index 0000000000..8e47f4c0aa --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore; + +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; +import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadWriteWithoutUidCollectionRepositoryImpl; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; +import org.hisp.dhis.android.core.arch.repositories.filters.internal.StringFilterConnector; +import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; + +import java.util.Map; + +import javax.inject.Inject; + +import dagger.Reusable; + +@Reusable +public final class LocalDataStoreCollectionRepository + extends ReadWriteWithoutUidCollectionRepositoryImpl { + + private final ObjectWithoutUidStore store; + + @Inject + LocalDataStoreCollectionRepository(final ObjectWithoutUidStore store, + final Map> childrenAppenders, + final RepositoryScope scope) { + super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, + s -> new LocalDataStoreCollectionRepository(store, childrenAppenders, s))); + this.store = store; + } + + public StringFilterConnector byKey() { + return cf.string(LocalDataStoreTableInfo.Columns.KEY); + } + + public StringFilterConnector byValue() { + return cf.string(LocalDataStoreTableInfo.Columns.VALUE); + } +} \ No newline at end of file From 74c944234891044e5f78ec1f99dad6621aa78e5a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 6 Aug 2021 17:09:33 +0200 Subject: [PATCH 254/308] [androsdk-1378] Add local data store collection repository and modules --- .../java/org/hisp/dhis/android/core/D2.java | 5 ++ .../core/arch/d2/internal/D2DIComponent.java | 3 ++ .../core/arch/d2/internal/D2Modules.java | 4 ++ ...{LocalDataStore.java => KeyValuePair.java} | 10 ++-- .../LocalDataStoreCollectionRepository.java | 9 ++-- .../core/datastore/LocalDataStoreModule.java | 33 ++++++++++++ .../internal/LocalDataStoreEntityDIModule.kt | 4 +- .../internal/LocalDataStoreModuleImpl.java | 52 +++++++++++++++++++ .../LocalDataStorePackageDIModule.java | 47 +++++++++++++++++ .../datastore/internal/LocalDataStoreStore.kt | 12 ++--- 10 files changed, 160 insertions(+), 19 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/datastore/{LocalDataStore.java => KeyValuePair.java} (88%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/D2.java b/core/src/main/java/org/hisp/dhis/android/core/D2.java index c2c04f096e..4ff65be5e6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/D2.java +++ b/core/src/main/java/org/hisp/dhis/android/core/D2.java @@ -40,6 +40,7 @@ import org.hisp.dhis.android.core.constant.ConstantModule; import org.hisp.dhis.android.core.dataelement.DataElementModule; import org.hisp.dhis.android.core.dataset.DataSetModule; +import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; import org.hisp.dhis.android.core.datavalue.DataValueModule; import org.hisp.dhis.android.core.domain.aggregated.AggregatedModule; import org.hisp.dhis.android.core.enrollment.EnrollmentModule; @@ -172,6 +173,10 @@ public LegendSetModule legendSetModule() { return this.modules.legendSet; } + public LocalDataStoreModule localDataStoreModule() { + return this.modules.localDataStore; + } + public MaintenanceModule maintenanceModule() { return this.modules.maintenance; } diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java index 3b72e895d2..d3f2559774 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java @@ -59,6 +59,7 @@ import org.hisp.dhis.android.core.dataelement.internal.DataElementPackageDIModule; import org.hisp.dhis.android.core.dataset.DataSet; import org.hisp.dhis.android.core.dataset.internal.DataSetPackageDIModule; +import org.hisp.dhis.android.core.datastore.internal.LocalDataStorePackageDIModule; import org.hisp.dhis.android.core.datavalue.internal.DataValueConflictDIModule; import org.hisp.dhis.android.core.datavalue.internal.DataValuePackageDIModule; import org.hisp.dhis.android.core.domain.aggregated.data.internal.AggregatedDataPackageDIModule; @@ -130,6 +131,7 @@ ImportPackageDIModule.class, IndicatorPackageDIModule.class, LegendPackageDIModule.class, + LocalDataStorePackageDIModule.class, MaintenancePackageDIModule.class, MaintenancePackageDIModule.class, NotePackageDIModule.class, @@ -211,6 +213,7 @@ interface Builder { Builder importPackageDIModule(ImportPackageDIModule importPackageDIModule); Builder indicatorPackageDIModule(IndicatorPackageDIModule indicatorPackageDIModule); Builder legendPackageDIModule(LegendPackageDIModule legendPackageDIModule); + Builder localDataStorePackageDIModule(LocalDataStorePackageDIModule localDataStorePackageDIModule); Builder maintenancePackageDIModule(MaintenancePackageDIModule maintenancePackageDIModule); Builder optionPackageDIModule(OptionPackageDIModule optionPackageDIModule); Builder organisationUnitPackageDIModule(OrganisationUnitPackageDIModule organisationUnitPackageDIModule); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java index 07905fb9e6..7b2c7b12ed 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java @@ -33,6 +33,7 @@ import org.hisp.dhis.android.core.constant.ConstantModule; import org.hisp.dhis.android.core.dataelement.DataElementModule; import org.hisp.dhis.android.core.dataset.DataSetModule; +import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; import org.hisp.dhis.android.core.datavalue.DataValueModule; import org.hisp.dhis.android.core.enrollment.EnrollmentModule; import org.hisp.dhis.android.core.event.EventModule; @@ -76,6 +77,7 @@ public final class D2Modules { public final ImportModule importModule; public final IndicatorModule indicator; public final LegendSetModule legendSet; + public final LocalDataStoreModule localDataStore; public final MaintenanceModule maintenance; public final NoteModule note; public final ProgramModule program; @@ -104,6 +106,7 @@ public D2Modules(AnalyticsModule analytics, ImportModule importModule, IndicatorModule indicator, LegendSetModule legendSet, + LocalDataStoreModule localDataStore, MaintenanceModule maintenance, NoteModule note, ProgramModule program, @@ -130,6 +133,7 @@ public D2Modules(AnalyticsModule analytics, this.importModule = importModule; this.indicator = indicator; this.legendSet = legendSet; + this.localDataStore = localDataStore; this.maintenance = maintenance; this.note = note; this.program = program; diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java similarity index 88% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java rename to core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java index 1bb0606236..d66985a5dd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java @@ -37,7 +37,7 @@ import org.hisp.dhis.android.core.common.CoreObject; @AutoValue -public abstract class LocalDataStore implements CoreObject { +public abstract class KeyValuePair implements CoreObject { @Nullable public abstract String key(); @@ -45,14 +45,14 @@ public abstract class LocalDataStore implements CoreObject { @Nullable public abstract String value(); - public static LocalDataStore create(Cursor cursor) { - return $AutoValue_LocalDataStore.createFromCursor(cursor); + public static KeyValuePair create(Cursor cursor) { + return $AutoValue_KeyValuePair.createFromCursor(cursor); } public abstract Builder toBuilder(); public static Builder builder() { - return new AutoValue_LocalDataStore.Builder(); + return new AutoValue_KeyValuePair.Builder(); } @AutoValue.Builder @@ -63,6 +63,6 @@ public static abstract class Builder { public abstract Builder value(String value); - public abstract LocalDataStore build(); + public abstract KeyValuePair build(); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java index 8e47f4c0aa..502f0a7dee 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java @@ -43,17 +43,14 @@ @Reusable public final class LocalDataStoreCollectionRepository - extends ReadWriteWithoutUidCollectionRepositoryImpl { - - private final ObjectWithoutUidStore store; + extends ReadWriteWithoutUidCollectionRepositoryImpl { @Inject - LocalDataStoreCollectionRepository(final ObjectWithoutUidStore store, - final Map> childrenAppenders, + LocalDataStoreCollectionRepository(final ObjectWithoutUidStore store, + final Map> childrenAppenders, final RepositoryScope scope) { super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, s -> new LocalDataStoreCollectionRepository(store, childrenAppenders, s))); - this.store = store; } public StringFilterConnector byKey() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.java new file mode 100644 index 0000000000..81389c3762 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore; + +public interface LocalDataStoreModule { + LocalDataStoreCollectionRepository localDataStore(); +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt index 80e8ac2c35..5f8874b69d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt @@ -32,14 +32,14 @@ import dagger.Provides import dagger.Reusable import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore -import org.hisp.dhis.android.core.datastore.LocalDataStore +import org.hisp.dhis.android.core.datastore.KeyValuePair @Module internal class LocalDataStoreEntityDIModule { @Provides @Reusable - fun store(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { + fun store(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { return LocalDataStoreStore.create(databaseAdapter) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.java new file mode 100644 index 0000000000..80e0ff0bcb --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore.internal; + +import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository; +import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; + +import javax.inject.Inject; + +import dagger.Reusable; + +@Reusable +public final class LocalDataStoreModuleImpl implements LocalDataStoreModule { + + private final LocalDataStoreCollectionRepository localDataStore; + + @Inject + LocalDataStoreModuleImpl(LocalDataStoreCollectionRepository localDataStore) { + this.localDataStore = localDataStore; + } + + @Override + public LocalDataStoreCollectionRepository localDataStore() { + return localDataStore; + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.java new file mode 100644 index 0000000000..7f7365efe7 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore.internal; + +import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; + +import dagger.Module; +import dagger.Provides; +import dagger.Reusable; + +@Module(includes = { + LocalDataStoreEntityDIModule.class +}) +public final class LocalDataStorePackageDIModule { + + @Provides + @Reusable + LocalDataStoreModule module(LocalDataStoreModuleImpl impl) { + return impl; + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt index 5a633b99f4..67a5d7d622 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt @@ -33,28 +33,28 @@ import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinde import org.hisp.dhis.android.core.arch.db.stores.binders.internal.WhereStatementBinder import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithoutUidStore -import org.hisp.dhis.android.core.datastore.LocalDataStore +import org.hisp.dhis.android.core.datastore.KeyValuePair import org.hisp.dhis.android.core.datastore.LocalDataStoreTableInfo @Suppress("MagicNumber") internal object LocalDataStoreStore { - private val BINDER: StatementBinder = StatementBinder { o, w -> + private val BINDER: StatementBinder = StatementBinder { o, w -> w.bind(1, o.key()) w.bind(2, o.value()) } - private val WHERE_UPDATE_BINDER = WhereStatementBinder { _: LocalDataStore, _ -> } - private val WHERE_DELETE_BINDER = WhereStatementBinder { _: LocalDataStore, _ -> } + private val WHERE_UPDATE_BINDER = WhereStatementBinder { _: KeyValuePair, _ -> } + private val WHERE_DELETE_BINDER = WhereStatementBinder { _: KeyValuePair, _ -> } @JvmStatic - fun create(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { + fun create(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { return objectWithoutUidStore( databaseAdapter, LocalDataStoreTableInfo.TABLE_INFO, BINDER, WHERE_UPDATE_BINDER, WHERE_DELETE_BINDER - ) { cursor: Cursor -> LocalDataStore.create(cursor) } + ) { cursor: Cursor -> KeyValuePair.create(cursor) } } } From f9478d4d4b5c411476ed103c27012b9d6d63c788 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 6 Aug 2021 17:09:45 +0200 Subject: [PATCH 255/308] [androsdk-1378] Add tests --- ...ectionRepositoryMockIntegrationShould.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java new file mode 100644 index 0000000000..612d019c8b --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2004-2021, 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.datastore; + +import static com.google.common.truth.Truth.assertThat; + +import org.hisp.dhis.android.core.datastore.KeyValuePair; +import org.hisp.dhis.android.core.maintenance.D2Error; +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) +public class LocalDataStoreCollectionRepositoryMockIntegrationShould extends BaseMockIntegrationTestFullDispatcher { + + @Test + public void add_values() throws D2Error { + d2.localDataStoreModule().localDataStore().blockingAdd( + KeyValuePair.builder() + .key("key1") + .value("value1") + .build() + ); + d2.localDataStoreModule().localDataStore().blockingAdd( + KeyValuePair.builder() + .key("key2") + .value("value2") + .build() + ); + assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); + } + + @Test + public void find_all() { + assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); + } + + @Test + public void filter_by_key() { + KeyValuePair pair = d2.localDataStoreModule().localDataStore() + .byKey().eq("key1") + .one() + .blockingGet(); + + assertThat(pair.key()).isEqualTo("key1"); + assertThat(pair.value()).isEqualTo("value1"); + } + + @Test + public void filter_by_value() { + KeyValuePair pair = d2.localDataStoreModule().localDataStore() + .byValue().eq("value2") + .one() + .blockingGet(); + + assertThat(pair.key()).isEqualTo("key2"); + assertThat(pair.value()).isEqualTo("value2"); + } +} \ No newline at end of file From 0e6eb1668b83d3d75a463e63111e5475e2045b25 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:09:11 +0200 Subject: [PATCH 256/308] [androsdk-1378] Fix LocalDataStoreEntityDIModule --- .../datastore/internal/LocalDataStoreEntityDIModule.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt index 5f8874b69d..c02d005abd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreEntityDIModule.kt @@ -32,6 +32,7 @@ import dagger.Provides import dagger.Reusable import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender import org.hisp.dhis.android.core.datastore.KeyValuePair @Module @@ -42,4 +43,10 @@ internal class LocalDataStoreEntityDIModule { fun store(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { return LocalDataStoreStore.create(databaseAdapter) } + + @Provides + @Reusable + fun childrenAppenders(databaseAdapter: DatabaseAdapter): Map> { + return emptyMap() + } } From 83f76db306fc81c72d5650c65f8cc4d576fc4218 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:10:18 +0200 Subject: [PATCH 257/308] [androsdk-1378] Improve LocalDataStoreCollectionRepositoryMockIntegrationShould --- ...ectionRepositoryMockIntegrationShould.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java index 612d019c8b..4106953e58 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java @@ -40,30 +40,15 @@ @RunWith(D2JunitRunner.class) public class LocalDataStoreCollectionRepositoryMockIntegrationShould extends BaseMockIntegrationTestFullDispatcher { - @Test - public void add_values() throws D2Error { - d2.localDataStoreModule().localDataStore().blockingAdd( - KeyValuePair.builder() - .key("key1") - .value("value1") - .build() - ); - d2.localDataStoreModule().localDataStore().blockingAdd( - KeyValuePair.builder() - .key("key2") - .value("value2") - .build() - ); - assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); - } - @Test public void find_all() { + add_values(); assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); } @Test public void filter_by_key() { + add_values(); KeyValuePair pair = d2.localDataStoreModule().localDataStore() .byKey().eq("key1") .one() @@ -75,6 +60,7 @@ public void filter_by_key() { @Test public void filter_by_value() { + add_values(); KeyValuePair pair = d2.localDataStoreModule().localDataStore() .byValue().eq("value2") .one() @@ -83,4 +69,22 @@ public void filter_by_value() { assertThat(pair.key()).isEqualTo("key2"); assertThat(pair.value()).isEqualTo("value2"); } + + private void add_values() { + try { + d2.localDataStoreModule().localDataStore().blockingAdd( + KeyValuePair.builder() + .key("key1") + .value("value1") + .build()); + d2.localDataStoreModule().localDataStore().blockingAdd( + KeyValuePair.builder() + .key("key2") + .value("value2") + .build()); + } catch (D2Error d2Error) { + d2Error.printStackTrace(); + } + assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); + } } \ No newline at end of file From 829b20ea1e9194f1facb4d4177ebf670652f9fec Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:14:36 +0200 Subject: [PATCH 258/308] [androsdk-1378] Add LocalDataStoreStoreIntegrationShould --- .../LocalDataStoreStoreIntegrationShould.kt | 61 +++++++++++++++++++ .../datastore/internal/LocalDataStoreStore.kt | 11 +++- .../data/datastore/KeyValuePairSamples.kt | 40 ++++++++++++ 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt create mode 100644 core/src/sharedTest/java/org/hisp/dhis/android/core/data/datastore/KeyValuePairSamples.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt new file mode 100644 index 0000000000..ba3cb13915 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore + +import org.hisp.dhis.android.core.data.database.ObjectStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore.create +import org.hisp.dhis.android.core.data.datastore.KeyValuePairSamples.keyValuePairSample +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.hisp.dhis.android.core.data.database.ObjectWithoutUidStoreAbstractIntegrationShould +import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore +import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory +import org.hisp.dhis.android.core.datastore.LocalDataStoreTableInfo +import org.hisp.dhis.android.core.data.datastore.KeyValuePairSamples +import org.hisp.dhis.android.core.data.settings.AnalyticsSettingsSamples +import org.hisp.dhis.android.core.settings.AnalyticsTeiAttribute +import org.hisp.dhis.android.core.settings.AnalyticsTeiAttributeTableInfo +import org.hisp.dhis.android.core.settings.internal.AnalyticsTeiAttributeStore +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class LocalDataStoreStoreIntegrationShould : ObjectWithoutUidStoreAbstractIntegrationShould( + create(TestDatabaseAdapterFactory.get()), + LocalDataStoreTableInfo.TABLE_INFO, + TestDatabaseAdapterFactory.get() +) { + override fun buildObject(): KeyValuePair { + return keyValuePairSample + } + + override fun buildObjectToUpdate(): KeyValuePair { + return keyValuePairSample + .toBuilder() + .value("value2") + .build() + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt index 67a5d7d622..96c115d913 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.datastore.internal import android.database.Cursor import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter 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 import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore import org.hisp.dhis.android.core.arch.db.stores.internal.StoreFactory.objectWithoutUidStore @@ -44,8 +45,14 @@ internal object LocalDataStoreStore { w.bind(2, o.value()) } - private val WHERE_UPDATE_BINDER = WhereStatementBinder { _: KeyValuePair, _ -> } - private val WHERE_DELETE_BINDER = WhereStatementBinder { _: KeyValuePair, _ -> } + + private val WHERE_UPDATE_BINDER = WhereStatementBinder { o: KeyValuePair, w: StatementWrapper -> + w.bind(3, o.key()) + } + + private val WHERE_DELETE_BINDER = WhereStatementBinder { o: KeyValuePair, w: StatementWrapper -> + w.bind(1, o.key()) + } @JvmStatic fun create(databaseAdapter: DatabaseAdapter): ObjectWithoutUidStore { diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datastore/KeyValuePairSamples.kt b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datastore/KeyValuePairSamples.kt new file mode 100644 index 0000000000..4263a1a2e9 --- /dev/null +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/datastore/KeyValuePairSamples.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2004-2021, 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.core.data.datastore + +import org.hisp.dhis.android.core.datastore.KeyValuePair + +object KeyValuePairSamples { + + val keyValuePairSample: KeyValuePair = + KeyValuePair.builder() + .id(1L) + .key("key1") + .value("value1") + .build() +} From 5fed779fff9c984f3779c2796b65aac044e44672 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:15:18 +0200 Subject: [PATCH 259/308] [androsdk-1378] Add KeyValuePairPublicAccessShould --- .../KeyValuePairPublicAccessShould.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 core/src/test/java/org/hisp/dhis/android/testapp/datastore/KeyValuePairPublicAccessShould.java diff --git a/core/src/test/java/org/hisp/dhis/android/testapp/datastore/KeyValuePairPublicAccessShould.java b/core/src/test/java/org/hisp/dhis/android/testapp/datastore/KeyValuePairPublicAccessShould.java new file mode 100644 index 0000000000..bf75937ae8 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/testapp/datastore/KeyValuePairPublicAccessShould.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.datastore; + +import org.hisp.dhis.android.core.datastore.KeyValuePair; +import org.hisp.dhis.android.testapp.arch.BasePublicAccessShould; +import org.mockito.Mock; + +public class KeyValuePairPublicAccessShould extends BasePublicAccessShould { + + @Mock + private KeyValuePair object; + + @Override + public KeyValuePair object() { + return object; + } + + @Override + public void has_public_create_method() { + KeyValuePair.create(null); + } + + @Override + public void has_public_builder_method() { + KeyValuePair.builder(); + } + + @Override + public void has_public_to_builder_method() { + object().toBuilder(); + } +} \ No newline at end of file From 3543ee8c2f521c9fbb2ba761772fe6d4e105eb3e Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:27:35 +0200 Subject: [PATCH 260/308] [androsdk-1378] Add LocalDataStoreModuleWiper --- .../internal/LocalDataStoreModuleWiper.kt | 47 +++++++++++++++++++ .../core/wipe/internal/D2ModuleWipers.java | 3 ++ 2 files changed, 50 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt new file mode 100644 index 0000000000..4f8c78b520 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.datastore.LocalDataStoreTableInfo +import org.hisp.dhis.android.core.wipe.internal.ModuleWiper +import org.hisp.dhis.android.core.wipe.internal.TableWiper +import javax.inject.Inject + +@Reusable +class LocalDataStoreModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { + override fun wipeMetadata() { + // No metadata to wipe + } + + override fun wipeData() { + tableWiper.wipeTables( + LocalDataStoreTableInfo.TABLE_INFO + ) + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java b/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java index db2d367d91..cddb9356a8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java +++ b/core/src/main/java/org/hisp/dhis/android/core/wipe/internal/D2ModuleWipers.java @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.constant.internal.ConstantModuleWiper; import org.hisp.dhis.android.core.dataelement.internal.DataElementModuleWiper; import org.hisp.dhis.android.core.dataset.internal.DataSetModuleWiper; +import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreModuleWiper; import org.hisp.dhis.android.core.datavalue.internal.DataValueModuleWiper; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentModuleWiper; import org.hisp.dhis.android.core.event.internal.EventModuleWiper; @@ -85,6 +86,7 @@ final class D2ModuleWipers { ImportModuleWiper importModule, IndicatorModuleWiper indicator, LegendSetModuleWiper legendSet, + LocalDataStoreModuleWiper localDataStore, MaintenanceModuleWiper maintenance, OptionModuleWiper option, @@ -118,6 +120,7 @@ final class D2ModuleWipers { importModule, indicator, legendSet, + localDataStore, maintenance, option, From 19b931cb804c57044621fd5c2a23186616229e5e Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:29:07 +0200 Subject: [PATCH 261/308] [androsdk-1378] Rename .java to .kt --- .../{LocalDataStoreModule.java => LocalDataStoreModule.kt} | 0 ...{LocalDataStoreModuleImpl.java => LocalDataStoreModuleImpl.kt} | 0 ...StorePackageDIModule.java => LocalDataStorePackageDIModule.kt} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/datastore/{LocalDataStoreModule.java => LocalDataStoreModule.kt} (100%) rename core/src/main/java/org/hisp/dhis/android/core/datastore/internal/{LocalDataStoreModuleImpl.java => LocalDataStoreModuleImpl.kt} (100%) rename core/src/main/java/org/hisp/dhis/android/core/datastore/internal/{LocalDataStorePackageDIModule.java => LocalDataStorePackageDIModule.kt} (100%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt similarity index 100% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.java rename to core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt similarity index 100% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.java rename to core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt similarity index 100% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.java rename to core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt From 4489cf9821ac0c10b31c36665288b337ef4bede5 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:29:08 +0200 Subject: [PATCH 262/308] [androsdk-1378] Transform to Kotlin some classes --- .../core/datastore/LocalDataStoreModule.kt | 7 ++--- .../internal/LocalDataStoreModuleImpl.kt | 29 ++++++------------- .../internal/LocalDataStorePackageDIModule.kt | 23 ++++++--------- 3 files changed, 21 insertions(+), 38 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt index 81389c3762..c9862714cc 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt @@ -25,9 +25,8 @@ * (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.datastore -package org.hisp.dhis.android.core.datastore; - -public interface LocalDataStoreModule { - LocalDataStoreCollectionRepository localDataStore(); +interface LocalDataStoreModule { + fun localDataStore(): LocalDataStoreCollectionRepository? } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt index 80e0ff0bcb..f8568ce35e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt @@ -25,28 +25,17 @@ * (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.datastore.internal -package org.hisp.dhis.android.core.datastore.internal; - -import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository; -import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; - -import javax.inject.Inject; - -import dagger.Reusable; +import dagger.Reusable +import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository +import org.hisp.dhis.android.core.datastore.LocalDataStoreModule +import javax.inject.Inject @Reusable -public final class LocalDataStoreModuleImpl implements LocalDataStoreModule { - - private final LocalDataStoreCollectionRepository localDataStore; - - @Inject - LocalDataStoreModuleImpl(LocalDataStoreCollectionRepository localDataStore) { - this.localDataStore = localDataStore; - } - - @Override - public LocalDataStoreCollectionRepository localDataStore() { - return localDataStore; +class LocalDataStoreModuleImpl @Inject internal constructor(private val localDataStore: LocalDataStoreCollectionRepository) : + LocalDataStoreModule { + override fun localDataStore(): LocalDataStoreCollectionRepository { + return localDataStore } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt index 7f7365efe7..79570869f5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt @@ -25,23 +25,18 @@ * (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.datastore.internal -package org.hisp.dhis.android.core.datastore.internal; - -import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; - -import dagger.Module; -import dagger.Provides; -import dagger.Reusable; - -@Module(includes = { - LocalDataStoreEntityDIModule.class -}) -public final class LocalDataStorePackageDIModule { +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.datastore.LocalDataStoreModule +@Module(includes = [LocalDataStoreEntityDIModule::class]) +class LocalDataStorePackageDIModule { @Provides @Reusable - LocalDataStoreModule module(LocalDataStoreModuleImpl impl) { - return impl; + fun module(impl: LocalDataStoreModuleImpl): LocalDataStoreModule { + return impl } } \ No newline at end of file From 455aef3b80fcef192b51fc8915161c9a8b0be451 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 11:32:36 +0200 Subject: [PATCH 263/308] [androsdk-1378] KtlintFormat --- .../LocalDataStoreStoreIntegrationShould.kt | 16 ++++------------ .../core/datastore/LocalDataStoreModule.kt | 2 +- .../internal/LocalDataStoreModuleImpl.kt | 8 +++++--- .../internal/LocalDataStoreModuleWiper.kt | 4 ++-- .../internal/LocalDataStorePackageDIModule.kt | 2 +- .../datastore/internal/LocalDataStoreStore.kt | 1 - 6 files changed, 13 insertions(+), 20 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt index ba3cb13915..be6dd95bda 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/datastore/LocalDataStoreStoreIntegrationShould.kt @@ -27,19 +27,11 @@ */ package org.hisp.dhis.android.core.datastore -import org.hisp.dhis.android.core.data.database.ObjectStoreAbstractIntegrationShould -import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore.create -import org.hisp.dhis.android.core.data.datastore.KeyValuePairSamples.keyValuePairSample -import org.hisp.dhis.android.core.utils.runner.D2JunitRunner import org.hisp.dhis.android.core.data.database.ObjectWithoutUidStoreAbstractIntegrationShould -import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore +import org.hisp.dhis.android.core.data.datastore.KeyValuePairSamples.keyValuePairSample +import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore.create import org.hisp.dhis.android.core.utils.integration.mock.TestDatabaseAdapterFactory -import org.hisp.dhis.android.core.datastore.LocalDataStoreTableInfo -import org.hisp.dhis.android.core.data.datastore.KeyValuePairSamples -import org.hisp.dhis.android.core.data.settings.AnalyticsSettingsSamples -import org.hisp.dhis.android.core.settings.AnalyticsTeiAttribute -import org.hisp.dhis.android.core.settings.AnalyticsTeiAttributeTableInfo -import org.hisp.dhis.android.core.settings.internal.AnalyticsTeiAttributeStore +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) @@ -58,4 +50,4 @@ class LocalDataStoreStoreIntegrationShould : ObjectWithoutUidStoreAbstractIntegr .value("value2") .build() } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt index c9862714cc..159c228d37 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt @@ -29,4 +29,4 @@ package org.hisp.dhis.android.core.datastore interface LocalDataStoreModule { fun localDataStore(): LocalDataStoreCollectionRepository? -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt index f8568ce35e..6d22371412 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt @@ -28,14 +28,16 @@ package org.hisp.dhis.android.core.datastore.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository import org.hisp.dhis.android.core.datastore.LocalDataStoreModule -import javax.inject.Inject @Reusable -class LocalDataStoreModuleImpl @Inject internal constructor(private val localDataStore: LocalDataStoreCollectionRepository) : +class LocalDataStoreModuleImpl @Inject internal constructor( + private val localDataStore: LocalDataStoreCollectionRepository +) : LocalDataStoreModule { override fun localDataStore(): LocalDataStoreCollectionRepository { return localDataStore } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt index 4f8c78b520..a863c7cf08 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleWiper.kt @@ -28,10 +28,10 @@ package org.hisp.dhis.android.core.datastore.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.datastore.LocalDataStoreTableInfo import org.hisp.dhis.android.core.wipe.internal.ModuleWiper import org.hisp.dhis.android.core.wipe.internal.TableWiper -import javax.inject.Inject @Reusable class LocalDataStoreModuleWiper @Inject internal constructor(private val tableWiper: TableWiper) : ModuleWiper { @@ -44,4 +44,4 @@ class LocalDataStoreModuleWiper @Inject internal constructor(private val tableWi LocalDataStoreTableInfo.TABLE_INFO ) } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt index 79570869f5..41a328a51c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt @@ -39,4 +39,4 @@ class LocalDataStorePackageDIModule { fun module(impl: LocalDataStoreModuleImpl): LocalDataStoreModule { return impl } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt index 96c115d913..e016ca61b4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreStore.kt @@ -45,7 +45,6 @@ internal object LocalDataStoreStore { w.bind(2, o.value()) } - private val WHERE_UPDATE_BINDER = WhereStatementBinder { o: KeyValuePair, w: StatementWrapper -> w.bind(3, o.key()) } From e58747c8357eab2650aaa2c5a00fef0b519d9e43 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Thu, 19 Aug 2021 12:11:09 +0200 Subject: [PATCH 264/308] [androsdk-1378] Fix failing tests --- ...BaseMockIntegrationTestFullDispatcher.java | 18 ++++++++++++++++ .../wipe/WipeDBCallMockIntegrationShould.java | 14 +++++++++++++ ...ectionRepositoryMockIntegrationShould.java | 21 ------------------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java b/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java index 89d2729633..68c1ce039f 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java @@ -28,9 +28,14 @@ package org.hisp.dhis.android.core.utils.integration.mock; +import static com.google.common.truth.Truth.assertThat; + import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; import org.hisp.dhis.android.core.data.imports.TrackerImportConflictSamples; import org.hisp.dhis.android.core.data.maintenance.D2ErrorSamples; +import org.hisp.dhis.android.core.datastore.KeyValuePair; +import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore; import org.hisp.dhis.android.core.imports.ImportStatus; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStoreImpl; @@ -61,6 +66,7 @@ public static void setUpClass() throws Exception { downloadAggregatedData(); storeSomeD2Errors(); storeSomeConflicts(); + storeSomeKeyValuesInLocalDataStore(); } } @@ -129,4 +135,16 @@ private static void storeSomeConflicts() { .build() ); } + + private static void storeSomeKeyValuesInLocalDataStore() { + ObjectWithoutUidStore dataStore = LocalDataStoreStore.create(databaseAdapter); + dataStore.insert(KeyValuePair.builder() + .key("key1") + .value("value1") + .build()); + dataStore.insert(KeyValuePair.builder() + .key("key2") + .value("value2") + .build()); + } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java index 60850631b0..e2a5f5cc36 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/wipe/WipeDBCallMockIntegrationShould.java @@ -29,6 +29,8 @@ package org.hisp.dhis.android.core.wipe; import org.hisp.dhis.android.core.data.database.DatabaseAssert; +import org.hisp.dhis.android.core.datastore.KeyValuePair; +import org.hisp.dhis.android.core.datastore.internal.LocalDataStoreStore; import org.hisp.dhis.android.core.datavalue.DataValueConflict; import org.hisp.dhis.android.core.datavalue.internal.DataValueConflictStore; import org.hisp.dhis.android.core.fileresource.FileResource; @@ -102,5 +104,17 @@ private void givenOthersInDatabase() { .build() ); DataValueConflictStore.create(databaseAdapter).insert(DataValueConflict.builder().build()); + LocalDataStoreStore.create(databaseAdapter).insert( + KeyValuePair.builder() + .key("key1") + .value("value1") + .build() + ); + LocalDataStoreStore.create(databaseAdapter).insert( + KeyValuePair.builder() + .key("key2") + .value("value2") + .build() + ); } } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java index 4106953e58..f9de0cd34a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java @@ -42,13 +42,11 @@ public class LocalDataStoreCollectionRepositoryMockIntegrationShould extends Bas @Test public void find_all() { - add_values(); assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); } @Test public void filter_by_key() { - add_values(); KeyValuePair pair = d2.localDataStoreModule().localDataStore() .byKey().eq("key1") .one() @@ -60,7 +58,6 @@ public void filter_by_key() { @Test public void filter_by_value() { - add_values(); KeyValuePair pair = d2.localDataStoreModule().localDataStore() .byValue().eq("value2") .one() @@ -69,22 +66,4 @@ public void filter_by_value() { assertThat(pair.key()).isEqualTo("key2"); assertThat(pair.value()).isEqualTo("value2"); } - - private void add_values() { - try { - d2.localDataStoreModule().localDataStore().blockingAdd( - KeyValuePair.builder() - .key("key1") - .value("value1") - .build()); - d2.localDataStoreModule().localDataStore().blockingAdd( - KeyValuePair.builder() - .key("key2") - .value("value2") - .build()); - } catch (D2Error d2Error) { - d2Error.printStackTrace(); - } - assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); - } } \ No newline at end of file From adf9109c0a5caf9bff288a989386eb2f62cb80cc Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 20 Aug 2021 10:23:51 +0200 Subject: [PATCH 265/308] [androsdk-1378] Fix LocalDataStoreModule --- .../java/org/hisp/dhis/android/core/datastore/KeyValuePair.java | 2 +- .../hisp/dhis/android/core/datastore/LocalDataStoreModule.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java index d66985a5dd..1a9bc3f43f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/KeyValuePair.java @@ -39,7 +39,7 @@ @AutoValue public abstract class KeyValuePair implements CoreObject { - @Nullable + @Nullable public abstract String key(); @Nullable diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt index 159c228d37..cc0d77b431 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt @@ -28,5 +28,5 @@ package org.hisp.dhis.android.core.datastore interface LocalDataStoreModule { - fun localDataStore(): LocalDataStoreCollectionRepository? + fun localDataStore(): LocalDataStoreCollectionRepository } From 5faf2f53ecd17cd70a5f724c2aefe40af73fe4c4 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 20 Aug 2021 10:24:16 +0200 Subject: [PATCH 266/308] [androsdk-1378] Add LocalDataStoreObjectRepository --- .../LocalDataStoreCollectionRepository.java | 8 +++ .../LocalDataStoreObjectRepository.java | 67 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreObjectRepository.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java index 502f0a7dee..2513d62169 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java @@ -45,12 +45,20 @@ public final class LocalDataStoreCollectionRepository extends ReadWriteWithoutUidCollectionRepositoryImpl { + private final ObjectWithoutUidStore store; + @Inject LocalDataStoreCollectionRepository(final ObjectWithoutUidStore store, final Map> childrenAppenders, final RepositoryScope scope) { super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, s -> new LocalDataStoreCollectionRepository(store, childrenAppenders, s))); + this.store = store; + } + + public LocalDataStoreObjectRepository value(String key) { + RepositoryScope updatedScope = byKey().eq(key).scope; + return new LocalDataStoreObjectRepository(store, childrenAppenders, updatedScope, key); } public StringFilterConnector byKey() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreObjectRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreObjectRepository.java new file mode 100644 index 0000000000..58b3d61864 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreObjectRepository.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2004-2021, 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.core.datastore; + +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; +import org.hisp.dhis.android.core.arch.repositories.object.ReadWriteValueObjectRepository; +import org.hisp.dhis.android.core.arch.repositories.object.internal.ReadWriteWithValueObjectRepositoryImpl; +import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; +import org.hisp.dhis.android.core.maintenance.D2Error; + +import java.util.Map; + +import io.reactivex.Completable; + +public final class LocalDataStoreObjectRepository + extends ReadWriteWithValueObjectRepositoryImpl + implements ReadWriteValueObjectRepository { + + private final String key; + + LocalDataStoreObjectRepository( + final ObjectWithoutUidStore store, + final Map> childrenAppenders, + final RepositoryScope scope, + final String key) { + super(store, childrenAppenders, scope, s -> + new LocalDataStoreObjectRepository(store, childrenAppenders, s, key)); + this.key = key; + } + + @Override + public Completable set(String value) { + return Completable.fromAction(() -> blockingSet(value)); + } + + public void blockingSet(String value) throws D2Error { + KeyValuePair pair = KeyValuePair.builder().key(key).value(value).build(); + setObject(pair); + } +} \ No newline at end of file From 7e681eab08ee6f1bcdfe2ce4bff6fb44f453a44b Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Fri, 20 Aug 2021 10:25:38 +0200 Subject: [PATCH 267/308] [androsdk-1378] Add LocalDataStoreObjectRepository tests --- ...BaseMockIntegrationTestFullDispatcher.java | 2 - ...ectionRepositoryMockIntegrationShould.java | 10 ++- ...ObjectRepositoryMockIntegrationShould.java | 77 +++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java b/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java index 68c1ce039f..022fd24fce 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/utils/integration/mock/BaseMockIntegrationTestFullDispatcher.java @@ -28,8 +28,6 @@ package org.hisp.dhis.android.core.utils.integration.mock; -import static com.google.common.truth.Truth.assertThat; - import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; import org.hisp.dhis.android.core.data.imports.TrackerImportConflictSamples; diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java index f9de0cd34a..1e8ec33435 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java @@ -31,7 +31,7 @@ import static com.google.common.truth.Truth.assertThat; import org.hisp.dhis.android.core.datastore.KeyValuePair; -import org.hisp.dhis.android.core.maintenance.D2Error; +import org.hisp.dhis.android.core.datastore.LocalDataStoreObjectRepository; import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; import org.junit.Test; @@ -66,4 +66,12 @@ public void filter_by_value() { assertThat(pair.key()).isEqualTo("key2"); assertThat(pair.value()).isEqualTo("value2"); } + + @Test + public void return_object_repository() { + LocalDataStoreObjectRepository objectRepository = d2.localDataStoreModule().localDataStore() + .value("key1"); + assertThat(objectRepository.blockingExists()).isEqualTo(Boolean.TRUE); + assertThat(objectRepository.blockingGet().value()).isEqualTo("value1"); + } } \ No newline at end of file diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java new file mode 100644 index 0000000000..789f02bde9 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2004-2021, 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.datastore; + +import static com.google.common.truth.Truth.assertThat; + +import org.hisp.dhis.android.core.datastore.LocalDataStoreObjectRepository; +import org.hisp.dhis.android.core.maintenance.D2Error; +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) +public class LocalDataStoreObjectRepositoryMockIntegrationShould extends BaseMockIntegrationTestFullDispatcher { + + @Test + public void update_value() throws D2Error { + String value = "new_value"; + + LocalDataStoreObjectRepository repository = objectRepository(); + + repository.blockingSet(value); + assertThat(repository.blockingGet().value()).isEqualTo(value); + + repository.blockingDelete(); + } + + + @Test + public void delete_value() throws D2Error { + LocalDataStoreObjectRepository repository = objectRepository(); + + repository.blockingSet("value"); + assertThat(repository.blockingExists()).isEqualTo(Boolean.TRUE); + repository.blockingDelete(); + assertThat(repository.blockingExists()).isEqualTo(Boolean.FALSE); + } + + @Test + public void return_that_a_value_exists_only_if_it_has_been_created() { + assertThat(d2.localDataStoreModule().localDataStore() + .value("no_key").blockingExists()).isEqualTo(Boolean.FALSE); + assertThat(d2.localDataStoreModule().localDataStore() + .value("key1").blockingExists()).isEqualTo(Boolean.TRUE); + } + + private LocalDataStoreObjectRepository objectRepository() { + return d2.localDataStoreModule().localDataStore().value("new_key"); + } +} \ No newline at end of file From ae116c74df24abc409e9e401897852e0c34aa6bb Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 20 Aug 2021 14:26:11 +0200 Subject: [PATCH 268/308] [ANDROSDK-344] Refactor tracker calls to support any kind of relationship --- ...ayloadGenerator29MockIntegrationShould.kt} | 10 +- .../core/arch/d2/internal/D2DIComponent.java | 4 +- .../core/event/internal/OldEventPostCall.kt | 26 +- .../internal/RelationshipImportSummaries.java | 59 ++++ .../internal/RelationshipImportSummary.java} | 23 +- .../internal/RelationshipWebResponse.java | 66 ++++ ...eHandler.java => TEIWebResponseHandler.kt} | 48 +-- .../internal/RelationshipDeleteCall.java | 132 -------- ...temStore.java => RelationshipItemStore.kt} | 25 +- .../internal/RelationshipItemStoreImpl.java | 171 ---------- .../internal/RelationshipItemStoreImpl.kt | 165 +++++++++ .../internal/RelationshipPayload.java | 59 ++++ .../internal/RelationshipPostCall.kt | 132 ++++++++ .../internal/RelationshipService.kt | 50 +++ .../OldTrackedEntityInstancePostCall.kt | 32 +- .../internal/OldTrackerImporterPayload.kt | 51 +++ .../OldTrackerImporterPayloadGenerator.kt | 313 ++++++++++++++++++ .../internal/OldTrackerImporterPostCall.kt | 164 +++++++++ .../internal/TrackedEntityDataValueStore.java | 2 + .../TrackedEntityDataValueStoreImpl.java | 10 + .../TrackedEntityInstanceImportHandler.kt | 3 +- ...edEntityInstancePostPayloadGenerator29.kt} | 117 ++++--- .../TrackedEntityInstanceService.java | 2 + .../relationship_delete_web_response.json | 19 ++ .../imports/relationship_web_response.json | 43 +++ ...relationship_web_response_with_errors.json | 43 +++ .../RelationshipDeleteWebResponseShould.java | 55 +++ .../RelationshipWebResponseShould.java | 63 ++++ 28 files changed, 1441 insertions(+), 446 deletions(-) rename core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/{TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt => TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt} (97%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummaries.java rename core/src/main/java/org/hisp/dhis/android/core/{relationship/internal/RelationshipService.java => imports/internal/RelationshipImportSummary.java} (71%) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponse.java rename core/src/main/java/org/hisp/dhis/android/core/imports/internal/{TEIWebResponseHandler.java => TEIWebResponseHandler.kt} (62%) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java rename core/src/main/java/org/hisp/dhis/android/core/relationship/internal/{RelationshipItemStore.java => RelationshipItemStore.kt} (72%) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPayload.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt create mode 100644 core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt rename core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/{TrackedEntityInstancePostPayloadGenerator.kt => TrackedEntityInstancePostPayloadGenerator29.kt} (71%) create mode 100644 core/src/sharedTest/resources/imports/relationship_delete_web_response.json create mode 100644 core/src/sharedTest/resources/imports/relationship_web_response.json create mode 100644 core/src/sharedTest/resources/imports/relationship_web_response_with_errors.json create mode 100644 core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipDeleteWebResponseShould.java create mode 100644 core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponseShould.java diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt similarity index 97% rename from core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt rename to core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt index 738524cfd3..392946ae4c 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt @@ -65,7 +65,7 @@ import org.junit.Test import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) -class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockIntegrationTestMetadataEnqueable() { +class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMockIntegrationTestMetadataEnqueable() { private val teiId = "teiId" private val enrollment1Id = "enrollment1Id" @@ -102,7 +102,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI } private val partitions: List> - get() = payloadGenerator.getTrackedEntityInstancesPartitions( + get() = payloadGenerator29.getTrackedEntityInstancesPartitions29( teiStore.queryTrackedEntityInstancesToSync() ) @@ -216,7 +216,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI storeRelationship("relationship3", tei1, tei5) storeRelationship("relationship4", tei5, tei4) - val partitions = payloadGenerator.getTrackedEntityInstancesPartitions( + val partitions = payloadGenerator29.getTrackedEntityInstancesPartitions29( d2.trackedEntityModule().trackedEntityInstances().byUid().eq(tei1) .byAggregatedSyncState().`in`(*State.uploadableStates()).blockingGet() ) @@ -513,7 +513,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI } companion object { - private lateinit var payloadGenerator: TrackedEntityInstancePostPayloadGenerator + private lateinit var payloadGenerator29: TrackedEntityInstancePostPayloadGenerator29 private lateinit var teiStore: TrackedEntityInstanceStore private lateinit var teiDataValueStore: TrackedEntityDataValueStore private lateinit var eventStore: EventStore @@ -524,7 +524,7 @@ class TrackedEntityInstancePostPayloadGeneratorMockIntegrationShould : BaseMockI @Throws(Exception::class) fun setUp() { setUpClass() - payloadGenerator = objects.d2DIComponent.trackedEntityInstancePostPayloadGenerator() + payloadGenerator29 = objects.d2DIComponent.trackedEntityInstancePostPayloadGenerator() teiStore = TrackedEntityInstanceStoreImpl.create(databaseAdapter) teiDataValueStore = TrackedEntityDataValueStoreImpl.create(databaseAdapter) eventStore = EventStoreImpl.create(databaseAdapter) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java index 3b72e895d2..ff2b4edd88 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java @@ -89,7 +89,7 @@ import org.hisp.dhis.android.core.systeminfo.internal.SystemInfoPackageDIModule; import org.hisp.dhis.android.core.trackedentity.TrackedEntityPackageDIModule; import org.hisp.dhis.android.core.trackedentity.TrackedEntityType; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstancePostPayloadGenerator; +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstancePostPayloadGenerator29; import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterPackageDIModule; import org.hisp.dhis.android.core.user.internal.UserPackageDIModule; import org.hisp.dhis.android.core.validation.internal.ValidationPackageDIModule; @@ -181,7 +181,7 @@ public interface D2DIComponent { @VisibleForTesting Handler trackedEntityTypeHandler(); @VisibleForTesting - TrackedEntityInstancePostPayloadGenerator trackedEntityInstancePostPayloadGenerator(); + TrackedEntityInstancePostPayloadGenerator29 trackedEntityInstancePostPayloadGenerator(); @VisibleForTesting EventPostPayloadGenerator eventPostPayloadGenerator(); @VisibleForTesting diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt index 5932d61ac1..085d0dfc56 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt @@ -37,6 +37,7 @@ import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.imports.internal.EventWebResponse import org.hisp.dhis.android.core.systeminfo.DHISVersionManager +import org.hisp.dhis.android.core.trackedentity.internal.OldTrackerImporterPostCall @Reusable internal class OldEventPostCall @Inject internal constructor( @@ -45,20 +46,30 @@ internal class OldEventPostCall @Inject internal constructor( private val eventService: EventService, private val apiCallExecutor: APICallExecutor, private val eventImportHandler: EventImportHandler, - private val stateManager: EventPostStateManager + private val stateManager: EventPostStateManager, + private val oldTrackerImporterPostCall: OldTrackerImporterPostCall ) { - @Suppress("TooGenericExceptionCaught") - fun uploadEvents(filteredEvents: List): Observable { + fun uploadEvents(events: List): Observable { + return if (versionManager.is2_29) { + uploadEvents29(events) + } else { + oldTrackerImporterPostCall.uploadEvents(events) + } + } + + private fun uploadEvents29( + events: List + ): Observable { return Observable.defer { val eventPayload = EventPayload() - val eventsToPost = payloadGenerator.getEvents(filteredEvents) + val eventsToPost = payloadGenerator.getEvents(events) stateManager.markObjectsAs(eventsToPost, State.UPLOADING) val progressManager = D2ProgressManager(1) eventPayload.events = eventsToPost - val strategy = if (versionManager.is2_29) "CREATE_AND_UPDATE" else "SYNC" + val strategy = "CREATE_AND_UPDATE" try { val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( eventService.postEvents(eventPayload, strategy), @@ -76,11 +87,8 @@ internal class OldEventPostCall @Inject internal constructor( } private fun handleWebResponse(webResponse: EventWebResponse?, events: List) { - if (webResponse?.response() == null) { - return - } eventImportHandler.handleEventImportSummaries( - webResponse.response()!!.importSummaries(), + webResponse?.response()?.importSummaries(), events, null, null diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummaries.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummaries.java new file mode 100644 index 0000000000..86400ceaf2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummaries.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.core.imports.internal; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +import java.util.List; + +@AutoValue +@JsonDeserialize(builder = AutoValue_RelationshipImportSummaries.Builder.class) +public abstract class RelationshipImportSummaries + extends BaseImportSummaries + implements ImportSummaries { + + @Override + @Nullable + @JsonProperty() + public abstract List importSummaries(); + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder extends BaseImportSummaries.Builder { + + public abstract Builder importSummaries(List importSummaries); + + public abstract RelationshipImportSummaries build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummary.java similarity index 71% rename from core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.java rename to core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummary.java index 52936c1b94..1c365ec3e0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipImportSummary.java @@ -25,16 +25,21 @@ * (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.relationship.internal; -import org.hisp.dhis.android.core.imports.internal.RelationshipDeleteWebResponse; +package org.hisp.dhis.android.core.imports.internal; -import retrofit2.Call; -import retrofit2.http.DELETE; -import retrofit2.http.Path; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; -interface RelationshipService { +@AutoValue +@JsonDeserialize(builder = AutoValue_RelationshipImportSummary.Builder.class) +public abstract class RelationshipImportSummary extends BaseImportSummary { - @DELETE("relationships/{uid}") - Call deleteRelationship(@Path("uid") String relationship); -} \ No newline at end of file + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder extends BaseImportSummary.Builder { + + public abstract RelationshipImportSummary build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponse.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponse.java new file mode 100644 index 0000000000..3584f38aa2 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponse.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004-2021, 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.core.imports.internal; + +import androidx.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.google.auto.value.AutoValue; + +@AutoValue +@JsonDeserialize(builder = AutoValue_RelationshipWebResponse.Builder.class) +public abstract class RelationshipWebResponse extends WebResponse { + + @Nullable + @JsonProperty() + public abstract RelationshipImportSummaries response(); + + public static Builder builder() { + return new AutoValue_RelationshipWebResponse.Builder(); + } + + public static RelationshipWebResponse empty() { + return builder() + .httpStatus("SUCCESS") + .httpStatusCode(200) + .message("Emtpy response") + .status("OK") + .build(); + } + + @AutoValue.Builder + @JsonPOJOBuilder(withPrefix = "") + public static abstract class Builder extends WebResponse.Builder { + public abstract Builder response(RelationshipImportSummaries response); + + public abstract RelationshipWebResponse build(); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt similarity index 62% rename from core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java rename to core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt index 7b9683ebd1..b8709c3215 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt @@ -25,40 +25,26 @@ * (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.imports.internal -package org.hisp.dhis.android.core.imports.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceImportHandler; - -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; +import dagger.Reusable +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceImportHandler +import javax.inject.Inject @Reusable -public final class TEIWebResponseHandler { - private final TrackedEntityInstanceImportHandler trackedEntityInstanceImportHandler; - - @Inject - public TEIWebResponseHandler(@NonNull TrackedEntityInstanceImportHandler trackedEntityInstanceImportHandler) { - this.trackedEntityInstanceImportHandler = trackedEntityInstanceImportHandler; - } - - public void handleWebResponse(@NonNull TEIWebResponse webResponse, - @NonNull List instances) { - if (webResponse == null || webResponse.response() == null) { - return; +internal class TEIWebResponseHandler @Inject constructor( + private val trackedEntityInstanceImportHandler: TrackedEntityInstanceImportHandler +) { + + fun handleWebResponse( + webResponse: TEIWebResponse?, + instances: List + ) { + webResponse?.response()?.let { response -> + trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( + response.importSummaries(), instances + ) } - - TEIImportSummaries importSummaries = webResponse.response(); - - trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( - importSummaries.importSummaries(), instances - ); - } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java deleted file mode 100644 index eda9b06bac..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipDeleteCall.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.relationship.internal; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.common.CoreColumns; -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.imports.ImportStatus; -import org.hisp.dhis.android.core.imports.internal.RelationshipDeleteWebResponse; -import org.hisp.dhis.android.core.systeminfo.DHISVersionManager; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Reusable; -import io.reactivex.Completable; - -import static org.hisp.dhis.android.core.arch.helpers.CollectionsHelper.isDeleted; - -@Reusable -public final class RelationshipDeleteCall { - - private final RelationshipService relationshipService; - - private final RelationshipStore relationshipStore; - - private final APICallExecutor apiCallExecutor; - - private final DHISVersionManager dhisVersionManager; - - @Inject - RelationshipDeleteCall(@NonNull RelationshipService relationshipService, - @NonNull RelationshipStore relationshipStore, - @NonNull APICallExecutor apiCallExecutor, - @NonNull DHISVersionManager dhisVersionManager) { - this.relationshipService = relationshipService; - this.relationshipStore = relationshipStore; - this.apiCallExecutor = apiCallExecutor; - this.dhisVersionManager = dhisVersionManager; - } - - @SuppressWarnings({"PMD.AvoidInstantiatingObjectsInLoops"}) - public List postDeletedRelationships(List trackedEntityInstances) { - List withoutDeletedRelationships = new ArrayList<>(trackedEntityInstances.size()); - - for (TrackedEntityInstance instance : trackedEntityInstances) { - List relationships = TrackedEntityInstanceInternalAccessor - .accessRelationships(instance); - - if (relationships == null || relationships.isEmpty()) { - withoutDeletedRelationships.add(instance); - } else { - List nonDeletedRelationships = new ArrayList<>(); - for (Relationship229Compatible relationship : relationships) { - if (isDeleted(relationship)) { - deleteRelationship(relationship).blockingAwait(); - } else { - nonDeletedRelationships.add(relationship); - } - } - TrackedEntityInstance newInstance = TrackedEntityInstanceInternalAccessor - .insertRelationships(instance.toBuilder(), nonDeletedRelationships) - .build(); - withoutDeletedRelationships.add(newInstance); - } - } - return withoutDeletedRelationships; - } - - private Completable deleteRelationship(Relationship229Compatible relationship) { - return Completable.fromCallable(() -> { - if (dhisVersionManager.is2_29()) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(CoreColumns.ID, relationship.id()).build(); - relationshipStore.deleteWhereIfExists(whereClause); - return RelationshipDeleteWebResponse.empty(); - } else { - RelationshipDeleteWebResponse httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( - relationshipService.deleteRelationship(relationship.uid()), - Collections.singletonList(404), - RelationshipDeleteWebResponse.class); - - ImportStatus status = httpResponse.response() == null ? null : httpResponse.response().status(); - - if (httpResponse.httpStatusCode() == 200 && ImportStatus.SUCCESS.equals(status) || - httpResponse.httpStatusCode() == 404) { - relationshipStore.delete(relationship.uid()); - } else { - // TODO Implement better handling - // The relationship is marked as error, but there is no handling in the TEI. The TEI is being posted - relationshipStore.setSyncState(relationship.uid(), State.ERROR); - } - return httpResponse; - } - }); - } - -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt similarity index 72% rename from core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.java rename to core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt index e273e97063..35063cdbb6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt @@ -25,23 +25,20 @@ * (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.relationship.internal -package org.hisp.dhis.android.core.relationship.internal; +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType +import org.hisp.dhis.android.core.relationship.RelationshipItem -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; -import org.hisp.dhis.android.core.relationship.RelationshipConstraintType; -import org.hisp.dhis.android.core.relationship.RelationshipItem; +internal interface RelationshipItemStore : ObjectWithoutUidStore { -import java.util.List; + fun getRelationshipUidsForItems(from: RelationshipItem, to: RelationshipItem): List -import androidx.annotation.NonNull; + fun getForRelationshipUidAndConstraintType( + uid: String, + constraintType: RelationshipConstraintType + ): RelationshipItem -public interface RelationshipItemStore extends ObjectWithoutUidStore { - List getRelationshipUidsForItems(@NonNull RelationshipItem from, @NonNull RelationshipItem to); - - RelationshipItem getForRelationshipUidAndConstraintType( - @NonNull String uid, - @NonNull RelationshipConstraintType constraintType); - - List getRelatedTeiUids(List trackedEntityInstanceUids); + fun getRelatedTeiUids(trackedEntityInstanceUids: List): List } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.java deleted file mode 100644 index 876b3b09b2..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.relationship.internal; - -import android.database.Cursor; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl; -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.binders.internal.WhereStatementBinder; -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStoreImpl; -import org.hisp.dhis.android.core.arch.helpers.UidsHelper; -import org.hisp.dhis.android.core.relationship.RelationshipConstraintType; -import org.hisp.dhis.android.core.relationship.RelationshipItem; -import org.hisp.dhis.android.core.relationship.RelationshipItemTableInfo; -import org.hisp.dhis.android.core.relationship.RelationshipItemTableInfo.Columns; - -import java.util.ArrayList; -import java.util.List; - -public final class RelationshipItemStoreImpl extends ObjectWithoutUidStoreImpl - implements RelationshipItemStore { - - private static final StatementBinder BINDER = (o, w) -> { - String trackedEntityInstance = o.trackedEntityInstance() == null ? null : - o.trackedEntityInstance().trackedEntityInstance(); - String enrollment = o.enrollment() == null ? null : o.enrollment().enrollment(); - String event = o.event() == null ? null : o.event().event(); - - w.bind(1, UidsHelper.getUidOrNull(o.relationship())); - w.bind(2, o.relationshipItemType()); - w.bind(3, trackedEntityInstance); - w.bind(4, enrollment); - w.bind(5, event); - }; - - private static final WhereStatementBinder WHERE_UPDATE_BINDER = (o, w) -> { - w.bind(6, UidsHelper.getUidOrNull(o.relationship())); - w.bind(7, o.relationshipItemType()); - }; - - private static final WhereStatementBinder WHERE_DELETE_BINDER = (o, w) -> { - w.bind(1, UidsHelper.getUidOrNull(o.relationship())); - w.bind(2, o.relationshipItemType()); - }; - - private RelationshipItemStoreImpl(DatabaseAdapter databaseAdapter, - SQLStatementBuilderImpl builder) { - super(databaseAdapter, builder, BINDER, WHERE_UPDATE_BINDER, WHERE_DELETE_BINDER, RelationshipItem::create); - } - - @Override - public List getRelationshipUidsForItems(@NonNull RelationshipItem from, @NonNull RelationshipItem to) { - List relationships = new ArrayList<>(); - try (Cursor cursor = this.getAllItemsOfSameType(from, to)) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - do { - String relationshipInDb = cursor.getString(0); - String fromElementUidInDb = cursor.getString(1); - String toElementUidInDb = cursor.getString(2); - - if (from.elementUid().equals(fromElementUidInDb) && to.elementUid().equals(toElementUidInDb)) { - relationships.add(relationshipInDb); - } - } - while (cursor.moveToNext()); - } - } - - return relationships; - } - - @Override - public RelationshipItem getForRelationshipUidAndConstraintType( - @NonNull String uid, - @NonNull RelationshipConstraintType constraintType) { - String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP, uid) - .appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE, constraintType) - .build(); - return selectOneWhere(whereClause); - } - - @Override - public List getRelatedTeiUids(List trackedEntityInstanceUids) { - String whereFromClause = new WhereClauseBuilder() - .appendInKeyStringValues(Columns.TRACKED_ENTITY_INSTANCE, trackedEntityInstanceUids) - .appendKeyStringValue(Columns.RELATIONSHIP_ITEM_TYPE, - RelationshipConstraintType.FROM) - .build(); - List relationshipItems = selectWhere(whereFromClause); - List relationshipUids = new ArrayList<>(); - for (RelationshipItem relationshipItem : relationshipItems) { - relationshipUids.add(relationshipItem.relationship().uid()); - } - - String whereToClause = new WhereClauseBuilder() - .appendInKeyStringValues(Columns.RELATIONSHIP, relationshipUids) - .appendKeyStringValue(Columns.RELATIONSHIP_ITEM_TYPE, RelationshipConstraintType.TO) - .appendIsNotNullValue(Columns.TRACKED_ENTITY_INSTANCE) - .build(); - List relatedRelationshipItems = selectWhere(whereToClause); - List relatedTEiUids = new ArrayList<>(); - for (RelationshipItem relationshipItem : relatedRelationshipItems) { - relatedTEiUids.add(relationshipItem.trackedEntityInstance().trackedEntityInstance()); - } - return relatedTEiUids; - } - - private Cursor getAllItemsOfSameType(@NonNull RelationshipItem from, @NonNull RelationshipItem to) { - String query = "SELECT " + RelationshipItemTableInfo.Columns.RELATIONSHIP + ", " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + - "THEN " + getItemElementColumn(from) + " END) AS fromElementUid, " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + - "THEN " + getItemElementColumn(to) + " END) AS toElementUid " + - "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + - " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP; - - return this.getDatabaseAdapter().rawQuery(query); - } - - private String getItemElementColumn(RelationshipItem item) { - if (item.hasTrackedEntityInstance()) { - return Columns.TRACKED_ENTITY_INSTANCE; - } else if (item.hasEnrollment()) { - return Columns.ENROLLMENT; - } else { - return Columns.EVENT; - } - } - - public static RelationshipItemStore create(DatabaseAdapter databaseAdapter) { - SQLStatementBuilderImpl statementBuilder = new SQLStatementBuilderImpl( - RelationshipItemTableInfo.TABLE_INFO.name(), new RelationshipItemTableInfo.Columns()); - - return new RelationshipItemStoreImpl( - databaseAdapter, - statementBuilder - ); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt new file mode 100644 index 0000000000..ea4ffecc54 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import android.database.Cursor +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +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 +import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStoreImpl +import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidOrNull +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType +import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.hisp.dhis.android.core.relationship.RelationshipItemTableInfo +import java.util.* + +internal class RelationshipItemStoreImpl private constructor( + databaseAdapter: DatabaseAdapter, + builder: SQLStatementBuilderImpl +) : ObjectWithoutUidStoreImpl( + databaseAdapter, + builder, + BINDER, + WHERE_UPDATE_BINDER, + WHERE_DELETE_BINDER, + { cursor: Cursor -> RelationshipItem.create(cursor) }), RelationshipItemStore { + + override fun getRelationshipUidsForItems(from: RelationshipItem, to: RelationshipItem): List { + val relationships: MutableList = ArrayList() + + getAllItemsOfSameType(from, to).use { cursor -> + if (cursor.count > 0) { + cursor.moveToFirst() + do { + val relationshipInDb = cursor.getString(0) + val fromElementUidInDb = cursor.getString(1) + val toElementUidInDb = cursor.getString(2) + if (from.elementUid() == fromElementUidInDb && to.elementUid() == toElementUidInDb) { + relationships.add(relationshipInDb) + } + } while (cursor.moveToNext()) + } + } + return relationships + } + + override fun getForRelationshipUidAndConstraintType( + uid: String, + constraintType: RelationshipConstraintType + ): RelationshipItem { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP, uid) + .appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE, constraintType) + .build() + return selectOneWhere(whereClause)!! + } + + override fun getRelatedTeiUids(trackedEntityInstanceUids: List): List { + val whereFromClause = WhereClauseBuilder() + .appendInKeyStringValues( + RelationshipItemTableInfo.Columns.TRACKED_ENTITY_INSTANCE, + trackedEntityInstanceUids + ) + .appendKeyStringValue( + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE, + RelationshipConstraintType.FROM + ) + .build() + + val relationshipItems = selectWhere(whereFromClause) + val relationshipUids = relationshipItems.map { it.relationship()!!.uid() } + + val whereToClause = WhereClauseBuilder() + .appendInKeyStringValues(RelationshipItemTableInfo.Columns.RELATIONSHIP, relationshipUids) + .appendKeyStringValue( + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE, + RelationshipConstraintType.TO + ) + .appendIsNotNullValue(RelationshipItemTableInfo.Columns.TRACKED_ENTITY_INSTANCE) + .build() + + val relatedRelationshipItems = selectWhere(whereToClause) + + return relatedRelationshipItems.map { it.trackedEntityInstance()!!.trackedEntityInstance() } + } + + private fun getAllItemsOfSameType(from: RelationshipItem, to: RelationshipItem): Cursor { + val query = "SELECT " + RelationshipItemTableInfo.Columns.RELATIONSHIP + ", " + + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + + "THEN " + getItemElementColumn(from) + " END) AS fromElementUid, " + + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + + "THEN " + getItemElementColumn(to) + " END) AS toElementUid " + + "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + + " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP + return databaseAdapter.rawQuery(query) + } + + private fun getItemElementColumn(item: RelationshipItem): String { + return when { + item.hasTrackedEntityInstance() -> RelationshipItemTableInfo.Columns.TRACKED_ENTITY_INSTANCE + item.hasEnrollment() -> RelationshipItemTableInfo.Columns.ENROLLMENT + else -> RelationshipItemTableInfo.Columns.EVENT + } + } + + companion object { + private val BINDER = StatementBinder { o: RelationshipItem, w: StatementWrapper -> + val trackedEntityInstance = if (o.trackedEntityInstance() == null) null else o.trackedEntityInstance()!! + .trackedEntityInstance() + val enrollment = if (o.enrollment() == null) null else o.enrollment()!!.enrollment() + val event = if (o.event() == null) null else o.event()!!.event() + w.bind(1, getUidOrNull(o.relationship())) + w.bind(2, o.relationshipItemType()) + w.bind(3, trackedEntityInstance) + w.bind(4, enrollment) + w.bind(5, event) + } + private val WHERE_UPDATE_BINDER = WhereStatementBinder { o: RelationshipItem, w: StatementWrapper -> + w.bind(6, getUidOrNull(o.relationship())) + w.bind(7, o.relationshipItemType()) + } + private val WHERE_DELETE_BINDER = WhereStatementBinder { o: RelationshipItem, w: StatementWrapper -> + w.bind(1, getUidOrNull(o.relationship())) + w.bind(2, o.relationshipItemType()) + } + + @JvmStatic + fun create(databaseAdapter: DatabaseAdapter): RelationshipItemStore { + val statementBuilder = SQLStatementBuilderImpl( + RelationshipItemTableInfo.TABLE_INFO.name(), RelationshipItemTableInfo.Columns() + ) + return RelationshipItemStoreImpl( + databaseAdapter, + statementBuilder + ) + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPayload.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPayload.java new file mode 100644 index 0000000000..deb8889780 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPayload.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.auto.value.AutoValue; + +import org.hisp.dhis.android.core.relationship.Relationship; + +import java.util.List; + +@AutoValue +public abstract class RelationshipPayload { + + @JsonProperty() + public abstract List relationships(); + + public static Builder builder() { + return new AutoValue_RelationshipPayload.Builder(); + } + + public static RelationshipPayload create(List relationships) { + return builder().relationships(relationships).build(); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder relationships(List relationships); + + public abstract RelationshipPayload build(); + } + +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt new file mode 100644 index 0000000000..01889e0866 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import dagger.Reusable +import io.reactivex.Completable +import io.reactivex.Observable +import io.reactivex.ObservableEmitter +import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor +import org.hisp.dhis.android.core.arch.call.D2Progress +import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper +import org.hisp.dhis.android.core.common.CoreColumns +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.internal.RelationshipDeleteWebResponse +import org.hisp.dhis.android.core.imports.internal.RelationshipWebResponse +import org.hisp.dhis.android.core.relationship.Relationship +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor +import java.lang.Exception +import javax.inject.Inject + +@Reusable +internal class RelationshipPostCall @Inject internal constructor( + private val relationshipService: RelationshipService, + private val relationshipStore: RelationshipStore, + private val dataStatePropagator: DataStatePropagator, + private val apiCallExecutor: APICallExecutor +) { + + fun deleteRelationships(relationships: List): Observable { + return Observable.create { emitter: ObservableEmitter -> + for (relationship in relationships) { + val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( + relationshipService.deleteRelationship(relationship.uid()!!), listOf(404), + RelationshipDeleteWebResponse::class.java + ) + val status = httpResponse.response()?.status() + + if ((httpResponse.httpStatusCode() == 200 && ImportStatus.SUCCESS == status) || + httpResponse.httpStatusCode() == 404 + ) { + relationshipStore.delete(relationship.uid()!!) + } else { + // TODO Implement better handling + // The relationship is marked as error, but there is no handling in the TEI. The TEI is being posted + relationshipStore.setSyncState(relationship.uid()!!, State.ERROR) + } + dataStatePropagator.propagateRelationshipUpdate(relationship.from()) + } + emitter.onComplete() + } + } + + fun postRelationships(relationships: List): Observable { + return Observable.defer { + val progressManager = D2ProgressManager(null) + val payload = RelationshipPayload.builder().relationships(relationships).build() + + try { + val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( + relationshipService.postRelationship(payload), + listOf(409), + RelationshipWebResponse::class.java + ) + + // TODO Implement handler + Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) + } catch (e: Exception) { + Observable.error(e) + } + } + } + + fun postDeletedRelationships29(trackedEntityInstances: List): List { + return trackedEntityInstances.map { instance -> + val relationships = TrackedEntityInstanceInternalAccessor.accessRelationships(instance) + + if (relationships == null || relationships.isEmpty()) { + instance + } else { + val partitionedRelationships = relationships.partition { CollectionsHelper.isDeleted(it) } + + partitionedRelationships.first.forEach { + deleteRelationship29(it).blockingAwait() + } + + TrackedEntityInstanceInternalAccessor + .insertRelationships(instance.toBuilder(), partitionedRelationships.second) + .build() + } + } + } + + private fun deleteRelationship29(relationship: Relationship229Compatible): Completable { + return Completable.fromCallable { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(CoreColumns.ID, relationship.id()).build() + relationshipStore.deleteWhereIfExists(whereClause) + return@fromCallable RelationshipDeleteWebResponse.empty() + + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt new file mode 100644 index 0000000000..567eade4dd --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import retrofit2.http.DELETE +import org.hisp.dhis.android.core.relationship.internal.RelationshipService +import org.hisp.dhis.android.core.imports.internal.RelationshipDeleteWebResponse +import org.hisp.dhis.android.core.imports.internal.RelationshipWebResponse +import org.hisp.dhis.android.core.relationship.internal.RelationshipPayload +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.Path + +internal interface RelationshipService { + + @DELETE("$RELATIONSHIPS/{uid}") + fun deleteRelationship(@Path("uid") relationship: String): Call + + @DELETE(RELATIONSHIPS) + fun postRelationship(@Body payload: RelationshipPayload): Call + + companion object { + const val RELATIONSHIPS = "relationships" + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt index 9ef38a1252..1a7525a2d4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt @@ -30,43 +30,54 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.ObservableEmitter -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager +import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.imports.internal.TEIWebResponse import org.hisp.dhis.android.core.imports.internal.TEIWebResponseHandler import org.hisp.dhis.android.core.maintenance.D2Error -import org.hisp.dhis.android.core.relationship.internal.RelationshipDeleteCall +import org.hisp.dhis.android.core.relationship.internal.RelationshipPostCall import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import javax.inject.Inject @Reusable internal class OldTrackedEntityInstancePostCall @Inject internal constructor( - private val payloadGenerator: TrackedEntityInstancePostPayloadGenerator, + private val payloadGenerator29: TrackedEntityInstancePostPayloadGenerator29, private val stateManager: TrackedEntityInstancePostStateManager, private val versionManager: DHISVersionManager, private val trackedEntityInstanceService: TrackedEntityInstanceService, private val teiWebResponseHandler: TEIWebResponseHandler, private val apiCallExecutor: APICallExecutor, - private val relationshipDeleteCall: RelationshipDeleteCall + private val relationshipPostCall: RelationshipPostCall, + private val oldTrackerImporterPostCall: OldTrackerImporterPostCall ) { - @Suppress("TooGenericExceptionCaught") fun uploadTrackedEntityInstances( + trackedEntityInstances: List + ): Observable { + return if (versionManager.is2_29) { + uploadTrackedEntityInstances29(trackedEntityInstances) + } else { + oldTrackerImporterPostCall.uploadTrackedEntityInstances(trackedEntityInstances) + } + } + + private fun uploadTrackedEntityInstances29( filteredTrackedEntityInstances: List ): Observable { return Observable.create { emitter: ObservableEmitter -> - val strategy = if (versionManager.is2_29) "CREATE_AND_UPDATE" else "SYNC" - val teiPartitions = payloadGenerator.getTrackedEntityInstancesPartitions(filteredTrackedEntityInstances) + val teiPartitions = payloadGenerator29.getTrackedEntityInstancesPartitions29(filteredTrackedEntityInstances) val progressManager = D2ProgressManager(teiPartitions.size) for (partition in teiPartitions) { - val thisPartition = relationshipDeleteCall.postDeletedRelationships(partition) - val trackedEntityInstancePayload = TrackedEntityInstancePayload.create(thisPartition) + stateManager.setPartitionStates(partition, State.UPLOADING) + val thisPartition = relationshipPostCall.postDeletedRelationships29(partition) try { + val trackedEntityInstancePayload = TrackedEntityInstancePayload.create(thisPartition) val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( trackedEntityInstanceService.postTrackedEntityInstances( - trackedEntityInstancePayload, strategy + trackedEntityInstancePayload, "CREATE_AND_UPDATE" ), @Suppress("MagicNumber") listOf(409), @@ -76,7 +87,6 @@ internal class OldTrackedEntityInstancePostCall @Inject internal constructor( emitter.onNext(progressManager.increaseProgress(TrackedEntityInstance::class.java, false)) } catch (e: Exception) { stateManager.restorePartitionStates(thisPartition) - if (e is D2Error && e.isOffline) { emitter.onError(e) break diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt new file mode 100644 index 0000000000..e1f95254aa --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.relationship.Relationship +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance + +internal data class OldTrackerImporterPayload( + val trackedEntityInstances: List = emptyList(), + val events: List = emptyList(), + val relationships: List = emptyList() +) { + fun isEmpty(): Boolean = trackedEntityInstances.isEmpty() && events.isEmpty() && relationships.isEmpty() + + fun isNotEmpty(): Boolean = trackedEntityInstances.isNotEmpty() || events.isNotEmpty() || relationships.isNotEmpty() + + fun concat(other: OldTrackerImporterPayload): OldTrackerImporterPayload { + return OldTrackerImporterPayload( + trackedEntityInstances = trackedEntityInstances + other.trackedEntityInstances, + events = events + other.events, + relationships = relationships + other.relationships + ) + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt new file mode 100644 index 0000000000..e0a10ba975 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.common.DataColumns +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.enrollment.EnrollmentInternalAccessor +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.note.Note +import org.hisp.dhis.android.core.note.internal.NoteToPostTransformer +import org.hisp.dhis.android.core.relationship.Relationship +import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.systeminfo.DHISVersionManager +import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor +import javax.inject.Inject + +@Reusable +internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( + private val versionManager: DHISVersionManager, + private val relationshipRepository: RelationshipCollectionRepository, + private val trackedEntityInstanceStore: TrackedEntityInstanceStore, + private val enrollmentStore: EnrollmentStore, + private val eventStore: EventStore, + private val trackedEntityDataValueStore: TrackedEntityDataValueStore, + private val trackedEntityAttributeValueStore: TrackedEntityAttributeValueStore, + private val noteStore: IdentifiableObjectStore +) { + + private val noteTransformer = NoteToPostTransformer(versionManager) + + private data class ExtraData( + val dataValueMap: Map>, + val eventMap: Map>, + val enrollmentMap: Map>, + val attributeValueMap: Map>, + val notes: List, + val relationships: List + ) + + fun getTrackedEntityInstancePayload( + trackedEntityInstances: List + ): OldTrackerImporterPayload { + val extraData = getExtraData() + + val recreatedTeis = trackedEntityInstances.map { + getTrackedEntityInstance(it, extraData) + } + + val payload = OldTrackerImporterPayload(trackedEntityInstances = recreatedTeis) + + return addRelationships(payload, extraData) + } + + fun getEventPayload( + events: List + ): OldTrackerImporterPayload { + val extraData = getExtraData() + + val recreatedEvents = events.map { + getEvent(it, extraData) + } + + val payload = OldTrackerImporterPayload(events = recreatedEvents) + + return addRelationships(payload, extraData) + } + + private fun addRelationships( + payload: OldTrackerImporterPayload, + extraData: ExtraData + ): OldTrackerImporterPayload { + val payloadWithRelationships = payload.copy( + relationships = extractRelationships(payload, extraData) + ) + + return addRelatedItems(payloadWithRelationships, extraData) + } + + private fun addRelatedItems( + payload: OldTrackerImporterPayload, + extraData: ExtraData + ): OldTrackerImporterPayload { + var accPayload = payload + var relatedItems = getMissingItems(payload, extraData) + + while (relatedItems.isNotEmpty()) { + accPayload = accPayload.concat(relatedItems) + relatedItems = getMissingItems(accPayload, extraData) + } + + return accPayload + } + + private fun getMissingItems( + payload: OldTrackerImporterPayload, + extraData: ExtraData + ): OldTrackerImporterPayload { + val relatedItems = payload.relationships.map { it.to() } + + val missingItems = relatedItems.filterNotNull().filter { item -> + when { + item.hasTrackedEntityInstance() -> isMissingTei(item.elementUid(), payload) + item.hasEnrollment() -> isMissingEnrollment(item.elementUid(), payload) + item.hasEvent() -> isMissingEvent(item.elementUid(), payload) + else -> false + } + } + + val missingTeis = mutableSetOf() + val missingEvents = mutableSetOf() + + missingItems.forEach { item -> + when { + item.hasTrackedEntityInstance() -> missingTeis.add(item.elementUid()) + item.hasEnrollment() -> { + enrollmentStore.selectByUid(item.elementUid())?.let { + missingTeis.add(it.trackedEntityInstance()!!) + } + } + item.hasEvent() -> { + eventStore.selectByUid(item.elementUid())?.let { event -> + if (event.enrollment() == null) { + missingEvents.add(event.uid()) + } else { + enrollmentStore.selectByUid(event.enrollment()!!)?.let { + missingTeis.add(it.trackedEntityInstance()!!) + } + } + } + } + } + } + + val trackedEntityInstances = trackedEntityInstanceStore.selectByUids(missingTeis.toList()) + val events = eventStore.selectByUids(missingEvents.toList()) + + return OldTrackerImporterPayload( + trackedEntityInstances = trackedEntityInstances, + events = events + ).run { + copy(relationships = extractRelationships(payload, extraData)) + } + } + + private fun isMissingTei(uid: String, payload: OldTrackerImporterPayload): Boolean { + val isIncludeInPayload = payload.trackedEntityInstances.map { it.uid() }.contains(uid) + val isPendingToSync: Boolean by lazy { + val dbTei = trackedEntityInstanceStore.selectByUid(uid) + State.uploadableStates().contains(dbTei?.aggregatedSyncState()) + } + + return !isIncludeInPayload && isPendingToSync + } + + private fun isMissingEnrollment(uid: String, payload: OldTrackerImporterPayload): Boolean { + val enrollments = payload.trackedEntityInstances.flatMap { + TrackedEntityInstanceInternalAccessor.accessEnrollments(it) + } + val isIncludeInPayload = enrollments.map { it.uid() }.contains(uid) + val isPendingToSync: Boolean by lazy { + val enrollment = enrollmentStore.selectByUid(uid) + State.uploadableStates().contains(enrollment?.aggregatedSyncState()) + } + + return !isIncludeInPayload && isPendingToSync + } + + private fun isMissingEvent(uid: String, payload: OldTrackerImporterPayload): Boolean { + val events = payload.trackedEntityInstances.flatMap { + TrackedEntityInstanceInternalAccessor.accessEnrollments(it) + }.flatMap { + EnrollmentInternalAccessor.accessEvents(it) + } + val isIncludedInPayload = events.map { it.uid() }.contains(uid) + val isPendingToSync: Boolean by lazy { + val event = eventStore.selectByUid(uid) + State.uploadableStates().contains(event?.aggregatedSyncState()) + } + + return !isIncludedInPayload && isPendingToSync + } + + private fun getExtraData(): ExtraData { + return ExtraData( + dataValueMap = trackedEntityDataValueStore.queryByUploadableEvents(), + eventMap = eventStore.queryEventsAttachedToEnrollmentToPost(), + enrollmentMap = enrollmentStore.queryEnrollmentsToPost(), + attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost(), + notes = noteStore.selectWhere(WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } + ) + .build()), + relationships = relationshipRepository.bySyncState() + .`in`(State.uploadableStatesIncludingError().toList()) + .withItems() + .blockingGet() + ) + } + + private fun extractRelationships( + payload: OldTrackerImporterPayload, + extraData: ExtraData + ): List { + val teiItems = payload.trackedEntityInstances.map { + RelationshipHelper.teiItem(it.uid()) + } + + val enrollments = payload.trackedEntityInstances.flatMap { + TrackedEntityInstanceInternalAccessor.accessEnrollments(it) + } + val enrollmentItems = enrollments.map { + RelationshipHelper.enrollmentItem(it.uid()) + } + + val events = enrollments.flatMap { EnrollmentInternalAccessor.accessEvents(it) } + payload.events + val eventItems = events.map { + RelationshipHelper.eventItem(it.uid()) + } + + val items = teiItems + enrollmentItems + eventItems + + return extraData.relationships.filter { + items.any { item -> RelationshipHelper.areItemsEqual(it.from(), item) } + } + } + + private fun getTrackedEntityInstance( + trackedEntityInstance: TrackedEntityInstance, + extraData: ExtraData + ): TrackedEntityInstance { + val enrollmentsRecreated = getEnrollments(extraData, trackedEntityInstance.uid()) + val attributeValues = extraData.attributeValueMap[trackedEntityInstance.uid()] + return TrackedEntityInstanceInternalAccessor + .insertEnrollments(trackedEntityInstance.toBuilder(), enrollmentsRecreated) + .trackedEntityAttributeValues(attributeValues ?: emptyList()) + .build() + } + + private fun getEnrollments( + extraData: ExtraData, + trackedEntityInstanceUid: String + ): List { + return extraData.enrollmentMap[trackedEntityInstanceUid]?.map { enrollment -> + val events = extraData.eventMap[enrollment.uid()]?.map { event -> + getEvent(event, extraData) + } ?: emptyList() + + EnrollmentInternalAccessor.insertEvents(enrollment.toBuilder(), events) + .notes(getEnrollmentNotes(extraData.notes, enrollment)) + .build() + } ?: emptyList() + } + + private fun getEvent(event: Event, extraData: ExtraData): Event { + val eventBuilder = event.toBuilder() + .trackedEntityDataValues(extraData.dataValueMap[event.uid()]) + .notes(getEventNotes(extraData.notes, event)) + + if (versionManager.is2_30) { + eventBuilder.geometry(null) + } + + return eventBuilder.build() + } + + private fun getEventNotes(notes: List, event: Event): List { + return notes + .filter { it.event() == event.uid() } + .map { noteTransformer.transform(it) } + } + + private fun getEnrollmentNotes(notes: List, enrollment: Enrollment): List { + return notes + .filter { it.enrollment() == enrollment.uid() } + .map { noteTransformer.transform(it) } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt new file mode 100644 index 0000000000..aebfa8c86a --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import dagger.Reusable +import io.reactivex.Observable +import io.reactivex.ObservableEmitter +import javax.inject.Inject +import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor +import org.hisp.dhis.android.core.arch.call.D2Progress +import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.internal.EventImportHandler +import org.hisp.dhis.android.core.event.internal.EventPayload +import org.hisp.dhis.android.core.event.internal.EventPostStateManager +import org.hisp.dhis.android.core.event.internal.EventService +import org.hisp.dhis.android.core.imports.internal.EventWebResponse +import org.hisp.dhis.android.core.imports.internal.TEIWebResponse +import org.hisp.dhis.android.core.imports.internal.TEIWebResponseHandler +import org.hisp.dhis.android.core.maintenance.D2Error +import org.hisp.dhis.android.core.relationship.internal.RelationshipPostCall +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance + +@Reusable +internal class OldTrackerImporterPostCall @Inject internal constructor( + private val trackerImporterPayloadGenerator: OldTrackerImporterPayloadGenerator, + private val trackedEntityInstanceStateManager: TrackedEntityInstancePostStateManager, + private val eventPostStateManager: EventPostStateManager, + private val trackedEntityInstanceService: TrackedEntityInstanceService, + private val eventService: EventService, + private val teiWebResponseHandler: TEIWebResponseHandler, + private val eventImportHandler: EventImportHandler, + private val apiCallExecutor: APICallExecutor, + private val relationshipPostCall: RelationshipPostCall +) { + + fun uploadTrackedEntityInstances( + trackedEntityInstances: List + ): Observable { + val payload = trackerImporterPayloadGenerator.getTrackedEntityInstancePayload(trackedEntityInstances) + return uploadPayload(payload) + } + + fun uploadEvents( + events: List + ): Observable { + val payload = trackerImporterPayloadGenerator.getEventPayload(events) + return uploadPayload(payload) + } + + private fun uploadPayload( + payload: OldTrackerImporterPayload + ): Observable { + return Observable.defer { + val partitionedRelationships = payload.relationships.partition { it.deleted()!! } + + Observable.concat( + relationshipPostCall.deleteRelationships(partitionedRelationships.first), + postTrackedEntityInstances(payload.trackedEntityInstances), + postEvents(payload.events), + relationshipPostCall.postRelationships(partitionedRelationships.second) + ) + } + } + + private fun postTrackedEntityInstances( + trackedEntityInstances: List + ): Observable { + return Observable.create { emitter: ObservableEmitter -> + val progressManager = D2ProgressManager(null) + val teiPartitions = trackedEntityInstances.chunked(TrackedEntityInstanceService.DEFAULT_PAGE_SIZE) + + for (partition in teiPartitions) { + try { + trackedEntityInstanceStateManager.setPartitionStates(partition, State.UPLOADING) + val trackedEntityInstancePayload = TrackedEntityInstancePayload.create(partition) + val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( + trackedEntityInstanceService.postTrackedEntityInstances( + trackedEntityInstancePayload, "SYNC" + ), + @Suppress("MagicNumber") + listOf(409), + TEIWebResponse::class.java + ) + teiWebResponseHandler.handleWebResponse(webResponse, partition) + emitter.onNext(progressManager.increaseProgress(TrackedEntityInstance::class.java, false)) + } catch (e: Exception) { + trackedEntityInstanceStateManager.restorePartitionStates(partition) + if (e is D2Error && e.isOffline) { + emitter.onError(e) + break + } else { + emitter.onNext( + progressManager.increaseProgress( + TrackedEntityInstance::class.java, + false + ) + ) + } + } + } + emitter.onComplete() + } + } + + private fun postEvents( + events: List + ): Observable { + return Observable.defer { + val eventPayload = EventPayload() + eventPostStateManager.markObjectsAs(events, State.UPLOADING) + + val progressManager = D2ProgressManager(null) + + eventPayload.events = events + val strategy = "SYNC" + try { + val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( + eventService.postEvents(eventPayload, strategy), + @Suppress("MagicNumber") + listOf(409), + EventWebResponse::class.java + ) + eventImportHandler.handleEventImportSummaries( + eventImportSummaries = webResponse?.response()?.importSummaries(), + events = events, + // TODO Manage tracker events + enrollmentUid = null, + teiUid = null + ) + Observable.just(progressManager.increaseProgress(Event::class.java, true)) + } catch (e: Exception) { + eventPostStateManager.markObjectsAs(events, State.TO_UPDATE) + Observable.error(e) + } + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStore.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStore.java index d83d15e593..de78803be0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStore.java @@ -47,4 +47,6 @@ public interface TrackedEntityDataValueStore extends ObjectWithoutUidStore> querySingleEventsTrackedEntityDataValues(); Map> queryTrackerTrackedEntityDataValues(); + + Map> queryByUploadableEvents(); } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java index 25969f38c2..57d6b7f40b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityDataValueStoreImpl.java @@ -144,6 +144,16 @@ public Map> queryTrackerTrackedEntityDataVa return queryTrackedEntityDataValues(queryStatement); } + @Override + public Map> queryByUploadableEvents() { + + String queryStatement = "SELECT TrackedEntityDataValue.* " + + " FROM (TrackedEntityDataValue INNER JOIN Event ON TrackedEntityDataValue.event = Event.uid) " + + " WHERE " + eventInUploadableState() + ";"; + + return queryTrackedEntityDataValues(queryStatement); + } + private Map> queryTrackedEntityDataValues(String queryStatement) { List dataValueList = new ArrayList<>(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt index 3339f21d2e..9864f9a310 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt @@ -49,8 +49,7 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo -@Reusable -internal class TrackedEntityInstanceImportHandler @Inject internal constructor( +@Reusable class TrackedEntityInstanceImportHandler @Inject internal constructor( private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentImportHandler: EnrollmentImportHandler, private val trackerImportConflictStore: TrackerImportConflictStore, diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt similarity index 71% rename from core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt rename to core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt index e2f2367c08..52146c4539 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt @@ -28,11 +28,8 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable -import java.util.ArrayList -import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore -import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidsList import org.hisp.dhis.android.core.common.DataColumns import org.hisp.dhis.android.core.common.State @@ -52,10 +49,10 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor +import javax.inject.Inject -@Suppress("LongParameterList") @Reusable -internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constructor( +internal class TrackedEntityInstancePostPayloadGenerator29 @Inject internal constructor( private val versionManager: DHISVersionManager, private val relationshipDHISVersionManager: RelationshipDHISVersionManager, private val relationshipRepository: RelationshipCollectionRepository, @@ -65,41 +62,49 @@ internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constr private val trackedEntityDataValueStore: TrackedEntityDataValueStore, private val trackedEntityAttributeValueStore: TrackedEntityAttributeValueStore, private val relationshipItemStore: RelationshipItemStore, - private val noteStore: IdentifiableObjectStore, - private val stateManager: TrackedEntityInstancePostStateManager + private val noteStore: IdentifiableObjectStore ) { - fun getTrackedEntityInstancesPartitions( + private data class ExtraData( + val dataValueMap: Map>, + val eventMap: Map>, + val enrollmentMap: Map>, + val attributeValueMap: Map>, + val notes: List + ) + + fun getTrackedEntityInstancesPartitions29( filteredTrackedEntityInstances: List ): List> { - val dataValueMap = trackedEntityDataValueStore.queryTrackerTrackedEntityDataValues() - val eventMap = eventStore.queryEventsAttachedToEnrollmentToPost() - val enrollmentMap = enrollmentStore.queryEnrollmentsToPost() - val attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost() - val whereNotesClause = WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } - ) - .build() - val notes = noteStore.selectWhere(whereNotesClause) + val extraData = getExtraData() val trackedEntityInstancesToSync = getPagedTrackedEntityInstances(filteredTrackedEntityInstances) return trackedEntityInstancesToSync.map { partition -> - val partitionRecreated = partition.map { trackedEntityInstance -> - getTrackedEntityInstance( - trackedEntityInstance, dataValueMap, eventMap, enrollmentMap, attributeValueMap, notes - ) + partition.map { trackedEntityInstance -> + getTrackedEntityInstance(trackedEntityInstance, extraData) } - - stateManager.setPartitionStates(partitionRecreated, State.UPLOADING) - partitionRecreated } } + private fun getExtraData(): ExtraData { + return ExtraData( + dataValueMap = trackedEntityDataValueStore.queryByUploadableEvents(), + eventMap = eventStore.queryEventsAttachedToEnrollmentToPost(), + enrollmentMap = enrollmentStore.queryEnrollmentsToPost(), + attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost(), + notes = noteStore.selectWhere(WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } + ) + .build()) + ) + } + private fun getPagedTrackedEntityInstances( filteredTrackedEntityInstances: List ): List> { + val partitions = filteredTrackedEntityInstances.chunked(TrackedEntityInstanceService.DEFAULT_PAGE_SIZE) + val includedUids: MutableSet = mutableSetOf() - val partitions = CollectionsHelper.setPartition(filteredTrackedEntityInstances, DEFAULT_PAGE_SIZE) val partitionsWithRelationships: MutableList> = ArrayList() for (partition in partitions) { val partitionWithoutDuplicates = partition.filterNot { o -> includedUids.contains(o.uid()) } @@ -119,16 +124,19 @@ internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constr val filteredUids: List = filteredTrackedEntityInstances.map { it.uid() } val teiUidsToPost = trackedEntityInstanceStore.queryTrackedEntityInstancesToPost().map { it.uid() } val relatedTeisToPost: MutableList = ArrayList() + var internalRelatedTeis = filteredUids do { val relatedTeiUids = relationshipItemStore.getRelatedTeiUids(internalRelatedTeis) - relatedTeiUids.retainAll(teiUidsToPost) - relatedTeiUids.removeAll(filteredUids) - relatedTeiUids.removeAll(relatedTeisToPost) - relatedTeiUids.removeAll(excludedUids) - relatedTeisToPost.addAll(relatedTeiUids) - internalRelatedTeis = relatedTeiUids + val filteredToPost = relatedTeiUids + .filter { teiUidsToPost.contains(it) } + .filter { !filteredUids.contains(it) } + .filter { !relatedTeisToPost.contains(it) } + .filter { !excludedUids.contains(it) } + relatedTeisToPost.addAll(filteredToPost) + internalRelatedTeis = filteredToPost } while (internalRelatedTeis.isNotEmpty()) + for (trackedEntityInstanceInDB in trackedEntityInstancesInDBToSync) { if (relatedTeisToPost.contains(trackedEntityInstanceInDB.uid())) { filteredTrackedEntityInstances.add(trackedEntityInstanceInDB) @@ -137,18 +145,12 @@ internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constr return filteredTrackedEntityInstances } - @Suppress("LongParameterList") private fun getTrackedEntityInstance( trackedEntityInstance: TrackedEntityInstance, - dataValueMap: Map>, - eventMap: Map>, - enrollmentMap: Map>, - attributeValueMap: Map>, - notes: List + extraData: ExtraData ): TrackedEntityInstance { - val enrollmentsRecreated = - getEnrollments(dataValueMap, eventMap, enrollmentMap, notes, trackedEntityInstance.uid()) - val attributeValues = attributeValueMap[trackedEntityInstance.uid()] + val enrollmentsRecreated = getEnrollments(extraData, trackedEntityInstance.uid()) + val attributeValues = extraData.attributeValueMap[trackedEntityInstance.uid()] val dbRelationships = relationshipRepository.getByItem(RelationshipHelper.teiItem(trackedEntityInstance.uid()), true) val ownedRelationships = @@ -166,30 +168,29 @@ internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constr } private fun getEnrollments( - dataValueMap: Map>, - eventMap: Map>, - enrollmentMap: Map>, - notes: List, + extraData: ExtraData, trackedEntityInstanceUid: String ): List { - return enrollmentMap[trackedEntityInstanceUid]?.map { enrollment -> + return extraData.enrollmentMap[trackedEntityInstanceUid]?.map { enrollment -> val transformer = NoteToPostTransformer(versionManager) - val events = eventMap[enrollment.uid()]?.map { event -> - val eventBuilder = event.toBuilder() - .trackedEntityDataValues(dataValueMap[event.uid()]) - .notes(getEventNotes(notes, event, transformer)) - if (versionManager.is2_30) { - eventBuilder.geometry(null).build() - } else { - eventBuilder.build() - } + val events = extraData.eventMap[enrollment.uid()]?.map { event -> + getEvent(event, extraData, transformer) } ?: emptyList() + EnrollmentInternalAccessor.insertEvents(enrollment.toBuilder(), events) - .notes(getEnrollmentNotes(notes, enrollment, transformer)) + .notes(getEnrollmentNotes(extraData.notes, enrollment, transformer)) .build() } ?: emptyList() } + private fun getEvent(event: Event, extraData: ExtraData, transformer: NoteToPostTransformer): Event { + val eventBuilder = event.toBuilder() + .trackedEntityDataValues(extraData.dataValueMap[event.uid()]) + .notes(getEventNotes(extraData.notes, event, transformer)) + + return eventBuilder.build() + } + private fun getEventNotes(notes: List, event: Event, t: NoteToPostTransformer): List { return notes .filter { it.event() == event.uid() } @@ -201,8 +202,4 @@ internal class TrackedEntityInstancePostPayloadGenerator @Inject internal constr .filter { it.enrollment() == enrollment.uid() } .map { t.transform(it) } } - - companion object { - private const val DEFAULT_PAGE_SIZE = 20 - } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceService.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceService.java index 696afe0e59..31a131895f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceService.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceService.java @@ -76,6 +76,8 @@ public interface TrackedEntityInstanceService { String ASSIGNED_USER_MODE = "assignedUserMode"; String ORDER = "order"; + Integer DEFAULT_PAGE_SIZE = 20; + @POST(TRACKED_ENTITY_INSTANCES) Call postTrackedEntityInstances( @Body TrackedEntityInstancePayload trackedEntityInstances, diff --git a/core/src/sharedTest/resources/imports/relationship_delete_web_response.json b/core/src/sharedTest/resources/imports/relationship_delete_web_response.json new file mode 100644 index 0000000000..1c48897133 --- /dev/null +++ b/core/src/sharedTest/resources/imports/relationship_delete_web_response.json @@ -0,0 +1,19 @@ +{ + "httpStatus": "OK", + "httpStatusCode": 200, + "status": "OK", + "message": "Import was successful.", + "response": { + "responseType": "ImportSummary", + "status": "SUCCESS", + "description": "Deletion of relationship wOhCbIpmVCp was successful", + "importCount": { + "imported": 0, + "updated": 0, + "ignored": 0, + "deleted": 1 + }, + "conflicts": [], + "reference": "wOhCbIpmVCp" + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/relationship_web_response.json b/core/src/sharedTest/resources/imports/relationship_web_response.json new file mode 100644 index 0000000000..8f52a68fb0 --- /dev/null +++ b/core/src/sharedTest/resources/imports/relationship_web_response.json @@ -0,0 +1,43 @@ +{ + "httpStatus": "OK", + "httpStatusCode": 200, + "status": "OK", + "message": "Import was successful.", + "response": { + "responseType": "ImportSummaries", + "status": "SUCCESS", + "imported": 2, + "updated": 0, + "deleted": 0, + "ignored": 0, + "importSummaries": [ + { + "responseType": "ImportSummary", + "status": "SUCCESS", + "importCount": { + "imported": 1, + "updated": 0, + "ignored": 0, + "deleted": 0 + }, + "conflicts": [], + "reference": "wOhCbIpmVCp", + "href": "https://play.dhis2.org/2.36.3/api/relationships/wOhCbIpmVCp" + }, + { + "responseType": "ImportSummary", + "status": "SUCCESS", + "importCount": { + "imported": 1, + "updated": 0, + "ignored": 0, + "deleted": 0 + }, + "conflicts": [], + "reference": "EdG77xZE29R", + "href": "https://play.dhis2.org/2.36.3/api/relationships/EdG77xZE29R" + } + ], + "total": 2 + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/imports/relationship_web_response_with_errors.json b/core/src/sharedTest/resources/imports/relationship_web_response_with_errors.json new file mode 100644 index 0000000000..135065d109 --- /dev/null +++ b/core/src/sharedTest/resources/imports/relationship_web_response_with_errors.json @@ -0,0 +1,43 @@ +{ + "httpStatus": "Conflict", + "httpStatusCode": 409, + "status": "ERROR", + "message": "An error occurred, please check import summary.", + "response": { + "responseType": "ImportSummaries", + "status": "ERROR", + "imported": 0, + "updated": 0, + "deleted": 0, + "ignored": 2, + "importSummaries": [ + { + "responseType": "ImportSummary", + "status": "ERROR", + "description": "Relationship wOhCbIpmVCp already exists", + "importCount": { + "imported": 0, + "updated": 0, + "ignored": 1, + "deleted": 0 + }, + "conflicts": [], + "reference": "wOhCbIpmVCp" + }, + { + "responseType": "ImportSummary", + "status": "ERROR", + "description": "Relationship EdG77xZE29R already exists", + "importCount": { + "imported": 0, + "updated": 0, + "ignored": 1, + "deleted": 0 + }, + "conflicts": [], + "reference": "EdG77xZE29R" + } + ], + "total": 2 + } +} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipDeleteWebResponseShould.java b/core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipDeleteWebResponseShould.java new file mode 100644 index 0000000000..46d41db3c4 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipDeleteWebResponseShould.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004-2021, 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.core.imports.internal; + +import static com.google.common.truth.Truth.assertThat; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.hisp.dhis.android.core.Inject; +import org.hisp.dhis.android.core.arch.file.ResourcesFileReader; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class RelationshipDeleteWebResponseShould { + + @Test + public void map_from_json_string() throws Exception { + ObjectMapper objectMapper = Inject.objectMapper(); + + String responseStr = new ResourcesFileReader().getStringFromFile("imports/relationship_delete_web_response.json"); + RelationshipDeleteWebResponse webResponse = objectMapper.readValue(responseStr, + RelationshipDeleteWebResponse.class); + + assertThat(webResponse.message()).isEqualTo("Import was successful."); + assertThat(webResponse.response()).isNotNull(); + } +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponseShould.java b/core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponseShould.java new file mode 100644 index 0000000000..1d65a7b3b2 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/imports/internal/RelationshipWebResponseShould.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2021, 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.core.imports.internal; + +import static com.google.common.truth.Truth.assertThat; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.hisp.dhis.android.core.Inject; +import org.hisp.dhis.android.core.arch.file.ResourcesFileReader; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class RelationshipWebResponseShould { + + @Test + public void map_from_json_string() throws Exception { + ObjectMapper objectMapper = Inject.objectMapper(); + + String responseStr = new ResourcesFileReader().getStringFromFile("imports/relationship_web_response.json"); + RelationshipWebResponse webResponse = objectMapper.readValue(responseStr, RelationshipWebResponse.class); + + assertThat(webResponse.message()).isEqualTo("Import was successful."); + assertThat(webResponse.response()).isNotNull(); + } + + @Test + public void map_from_json_string_with_errors() throws Exception { + ObjectMapper objectMapper = Inject.objectMapper(); + + String webResponseStr = new ResourcesFileReader().getStringFromFile( + "imports/relationship_web_response_with_errors.json"); + objectMapper.readValue(webResponseStr, RelationshipWebResponse.class); + } +} From 0d79736a944b1a5b2513e110eb4533791d0a2468 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 23 Aug 2021 13:38:40 +0200 Subject: [PATCH 269/308] [ANDROSDK-344] Tracker payload integration tests! --- .../BasePayloadGeneratorMockIntegration.kt | 270 +++++++++++++++++ ...erPayloadGeneratorMockIntegrationShould.kt | 205 +++++++++++++ ...PayloadGenerator29MockIntegrationShould.kt | 275 +----------------- .../sms/SmsModuleMockIntegrationShould.java | 8 +- .../core/arch/d2/internal/D2DIComponent.java | 3 + .../internal/RelationshipPostCall.kt | 31 +- .../internal/RelationshipService.kt | 7 +- .../OldTrackerImporterPayloadGenerator.kt | 23 +- .../internal/OldTrackerImporterPostCall.kt | 52 ++-- .../TrackedEntityInstancePostStateManager.kt | 4 +- .../relationship/RelationshipSamples.java | 8 +- 11 files changed, 565 insertions(+), 321 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt new file mode 100644 index 0000000000..3f936afa30 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import org.hisp.dhis.android.core.arch.call.executors.internal.D2CallExecutor +import org.hisp.dhis.android.core.common.ObjectWithUid +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.data.relationship.RelationshipSamples +import org.hisp.dhis.android.core.data.trackedentity.TrackedEntityDataValueSamples +import org.hisp.dhis.android.core.data.trackedentity.TrackedEntityInstanceSamples +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.enrollment.EnrollmentInternalAccessor +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStoreImpl +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.event.internal.EventStoreImpl +import org.hisp.dhis.android.core.maintenance.D2Error +import org.hisp.dhis.android.core.maintenance.internal.ForeignKeyCleanerImpl +import org.hisp.dhis.android.core.organisationunit.internal.OrganisationUnitStore.create +import org.hisp.dhis.android.core.program.internal.ProgramStageStore +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStoreImpl +import org.hisp.dhis.android.core.relationship.internal.RelationshipStoreImpl +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeStore +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestMetadataEnqueable +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.junit.After +import org.junit.BeforeClass +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +open class BasePayloadGeneratorMockIntegration : BaseMockIntegrationTestMetadataEnqueable() { + + protected val teiId = "teiId" + protected val enrollment1Id = "enrollment1Id" + protected val enrollment2Id = "enrollment2Id" + protected val enrollment3Id = "enrollment3Id" + protected val event1Id = "event1Id" + protected val event2Id = "event2Id" + protected val event3Id = "event3Id" + protected val singleEventId = "singleEventId" + + @After + @Throws(D2Error::class) + fun tearDown() { + d2.wipeModule().wipeData() + } + + protected fun storeTrackerData() { + val orgUnit = create(databaseAdapter).selectFirst() + val teiType = TrackedEntityTypeStore.create(databaseAdapter).selectFirst() + val program = d2.programModule().programs().one().blockingGet() + val programStage = ProgramStageStore.create(databaseAdapter).selectFirst() + + val dataValue1 = TrackedEntityDataValueSamples.get().toBuilder().event(event1Id).build() + + val event1 = Event.builder() + .uid(event1Id) + .enrollment(enrollment1Id) + .organisationUnit(orgUnit!!.uid()) + .program(program.uid()) + .programStage(programStage!!.uid()) + .syncState(State.TO_UPDATE) + .aggregatedSyncState(State.TO_UPDATE) + .trackedEntityDataValues(listOf(dataValue1)) + .build() + + val enrollment1 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), listOf(event1)) + .uid(enrollment1Id) + .program(program.uid()) + .organisationUnit(orgUnit.uid()) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) + .trackedEntityInstance(teiId) + .build() + val dataValue2 = TrackedEntityDataValueSamples.get().toBuilder().event(event2Id).build() + + val event2 = Event.builder() + .uid(event2Id) + .enrollment(enrollment2Id) + .organisationUnit(orgUnit.uid()) + .program(program.uid()) + .programStage(programStage.uid()) + .syncState(State.SYNCED_VIA_SMS) + .aggregatedSyncState(State.SYNCED_VIA_SMS) + .trackedEntityDataValues(listOf(dataValue2)) + .build() + + val enrollment2 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), listOf(event2)) + .uid(enrollment2Id) + .program(program.uid()) + .organisationUnit(orgUnit.uid()) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) + .trackedEntityInstance(teiId) + .build() + + val dataValue3 = TrackedEntityDataValueSamples.get().toBuilder().event(event3Id).build() + + val event3 = Event.builder() + .uid(event3Id) + .enrollment(enrollment3Id) + .organisationUnit(orgUnit.uid()) + .program(program.uid()) + .programStage(programStage.uid()) + .syncState(State.ERROR) + .aggregatedSyncState(State.ERROR) + .trackedEntityDataValues(listOf(dataValue3)) + .build() + + val enrollment3 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), listOf(event3)) + .uid(enrollment3Id) + .program(program.uid()) + .organisationUnit(orgUnit.uid()) + .syncState(State.TO_POST) + .aggregatedSyncState(State.SYNCED) + .trackedEntityInstance(teiId) + .build() + + val tei = TrackedEntityInstanceInternalAccessor.insertEnrollments( + TrackedEntityInstance.builder(), listOf(enrollment1, enrollment2, enrollment3) + ) + .uid(teiId) + .trackedEntityType(teiType!!.uid()) + .organisationUnit(orgUnit.uid()) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) + .build() + + val singleEventDataValue = TrackedEntityDataValueSamples.get().toBuilder().event(singleEventId).build() + + val singleEvent = Event.builder() + .uid(singleEventId) + .organisationUnit(orgUnit.uid()) + .program(program.uid()) + .programStage(programStage.uid()) + .syncState(State.TO_POST) + .aggregatedSyncState(State.TO_POST) + .trackedEntityDataValues(listOf(singleEventDataValue)) + .build() + + teiStore.insert(tei) + enrollmentStore.insert(enrollment1) + enrollmentStore.insert(enrollment2) + enrollmentStore.insert(enrollment3) + eventStore.insert(event1) + eventStore.insert(event2) + eventStore.insert(event3) + eventStore.insert(singleEvent) + teiDataValueStore.insert(dataValue1) + teiDataValueStore.insert(dataValue2) + teiDataValueStore.insert(dataValue3) + teiDataValueStore.insert(singleEventDataValue) + } + + protected fun storeSimpleTrackedEntityInstance(teiUid: String, state: State) { + val orgUnit = create(databaseAdapter).selectFirst() + val teiType = TrackedEntityTypeStore.create(databaseAdapter).selectFirst() + TrackedEntityInstanceStoreImpl.create(databaseAdapter).insert( + TrackedEntityInstanceSamples.get().toBuilder() + .uid(teiUid) + .trackedEntityType(teiType!!.uid()) + .organisationUnit(orgUnit!!.uid()) + .syncState(state) + .aggregatedSyncState(state) + .build() + ) + } + + @Throws(D2Error::class) + protected fun storeRelationship( + relationshipUid: String, + from: String, + to: String + ) { + storeRelationship(relationshipUid, RelationshipHelper.teiItem(from), RelationshipHelper.teiItem(to)) + } + + @Throws(D2Error::class) + protected fun storeRelationship( + relationshipUid: String, + from: RelationshipItem, + to: RelationshipItem + ) { + val relationshipType = RelationshipTypeStore.create(databaseAdapter).selectFirst() + val executor = D2CallExecutor.create(databaseAdapter) + executor.executeD2CallTransactionally { + RelationshipStoreImpl.create(databaseAdapter).insert( + RelationshipSamples.get230(relationshipUid, from, to).toBuilder() + .relationshipType(relationshipType!!.uid()) + .syncState(State.TO_POST) + .build() + ) + RelationshipItemStoreImpl.create(databaseAdapter).insert( + from.toBuilder() + .relationship(ObjectWithUid.create(relationshipUid)) + .relationshipItemType(RelationshipConstraintType.FROM) + .build() + ) + RelationshipItemStoreImpl.create(databaseAdapter).insert( + to.toBuilder() + .relationship(ObjectWithUid.create(relationshipUid)) + .relationshipItemType(RelationshipConstraintType.TO) + .build() + ) + ForeignKeyCleanerImpl.create(databaseAdapter).cleanForeignKeyErrors() + null + } + } + + protected fun getEnrollments(trackedEntityInstance: TrackedEntityInstance): List { + return TrackedEntityInstanceInternalAccessor.accessEnrollments(trackedEntityInstance) + } + + protected fun getEvents(enrollment: Enrollment): List { + return EnrollmentInternalAccessor.accessEvents(enrollment) + } + + protected companion object { + internal lateinit var payloadGenerator29: TrackedEntityInstancePostPayloadGenerator29 + internal lateinit var oldTrackerPayloadGenerator: OldTrackerImporterPayloadGenerator + internal lateinit var teiStore: TrackedEntityInstanceStore + internal lateinit var teiDataValueStore: TrackedEntityDataValueStore + internal lateinit var eventStore: EventStore + internal lateinit var enrollmentStore: EnrollmentStore + + @BeforeClass + @JvmStatic + @Throws(Exception::class) + fun setUp() { + setUpClass() + payloadGenerator29 = objects.d2DIComponent.trackedEntityInstancePostPayloadGenerator() + oldTrackerPayloadGenerator = objects.d2DIComponent.oldTrackerImporterPayloadGenerator() + teiStore = TrackedEntityInstanceStoreImpl.create(databaseAdapter) + teiDataValueStore = TrackedEntityDataValueStoreImpl.create(databaseAdapter) + eventStore = EventStoreImpl.create(databaseAdapter) + enrollmentStore = EnrollmentStoreImpl.create(databaseAdapter) + } + } +} diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt new file mode 100644 index 0000000000..d0efc2a507 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import com.google.common.truth.Truth.assertThat +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.relationship.RelationshipHelper +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.junit.Assert.fail +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class OldTrackerImporterPayloadGeneratorMockIntegrationShould : BasePayloadGeneratorMockIntegration() { + + @Test + fun build_tracked_entity_instance_payload_with_nested_elements() { + storeTrackerData() + val trackedEntityInstance = teiStore.selectByUid(teiId)!! + + val payload = oldTrackerPayloadGenerator.getTrackedEntityInstancePayload(listOf(trackedEntityInstance)) + + assertThat(payload.trackedEntityInstances.size).isEqualTo(1) + assertThat(payload.events.size).isEqualTo(0) + assertThat(payload.relationships.size).isEqualTo(0) + + val payloadInstance = payload.trackedEntityInstances.first() + + assertThat(getEnrollments(payloadInstance).size).isEqualTo(2) + for (enrollment in getEnrollments(payloadInstance)) { + assertThat(getEvents(enrollment).size).isEqualTo(1) + for (event in getEvents(enrollment)) { + assertThat(event.trackedEntityDataValues()!!.size).isEqualTo(1) + } + } + } + + @Test + fun build_single_event_with_nested_elements() { + storeTrackerData() + val event = eventStore.selectByUid(singleEventId)!! + + val payload = oldTrackerPayloadGenerator.getEventPayload(listOf(event)) + + assertThat(payload.trackedEntityInstances.size).isEqualTo(0) + assertThat(payload.events.size).isEqualTo(1) + assertThat(payload.relationships.size).isEqualTo(0) + + val payloadEvent = payload.events.first() + + assertThat(payloadEvent.trackedEntityDataValues()!!.size).isEqualTo(1) + } + + @Test + fun build_payload_from_tei_with_related_single_events() { + storeTrackerData() + storeRelationship( + relationshipUid = "relationship1", + from = RelationshipHelper.teiItem(teiId), + to = RelationshipHelper.eventItem(singleEventId) + ) + val instance = teiStore.selectByUid(teiId)!! + + val payload = oldTrackerPayloadGenerator.getTrackedEntityInstancePayload(listOf(instance)) + + assertThat(payload.trackedEntityInstances.size).isEqualTo(1) + assertThat(payload.events.size).isEqualTo(1) + assertThat(payload.relationships.size).isEqualTo(1) + + assertThat(payload.events.first().uid()).isEqualTo(singleEventId) + } + + @Test + fun build_payload_from_tei_with_related_tracker_event() { + val fromTeiUid = "fromTei" + storeTrackerData() + storeSimpleTrackedEntityInstance(fromTeiUid, State.TO_UPDATE) + + storeRelationship( + relationshipUid = "relationship1", + from = RelationshipHelper.teiItem(fromTeiUid), + to = RelationshipHelper.eventItem(event1Id) + ) + val instance = teiStore.selectByUid(fromTeiUid)!! + + val payload = oldTrackerPayloadGenerator.getTrackedEntityInstancePayload(listOf(instance)) + + checkTeisInPayload(payload, fromTeiUid, teiId) + } + + @Test + fun build_payload_from_tei_with_related_enrollments() { + val fromTeiUid = "fromTei" + storeTrackerData() + storeSimpleTrackedEntityInstance(fromTeiUid, State.TO_UPDATE) + + storeRelationship( + relationshipUid = "relationship1", + from = RelationshipHelper.teiItem(fromTeiUid), + to = RelationshipHelper.enrollmentItem(enrollment1Id) + ) + val instance = teiStore.selectByUid(fromTeiUid)!! + + val payload = oldTrackerPayloadGenerator.getTrackedEntityInstancePayload(listOf(instance)) + + checkTeisInPayload(payload, fromTeiUid, teiId) + } + + @Test + fun build_payload_from_tei_with_related_trackedEntityInstances() { + val fromTeiUid = "fromTei" + storeTrackerData() + storeSimpleTrackedEntityInstance(fromTeiUid, State.TO_UPDATE) + + storeRelationship( + relationshipUid = "relationship1", + from = RelationshipHelper.teiItem(fromTeiUid), + to = RelationshipHelper.teiItem(teiId) + ) + val instance = teiStore.selectByUid(fromTeiUid)!! + + val payload = oldTrackerPayloadGenerator.getTrackedEntityInstancePayload(listOf(instance)) + + checkTeisInPayload(payload, fromTeiUid, teiId) + } + + private fun checkTeisInPayload(payload: OldTrackerImporterPayload, fromTei: String, toTei: String) { + assertThat(payload.trackedEntityInstances.size).isEqualTo(2) + assertThat(payload.events.size).isEqualTo(0) + assertThat(payload.relationships.size).isEqualTo(1) + + payload.trackedEntityInstances.forEach { + when(it.uid()) { + fromTei -> assertThat(TrackedEntityInstanceInternalAccessor.accessEnrollments(it)).isEmpty() + toTei -> assertThat(TrackedEntityInstanceInternalAccessor.accessEnrollments(it)).isNotEmpty() + else -> fail("Unexpected trackedEntityInstance uid: " + it.uid()) + } + } + } + + @Test + fun build_payload_from_single_event_with_related_tei() { + storeTrackerData() + + storeRelationship( + relationshipUid = "relationship1", + from = RelationshipHelper.eventItem(singleEventId), + to = RelationshipHelper.teiItem(teiId) + ) + val event = eventStore.selectByUid(singleEventId)!! + + val payload = oldTrackerPayloadGenerator.getEventPayload(listOf(event)) + + assertThat(payload.trackedEntityInstances.size).isEqualTo(1) + assertThat(payload.events.size).isEqualTo(1) + assertThat(payload.relationships.size).isEqualTo(1) + + assertThat(payload.trackedEntityInstances.first().uid()).isEqualTo(teiId) + assertThat(payload.events.first().uid()).isEqualTo(singleEventId) + } + + @Test + fun build_recursive_relationship() { + storeTrackerData() + + storeRelationship( + relationshipUid = "relationship1", + from = RelationshipHelper.enrollmentItem(enrollment1Id), + to = RelationshipHelper.enrollmentItem(enrollment1Id) + ) + val instance = teiStore.selectByUid(teiId)!! + + val payload = oldTrackerPayloadGenerator.getTrackedEntityInstancePayload(listOf(instance)) + + assertThat(payload.trackedEntityInstances.size).isEqualTo(1) + assertThat(payload.events.size).isEqualTo(0) + assertThat(payload.relationships.size).isEqualTo(1) + } +} diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt index 392946ae4c..cb6ac2df94 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt @@ -29,61 +29,22 @@ package org.hisp.dhis.android.core.trackedentity.internal import com.google.common.collect.Lists import com.google.common.truth.Truth.assertThat -import org.hisp.dhis.android.core.arch.call.executors.internal.D2CallExecutor import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidsList -import org.hisp.dhis.android.core.common.ObjectWithUid import org.hisp.dhis.android.core.common.State -import org.hisp.dhis.android.core.data.relationship.RelationshipSamples -import org.hisp.dhis.android.core.data.trackedentity.TrackedEntityDataValueSamples -import org.hisp.dhis.android.core.data.trackedentity.TrackedEntityInstanceSamples -import org.hisp.dhis.android.core.enrollment.Enrollment -import org.hisp.dhis.android.core.enrollment.EnrollmentInternalAccessor -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStoreImpl -import org.hisp.dhis.android.core.event.Event -import org.hisp.dhis.android.core.event.internal.EventStore -import org.hisp.dhis.android.core.event.internal.EventStoreImpl import org.hisp.dhis.android.core.maintenance.D2Error -import org.hisp.dhis.android.core.maintenance.internal.ForeignKeyCleanerImpl import org.hisp.dhis.android.core.note.Note import org.hisp.dhis.android.core.note.NoteCreateProjection -import org.hisp.dhis.android.core.organisationunit.internal.OrganisationUnitStore.create -import org.hisp.dhis.android.core.program.internal.ProgramStageStore -import org.hisp.dhis.android.core.relationship.RelationshipConstraintType -import org.hisp.dhis.android.core.relationship.RelationshipItem -import org.hisp.dhis.android.core.relationship.RelationshipItemTrackedEntityInstance -import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStoreImpl -import org.hisp.dhis.android.core.relationship.internal.RelationshipStoreImpl -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor -import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestMetadataEnqueable import org.hisp.dhis.android.core.utils.runner.D2JunitRunner -import org.junit.After -import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith @RunWith(D2JunitRunner::class) -class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMockIntegrationTestMetadataEnqueable() { - - private val teiId = "teiId" - private val enrollment1Id = "enrollment1Id" - private val enrollment2Id = "enrollment2Id" - private val enrollment3Id = "enrollment3Id" - private val event1Id = "event1Id" - private val event2Id = "event2Id" - private val event3Id = "event3Id" - - @After - @Throws(D2Error::class) - fun tearDown() { - d2.wipeModule().wipeData() - } +class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BasePayloadGeneratorMockIntegration() { @Test fun build_payload_with_different_enrollments() { - storeTrackedEntityInstance() + storeTrackerData() val partitions = partitions @@ -106,33 +67,14 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc teiStore.queryTrackedEntityInstancesToSync() ) - @Test - fun build_payload_with_the_enrollments_events_and_values_set_for_upload() { - storeTrackedEntityInstance() - - val partitions = partitions - - assertThat(partitions.size).isEqualTo(1) - assertThat(partitions.first().size).isEqualTo(1) - - for (instance in partitions.first()) { - assertThat(getEnrollments(instance).size).isEqualTo(2) - for (enrollment in getEnrollments(instance)) { - assertThat(getEvents(enrollment).size).isEqualTo(1) - for (event in getEvents(enrollment)) { - assertThat(event.trackedEntityDataValues()!!.size).isEqualTo(1) - } - } - } - } - @Test fun build_payload_without_events_marked_as_error() { - storeTrackedEntityInstance() + storeTrackerData() enrollmentStore.setAggregatedSyncState(enrollment3Id, State.TO_POST) val partitions = partitions + assertThat(partitions.size).isEqualTo(1) assertThat(partitions.first().size).isEqualTo(1) @@ -150,7 +92,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc @Test fun handle_import_conflicts_correctly() { - storeTrackedEntityInstance() + storeTrackerData() dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_2.json") @@ -161,7 +103,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc @Test fun delete_old_import_conflicts() { - storeTrackedEntityInstance() + storeTrackerData() dhis2MockServer.enqueueMockResponse("imports/web_response_with_import_conflicts_2.json") @@ -184,7 +126,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc @Test @Throws(D2Error::class) fun handle_tei_deletions() { - storeTrackedEntityInstance() + storeTrackerData() d2.trackedEntityModule().trackedEntityInstances().uid("teiId").blockingDelete() @@ -226,38 +168,9 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc assertThat(getUidsList(partitions[0]).containsAll(Lists.newArrayList(tei1, tei2, tei3))).isTrue() } - @Test - fun mark_payload_as_uploading() { - storeTrackedEntityInstance() - - // Ignore result. Just interested in check that target TEIs are marked as UPLOADING - val partitions = partitions - - val instance = teiStore.selectFirst() - assertThat(instance!!.syncState()).isEqualTo(State.UPLOADING) - - val enrollments = enrollmentStore.selectAll() - for (enrollment in enrollments) { - if ("enrollment1Id" == enrollment.uid() || "enrollment2Id" == enrollment.uid()) { - assertThat(enrollment.syncState()).isEqualTo(State.UPLOADING) - } else { - assertThat(enrollment.syncState()).isNotEqualTo(State.UPLOADING) - } - } - - val events = eventStore.selectAll() - for (event in events) { - if (event1Id == event.uid() || event2Id == event.uid()) { - assertThat(event.syncState()).isEqualTo(State.UPLOADING) - } else { - assertThat(event.syncState()).isNotEqualTo(State.UPLOADING) - } - } - } - @Test fun restore_payload_states_when_error_500() { - storeTrackedEntityInstance() + storeTrackerData() dhis2MockServer.enqueueMockResponse(500, "Internal Server Error") d2.trackedEntityModule().trackedEntityInstances().blockingUpload() @@ -286,7 +199,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc @Test @Throws(D2Error::class) fun build_payload_with_enrollment_notes() { - storeTrackedEntityInstance() + storeTrackerData() d2.noteModule().notes().blockingAdd( NoteCreateProjection.builder() .enrollment(enrollment1Id) @@ -311,7 +224,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc @Test @Throws(D2Error::class) fun build_payload_with_event_notes() { - storeTrackedEntityInstance() + storeTrackerData() d2.noteModule().notes().blockingAdd( NoteCreateProjection.builder() @@ -341,7 +254,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc @Test fun do_not_ignore_elements_not_present_in_the_import_summary() { - storeTrackedEntityInstance() + storeTrackerData() // Only enrollment1 and event1 are TO_UPDATE enrollmentStore.setAggregatedSyncState(enrollment2Id, State.SYNCED) @@ -365,170 +278,4 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BaseMoc assertThat(eventStore.selectByUid(event2Id)!!.syncState()).isEqualTo(State.SYNCED) } - private fun storeTrackedEntityInstance() { - val orgUnit = create(databaseAdapter).selectFirst() - val teiType = TrackedEntityTypeStore.create(databaseAdapter).selectFirst() - val program = d2.programModule().programs().one().blockingGet() - val programStage = ProgramStageStore.create(databaseAdapter).selectFirst() - - val dataValue1 = TrackedEntityDataValueSamples.get().toBuilder().event(event1Id).build() - - val event1 = Event.builder() - .uid(event1Id) - .enrollment(enrollment1Id) - .organisationUnit(orgUnit!!.uid()) - .program(program.uid()) - .programStage(programStage!!.uid()) - .syncState(State.TO_UPDATE) - .aggregatedSyncState(State.TO_UPDATE) - .trackedEntityDataValues(listOf(dataValue1)) - .build() - - val enrollment1 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), listOf(event1)) - .uid(enrollment1Id) - .program(program.uid()) - .organisationUnit(orgUnit.uid()) - .syncState(State.TO_POST) - .aggregatedSyncState(State.TO_POST) - .trackedEntityInstance(teiId) - .build() - val dataValue2 = TrackedEntityDataValueSamples.get().toBuilder().event(event2Id).build() - - val event2 = Event.builder() - .uid(event2Id) - .enrollment(enrollment2Id) - .organisationUnit(orgUnit.uid()) - .program(program.uid()) - .programStage(programStage.uid()) - .syncState(State.SYNCED_VIA_SMS) - .aggregatedSyncState(State.SYNCED_VIA_SMS) - .trackedEntityDataValues(listOf(dataValue2)) - .build() - - val enrollment2 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), listOf(event2)) - .uid(enrollment2Id) - .program(program.uid()) - .organisationUnit(orgUnit.uid()) - .syncState(State.TO_POST) - .aggregatedSyncState(State.TO_POST) - .trackedEntityInstance(teiId) - .build() - - val dataValue3 = TrackedEntityDataValueSamples.get().toBuilder().event(event3Id).build() - - val event3 = Event.builder() - .uid(event3Id) - .enrollment(enrollment3Id) - .organisationUnit(orgUnit.uid()) - .program(program.uid()) - .programStage(programStage.uid()) - .syncState(State.ERROR) - .aggregatedSyncState(State.ERROR) - .trackedEntityDataValues(listOf(dataValue3)) - .build() - - val enrollment3 = EnrollmentInternalAccessor.insertEvents(Enrollment.builder(), listOf(event3)) - .uid(enrollment3Id) - .program(program.uid()) - .organisationUnit(orgUnit.uid()) - .syncState(State.TO_POST) - .aggregatedSyncState(State.SYNCED) - .trackedEntityInstance(teiId) - .build() - - val tei = TrackedEntityInstanceInternalAccessor.insertEnrollments( - TrackedEntityInstance.builder(), listOf(enrollment1, enrollment2, enrollment3) - ) - .uid(teiId) - .trackedEntityType(teiType!!.uid()) - .organisationUnit(orgUnit.uid()) - .syncState(State.TO_POST) - .aggregatedSyncState(State.TO_POST) - .build() - - teiStore.insert(tei) - enrollmentStore.insert(enrollment1) - enrollmentStore.insert(enrollment2) - enrollmentStore.insert(enrollment3) - eventStore.insert(event1) - eventStore.insert(event2) - eventStore.insert(event3) - teiDataValueStore.insert(dataValue1) - teiDataValueStore.insert(dataValue2) - teiDataValueStore.insert(dataValue3) - } - - private fun storeSimpleTrackedEntityInstance(teiUid: String, state: State) { - val orgUnit = create(databaseAdapter).selectFirst() - val teiType = TrackedEntityTypeStore.create(databaseAdapter).selectFirst() - TrackedEntityInstanceStoreImpl.create(databaseAdapter).insert( - TrackedEntityInstanceSamples.get().toBuilder() - .uid(teiUid) - .trackedEntityType(teiType!!.uid()) - .organisationUnit(orgUnit!!.uid()) - .syncState(state) - .aggregatedSyncState(state) - .build() - ) - } - - @Throws(D2Error::class) - private fun storeRelationship(relationshipUid: String, fromUid: String, toUid: String) { - val relationshipType = RelationshipTypeStore.create(databaseAdapter).selectFirst() - val executor = D2CallExecutor.create(databaseAdapter) - executor.executeD2CallTransactionally { - RelationshipStoreImpl.create(databaseAdapter).insert( - RelationshipSamples.get230(relationshipUid, fromUid, toUid).toBuilder() - .relationshipType(relationshipType!!.uid()).build() - ) - RelationshipItemStoreImpl.create(databaseAdapter).insert( - RelationshipItem.builder() - .relationship(ObjectWithUid.create(relationshipUid)) - .relationshipItemType(RelationshipConstraintType.FROM) - .trackedEntityInstance( - RelationshipItemTrackedEntityInstance.builder().trackedEntityInstance(fromUid).build() - ) - .build() - ) - RelationshipItemStoreImpl.create(databaseAdapter).insert( - RelationshipItem.builder() - .relationship(ObjectWithUid.create(relationshipUid)) - .relationshipItemType(RelationshipConstraintType.TO) - .trackedEntityInstance( - RelationshipItemTrackedEntityInstance.builder().trackedEntityInstance(toUid).build() - ) - .build() - ) - ForeignKeyCleanerImpl.create(databaseAdapter).cleanForeignKeyErrors() - null - } - } - - private fun getEnrollments(trackedEntityInstance: TrackedEntityInstance): List { - return TrackedEntityInstanceInternalAccessor.accessEnrollments(trackedEntityInstance) - } - - private fun getEvents(enrollment: Enrollment): List { - return EnrollmentInternalAccessor.accessEvents(enrollment) - } - - companion object { - private lateinit var payloadGenerator29: TrackedEntityInstancePostPayloadGenerator29 - private lateinit var teiStore: TrackedEntityInstanceStore - private lateinit var teiDataValueStore: TrackedEntityDataValueStore - private lateinit var eventStore: EventStore - private lateinit var enrollmentStore: EnrollmentStore - - @BeforeClass - @JvmStatic - @Throws(Exception::class) - fun setUp() { - setUpClass() - payloadGenerator29 = objects.d2DIComponent.trackedEntityInstancePostPayloadGenerator() - teiStore = TrackedEntityInstanceStoreImpl.create(databaseAdapter) - teiDataValueStore = TrackedEntityDataValueStoreImpl.create(databaseAdapter) - eventStore = EventStoreImpl.create(databaseAdapter) - enrollmentStore = EnrollmentStoreImpl.create(databaseAdapter) - } - } } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java index e617360931..16f80cc83d 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/sms/SmsModuleMockIntegrationShould.java @@ -28,18 +28,18 @@ package org.hisp.dhis.android.testapp.sms; +import static com.google.common.truth.Truth.assertThat; + import org.hisp.dhis.android.core.sms.domain.interactor.ConfigCase; import org.hisp.dhis.android.core.sms.domain.interactor.QrCodeCase; import org.hisp.dhis.android.core.sms.domain.interactor.SmsSubmitCase; -import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTest; +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestEmptyEnqueable; 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 SmsModuleMockIntegrationShould extends BaseMockIntegrationTest { +public class SmsModuleMockIntegrationShould extends BaseMockIntegrationTestEmptyEnqueable { @Test public void access_submit_case() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java index ff2b4edd88..49bb4df996 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java @@ -89,6 +89,7 @@ import org.hisp.dhis.android.core.systeminfo.internal.SystemInfoPackageDIModule; import org.hisp.dhis.android.core.trackedentity.TrackedEntityPackageDIModule; import org.hisp.dhis.android.core.trackedentity.TrackedEntityType; +import org.hisp.dhis.android.core.trackedentity.internal.OldTrackerImporterPayloadGenerator; import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstancePostPayloadGenerator29; import org.hisp.dhis.android.core.tracker.importer.internal.TrackerImporterPackageDIModule; import org.hisp.dhis.android.core.user.internal.UserPackageDIModule; @@ -183,6 +184,8 @@ public interface D2DIComponent { @VisibleForTesting TrackedEntityInstancePostPayloadGenerator29 trackedEntityInstancePostPayloadGenerator(); @VisibleForTesting + OldTrackerImporterPayloadGenerator oldTrackerImporterPayloadGenerator(); + @VisibleForTesting EventPostPayloadGenerator eventPostPayloadGenerator(); @VisibleForTesting IdentifiableObjectStore categoryOptionStore(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt index 01889e0866..45d7c5020a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt @@ -81,21 +81,26 @@ internal class RelationshipPostCall @Inject internal constructor( } fun postRelationships(relationships: List): Observable { - return Observable.defer { - val progressManager = D2ProgressManager(null) - val payload = RelationshipPayload.builder().relationships(relationships).build() + val progressManager = D2ProgressManager(null) - try { - val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( - relationshipService.postRelationship(payload), - listOf(409), - RelationshipWebResponse::class.java - ) + return if(relationships.isEmpty()) { + Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) + } else { + Observable.defer { + val payload = RelationshipPayload.builder().relationships(relationships).build() - // TODO Implement handler - Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) - } catch (e: Exception) { - Observable.error(e) + try { + val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( + relationshipService.postRelationship(payload), + listOf(409), + RelationshipWebResponse::class.java + ) + + // TODO Implement handler + Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) + } catch (e: Exception) { + Observable.error(e) + } } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt index 567eade4dd..c22a850d9d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt @@ -27,13 +27,12 @@ */ package org.hisp.dhis.android.core.relationship.internal -import retrofit2.http.DELETE -import org.hisp.dhis.android.core.relationship.internal.RelationshipService import org.hisp.dhis.android.core.imports.internal.RelationshipDeleteWebResponse import org.hisp.dhis.android.core.imports.internal.RelationshipWebResponse -import org.hisp.dhis.android.core.relationship.internal.RelationshipPayload import retrofit2.Call import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.POST import retrofit2.http.Path internal interface RelationshipService { @@ -41,7 +40,7 @@ internal interface RelationshipService { @DELETE("$RELATIONSHIPS/{uid}") fun deleteRelationship(@Path("uid") relationship: String): Call - @DELETE(RELATIONSHIPS) + @POST(RELATIONSHIPS) fun postRelationship(@Body payload: RelationshipPayload): Call companion object { diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt index e0a10ba975..812ae43bad 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt @@ -166,14 +166,16 @@ internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( } } - val trackedEntityInstances = trackedEntityInstanceStore.selectByUids(missingTeis.toList()) + val trackedEntityInstances = trackedEntityInstanceStore.selectByUids(missingTeis.toList()).map { + getTrackedEntityInstance(it, extraData) + } val events = eventStore.selectByUids(missingEvents.toList()) return OldTrackerImporterPayload( trackedEntityInstances = trackedEntityInstances, events = events ).run { - copy(relationships = extractRelationships(payload, extraData)) + copy(relationships = extractRelationships(this, extraData)) } } @@ -189,7 +191,7 @@ internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( private fun isMissingEnrollment(uid: String, payload: OldTrackerImporterPayload): Boolean { val enrollments = payload.trackedEntityInstances.flatMap { - TrackedEntityInstanceInternalAccessor.accessEnrollments(it) + TrackedEntityInstanceInternalAccessor.accessEnrollments(it) ?: emptyList() } val isIncludeInPayload = enrollments.map { it.uid() }.contains(uid) val isPendingToSync: Boolean by lazy { @@ -202,10 +204,11 @@ internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( private fun isMissingEvent(uid: String, payload: OldTrackerImporterPayload): Boolean { val events = payload.trackedEntityInstances.flatMap { - TrackedEntityInstanceInternalAccessor.accessEnrollments(it) + TrackedEntityInstanceInternalAccessor.accessEnrollments(it) ?: emptyList() }.flatMap { - EnrollmentInternalAccessor.accessEvents(it) - } + EnrollmentInternalAccessor.accessEvents(it) ?: emptyList() + } + payload.events + val isIncludedInPayload = events.map { it.uid() }.contains(uid) val isPendingToSync: Boolean by lazy { val event = eventStore.selectByUid(uid) @@ -242,13 +245,17 @@ internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( } val enrollments = payload.trackedEntityInstances.flatMap { - TrackedEntityInstanceInternalAccessor.accessEnrollments(it) + TrackedEntityInstanceInternalAccessor.accessEnrollments(it) ?: emptyList() } + val enrollmentItems = enrollments.map { RelationshipHelper.enrollmentItem(it.uid()) } - val events = enrollments.flatMap { EnrollmentInternalAccessor.accessEvents(it) } + payload.events + val events = enrollments.flatMap { + EnrollmentInternalAccessor.accessEvents(it) ?: emptyList() + } + payload.events + val eventItems = events.map { RelationshipHelper.eventItem(it.uid()) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt index aebfa8c86a..8f7a6f8555 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt @@ -132,32 +132,36 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( private fun postEvents( events: List ): Observable { - return Observable.defer { - val eventPayload = EventPayload() - eventPostStateManager.markObjectsAs(events, State.UPLOADING) + val progressManager = D2ProgressManager(null) - val progressManager = D2ProgressManager(null) + return if (events.isEmpty()) { + Observable.just(progressManager.increaseProgress(Event::class.java, true)) + } else { + Observable.defer { + val eventPayload = EventPayload() + eventPostStateManager.markObjectsAs(events, State.UPLOADING) - eventPayload.events = events - val strategy = "SYNC" - try { - val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( - eventService.postEvents(eventPayload, strategy), - @Suppress("MagicNumber") - listOf(409), - EventWebResponse::class.java - ) - eventImportHandler.handleEventImportSummaries( - eventImportSummaries = webResponse?.response()?.importSummaries(), - events = events, - // TODO Manage tracker events - enrollmentUid = null, - teiUid = null - ) - Observable.just(progressManager.increaseProgress(Event::class.java, true)) - } catch (e: Exception) { - eventPostStateManager.markObjectsAs(events, State.TO_UPDATE) - Observable.error(e) + eventPayload.events = events + val strategy = "SYNC" + try { + val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( + eventService.postEvents(eventPayload, strategy), + @Suppress("MagicNumber") + listOf(409), + EventWebResponse::class.java + ) + eventImportHandler.handleEventImportSummaries( + eventImportSummaries = webResponse?.response()?.importSummaries(), + events = events, + // TODO Manage tracker events + enrollmentUid = null, + teiUid = null + ) + Observable.just(progressManager.increaseProgress(Event::class.java, true)) + } catch (e: Exception) { + eventPostStateManager.markObjectsAs(events, State.TO_UPDATE) + Observable.error(e) + } } } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt index 7ba78c7841..0afcc07183 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt @@ -63,13 +63,13 @@ internal class TrackedEntityInstancePostStateManager @Inject internal constructo for (instance in partition) { h.addState(teiMap, instance, forcedState) - for (enrollment in TrackedEntityInstanceInternalAccessor.accessEnrollments(instance)) { + TrackedEntityInstanceInternalAccessor.accessEnrollments(instance)?.forEach { enrollment -> h.addState(enrollmentMap, enrollment, forcedState) for (event in EnrollmentInternalAccessor.accessEvents(enrollment)) { h.addState(eventMap, event, forcedState) } } - for (r in TrackedEntityInstanceInternalAccessor.accessRelationships(instance)) { + TrackedEntityInstanceInternalAccessor.accessRelationships(instance)?.forEach { r -> if (versionManager.is2_29) { val whereClause = WhereClauseBuilder().appendKeyStringValue(CoreColumns.ID, r.id()).build() val dbRelationship = relationshipStore.selectOneWhere(whereClause) diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java index 433b4b909b..ef20c5368a 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/relationship/RelationshipSamples.java @@ -102,11 +102,15 @@ protected Relationship get230() { } public static Relationship get230(String uid, String fromUid, String toUid) { + return get230(uid, RelationshipHelper.teiItem(fromUid), RelationshipHelper.teiItem(toUid)); + } + + public static Relationship get230(String uid, RelationshipItem from, RelationshipItem to) { return commonBuilder .uid(uid) .relationshipType(TYPE) - .from(RelationshipHelper.teiItem(fromUid)) - .to(RelationshipHelper.teiItem(toUid)) + .from(from) + .to(to) .build(); } From db868e525d75900039b2c9cb344dc042c9481416 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 23 Aug 2021 14:09:39 +0200 Subject: [PATCH 270/308] [androsdk-1378] Rename LocalDataStoreModule to DataStoreModule --- ...ataStoreCollectionRepositoryMockIntegrationShould.java | 8 ++++---- ...calDataStoreObjectRepositoryMockIntegrationShould.java | 6 +++--- core/src/main/java/org/hisp/dhis/android/core/D2.java | 6 +++--- .../dhis/android/core/arch/d2/internal/D2DIComponent.java | 6 +++--- .../dhis/android/core/arch/d2/internal/D2Modules.java | 8 ++++---- .../{LocalDataStoreModule.kt => DataStoreModule.kt} | 2 +- ...LocalDataStoreModuleImpl.kt => DataStoreModuleImpl.kt} | 6 +++--- ...torePackageDIModule.kt => DataStorePackageDIModule.kt} | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/datastore/{LocalDataStoreModule.kt => DataStoreModule.kt} (98%) rename core/src/main/java/org/hisp/dhis/android/core/datastore/internal/{LocalDataStoreModuleImpl.kt => DataStoreModuleImpl.kt} (92%) rename core/src/main/java/org/hisp/dhis/android/core/datastore/internal/{LocalDataStorePackageDIModule.kt => DataStorePackageDIModule.kt} (91%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java index 1e8ec33435..7b7f4d06e0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreCollectionRepositoryMockIntegrationShould.java @@ -42,12 +42,12 @@ public class LocalDataStoreCollectionRepositoryMockIntegrationShould extends Bas @Test public void find_all() { - assertThat(d2.localDataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); + assertThat(d2.dataStoreModule().localDataStore().blockingGet().size()).isEqualTo(2); } @Test public void filter_by_key() { - KeyValuePair pair = d2.localDataStoreModule().localDataStore() + KeyValuePair pair = d2.dataStoreModule().localDataStore() .byKey().eq("key1") .one() .blockingGet(); @@ -58,7 +58,7 @@ public void filter_by_key() { @Test public void filter_by_value() { - KeyValuePair pair = d2.localDataStoreModule().localDataStore() + KeyValuePair pair = d2.dataStoreModule().localDataStore() .byValue().eq("value2") .one() .blockingGet(); @@ -69,7 +69,7 @@ public void filter_by_value() { @Test public void return_object_repository() { - LocalDataStoreObjectRepository objectRepository = d2.localDataStoreModule().localDataStore() + LocalDataStoreObjectRepository objectRepository = d2.dataStoreModule().localDataStore() .value("key1"); assertThat(objectRepository.blockingExists()).isEqualTo(Boolean.TRUE); assertThat(objectRepository.blockingGet().value()).isEqualTo("value1"); diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java index 789f02bde9..07594ea5cd 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/datastore/LocalDataStoreObjectRepositoryMockIntegrationShould.java @@ -65,13 +65,13 @@ public void delete_value() throws D2Error { @Test public void return_that_a_value_exists_only_if_it_has_been_created() { - assertThat(d2.localDataStoreModule().localDataStore() + assertThat(d2.dataStoreModule().localDataStore() .value("no_key").blockingExists()).isEqualTo(Boolean.FALSE); - assertThat(d2.localDataStoreModule().localDataStore() + assertThat(d2.dataStoreModule().localDataStore() .value("key1").blockingExists()).isEqualTo(Boolean.TRUE); } private LocalDataStoreObjectRepository objectRepository() { - return d2.localDataStoreModule().localDataStore().value("new_key"); + return d2.dataStoreModule().localDataStore().value("new_key"); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/D2.java b/core/src/main/java/org/hisp/dhis/android/core/D2.java index 4ff65be5e6..b098f952d2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/D2.java +++ b/core/src/main/java/org/hisp/dhis/android/core/D2.java @@ -40,7 +40,7 @@ import org.hisp.dhis.android.core.constant.ConstantModule; import org.hisp.dhis.android.core.dataelement.DataElementModule; import org.hisp.dhis.android.core.dataset.DataSetModule; -import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; +import org.hisp.dhis.android.core.datastore.DataStoreModule; import org.hisp.dhis.android.core.datavalue.DataValueModule; import org.hisp.dhis.android.core.domain.aggregated.AggregatedModule; import org.hisp.dhis.android.core.enrollment.EnrollmentModule; @@ -173,8 +173,8 @@ public LegendSetModule legendSetModule() { return this.modules.legendSet; } - public LocalDataStoreModule localDataStoreModule() { - return this.modules.localDataStore; + public DataStoreModule dataStoreModule() { + return this.modules.dataStore; } public MaintenanceModule maintenanceModule() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java index d3f2559774..a9e6aa7ee4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2DIComponent.java @@ -59,7 +59,7 @@ import org.hisp.dhis.android.core.dataelement.internal.DataElementPackageDIModule; import org.hisp.dhis.android.core.dataset.DataSet; import org.hisp.dhis.android.core.dataset.internal.DataSetPackageDIModule; -import org.hisp.dhis.android.core.datastore.internal.LocalDataStorePackageDIModule; +import org.hisp.dhis.android.core.datastore.internal.DataStorePackageDIModule; import org.hisp.dhis.android.core.datavalue.internal.DataValueConflictDIModule; import org.hisp.dhis.android.core.datavalue.internal.DataValuePackageDIModule; import org.hisp.dhis.android.core.domain.aggregated.data.internal.AggregatedDataPackageDIModule; @@ -131,7 +131,7 @@ ImportPackageDIModule.class, IndicatorPackageDIModule.class, LegendPackageDIModule.class, - LocalDataStorePackageDIModule.class, + DataStorePackageDIModule.class, MaintenancePackageDIModule.class, MaintenancePackageDIModule.class, NotePackageDIModule.class, @@ -213,7 +213,7 @@ interface Builder { Builder importPackageDIModule(ImportPackageDIModule importPackageDIModule); Builder indicatorPackageDIModule(IndicatorPackageDIModule indicatorPackageDIModule); Builder legendPackageDIModule(LegendPackageDIModule legendPackageDIModule); - Builder localDataStorePackageDIModule(LocalDataStorePackageDIModule localDataStorePackageDIModule); + Builder dataStorePackageDIModule(DataStorePackageDIModule dataStorePackageDIModule); Builder maintenancePackageDIModule(MaintenancePackageDIModule maintenancePackageDIModule); Builder optionPackageDIModule(OptionPackageDIModule optionPackageDIModule); Builder organisationUnitPackageDIModule(OrganisationUnitPackageDIModule organisationUnitPackageDIModule); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java index 7b2c7b12ed..f8def3b1b6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/d2/internal/D2Modules.java @@ -33,7 +33,7 @@ import org.hisp.dhis.android.core.constant.ConstantModule; import org.hisp.dhis.android.core.dataelement.DataElementModule; import org.hisp.dhis.android.core.dataset.DataSetModule; -import org.hisp.dhis.android.core.datastore.LocalDataStoreModule; +import org.hisp.dhis.android.core.datastore.DataStoreModule; import org.hisp.dhis.android.core.datavalue.DataValueModule; import org.hisp.dhis.android.core.enrollment.EnrollmentModule; import org.hisp.dhis.android.core.event.EventModule; @@ -77,7 +77,7 @@ public final class D2Modules { public final ImportModule importModule; public final IndicatorModule indicator; public final LegendSetModule legendSet; - public final LocalDataStoreModule localDataStore; + public final DataStoreModule dataStore; public final MaintenanceModule maintenance; public final NoteModule note; public final ProgramModule program; @@ -106,7 +106,7 @@ public D2Modules(AnalyticsModule analytics, ImportModule importModule, IndicatorModule indicator, LegendSetModule legendSet, - LocalDataStoreModule localDataStore, + DataStoreModule dataStore, MaintenanceModule maintenance, NoteModule note, ProgramModule program, @@ -133,7 +133,7 @@ public D2Modules(AnalyticsModule analytics, this.importModule = importModule; this.indicator = indicator; this.legendSet = legendSet; - this.localDataStore = localDataStore; + this.dataStore = dataStore; this.maintenance = maintenance; this.note = note; this.program = program; diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/DataStoreModule.kt similarity index 98% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt rename to core/src/main/java/org/hisp/dhis/android/core/datastore/DataStoreModule.kt index cc0d77b431..fbab9349f7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/DataStoreModule.kt @@ -27,6 +27,6 @@ */ package org.hisp.dhis.android.core.datastore -interface LocalDataStoreModule { +interface DataStoreModule { fun localDataStore(): LocalDataStoreCollectionRepository } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt similarity index 92% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt rename to core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt index 6d22371412..0e1b366da3 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStoreModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt @@ -30,13 +30,13 @@ package org.hisp.dhis.android.core.datastore.internal import dagger.Reusable import javax.inject.Inject import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository -import org.hisp.dhis.android.core.datastore.LocalDataStoreModule +import org.hisp.dhis.android.core.datastore.DataStoreModule @Reusable -class LocalDataStoreModuleImpl @Inject internal constructor( +class DataStoreModuleImpl @Inject internal constructor( private val localDataStore: LocalDataStoreCollectionRepository ) : - LocalDataStoreModule { + DataStoreModule { override fun localDataStore(): LocalDataStoreCollectionRepository { return localDataStore } diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStorePackageDIModule.kt similarity index 91% rename from core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt rename to core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStorePackageDIModule.kt index 41a328a51c..230924bf12 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/LocalDataStorePackageDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStorePackageDIModule.kt @@ -30,13 +30,13 @@ package org.hisp.dhis.android.core.datastore.internal import dagger.Module import dagger.Provides import dagger.Reusable -import org.hisp.dhis.android.core.datastore.LocalDataStoreModule +import org.hisp.dhis.android.core.datastore.DataStoreModule @Module(includes = [LocalDataStoreEntityDIModule::class]) -class LocalDataStorePackageDIModule { +class DataStorePackageDIModule { @Provides @Reusable - fun module(impl: LocalDataStoreModuleImpl): LocalDataStoreModule { + fun module(impl: DataStoreModuleImpl): DataStoreModule { return impl } } From d8c96e7173e9d0a2fe98a329a314e4f8e6272321 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 23 Aug 2021 14:13:19 +0200 Subject: [PATCH 271/308] [androsdk-1378] Remove add method from LocalDataStoreCollectionRepository --- .../core/datastore/LocalDataStoreCollectionRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java index 2513d62169..29a1f03085 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/LocalDataStoreCollectionRepository.java @@ -30,7 +30,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; -import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadWriteWithoutUidCollectionRepositoryImpl; +import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnlyCollectionRepositoryImpl; import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; import org.hisp.dhis.android.core.arch.repositories.filters.internal.StringFilterConnector; import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; @@ -43,7 +43,7 @@ @Reusable public final class LocalDataStoreCollectionRepository - extends ReadWriteWithoutUidCollectionRepositoryImpl { + extends ReadOnlyCollectionRepositoryImpl { private final ObjectWithoutUidStore store; From 36c01a54b76a772c7b3fa22b47b7a5536f978045 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Mon, 23 Aug 2021 14:48:01 +0200 Subject: [PATCH 272/308] [androsdk-1378] KtlintFormat --- .../dhis/android/core/datastore/internal/DataStoreModuleImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt index 0e1b366da3..27c5f38e27 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/datastore/internal/DataStoreModuleImpl.kt @@ -29,8 +29,8 @@ package org.hisp.dhis.android.core.datastore.internal import dagger.Reusable import javax.inject.Inject -import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository import org.hisp.dhis.android.core.datastore.DataStoreModule +import org.hisp.dhis.android.core.datastore.LocalDataStoreCollectionRepository @Reusable class DataStoreModuleImpl @Inject internal constructor( From 3df7a154375de69305df297ee19831ff11e30d1e Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 23 Aug 2021 15:40:38 +0200 Subject: [PATCH 273/308] [ANDROSDK-344] Relationship import handler --- .../internal/RelationshipImportHandler.kt | 76 ++++++++ .../internal/RelationshipPostCall.kt | 8 +- .../RelationshipImportHandlerShould.kt | 126 ++++++++++++ ...ckedEntityInstanceImportHandlerShould.java | 183 ------------------ ...rackedEntityInstanceImportHandlerShould.kt | 162 ++++++++++++++++ 5 files changed, 370 insertions(+), 185 deletions(-) create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt create mode 100644 core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt delete mode 100644 core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java create mode 100644 core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt new file mode 100644 index 0000000000..dc801acf25 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.imports.internal.BaseImportSummaryHelper.getReferences +import org.hisp.dhis.android.core.imports.internal.RelationshipImportSummary +import org.hisp.dhis.android.core.relationship.Relationship +import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository +import javax.inject.Inject + +@Reusable class RelationshipImportHandler @Inject internal constructor( + private val relationshipStore: RelationshipStore, + private val dataStatePropagator: DataStatePropagator, + private val relationshipRepository: RelationshipCollectionRepository +) { + + fun handleRelationshipImportSummaries( + importSummaries: List?, + relationships: List + ) { + + importSummaries?.filterNotNull()?.forEach { importSummary -> + importSummary.reference()?.let { relationshipUid -> + val relationship = relationshipRepository.withItems().uid(relationshipUid).blockingGet() + + val state = getSyncState(importSummary.status()) + + relationshipStore.setSyncStateOrDelete(relationshipUid, state) + dataStatePropagator.propagateRelationshipUpdate(relationship?.from()) + } + } + + processIgnoredRelationships(importSummaries, relationships) + } + + private fun processIgnoredRelationships( + importSummaries: List?, + relationships: List + ) { + val processedRelationships = getReferences(importSummaries) + + relationships.filterNot { processedRelationships.contains(it.uid()) }.forEach { relationship -> + relationshipStore.setSyncStateOrDelete(relationship.uid()!!, State.TO_UPDATE) + dataStatePropagator.propagateRelationshipUpdate(relationship.from()) + } + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt index 45d7c5020a..3a89a2da7d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt @@ -52,6 +52,7 @@ import javax.inject.Inject internal class RelationshipPostCall @Inject internal constructor( private val relationshipService: RelationshipService, private val relationshipStore: RelationshipStore, + private val relationshipImportHandler: RelationshipImportHandler, private val dataStatePropagator: DataStatePropagator, private val apiCallExecutor: APICallExecutor ) { @@ -83,7 +84,7 @@ internal class RelationshipPostCall @Inject internal constructor( fun postRelationships(relationships: List): Observable { val progressManager = D2ProgressManager(null) - return if(relationships.isEmpty()) { + return if (relationships.isEmpty()) { Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) } else { Observable.defer { @@ -96,7 +97,10 @@ internal class RelationshipPostCall @Inject internal constructor( RelationshipWebResponse::class.java ) - // TODO Implement handler + relationshipImportHandler.handleRelationshipImportSummaries( + importSummaries = httpResponse.response()?.importSummaries(), + relationships = relationships + ) Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) } catch (e: Exception) { Observable.error(e) diff --git a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt new file mode 100644 index 0000000000..c785b2bfc2 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import com.nhaarman.mockitokotlin2.* +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.internal.RelationshipImportSummary +import org.hisp.dhis.android.core.relationship.Relationship +import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository +import org.hisp.dhis.android.core.relationship.RelationshipItem +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.ArgumentMatchers.anyString +import org.mockito.Mockito + +@RunWith(JUnit4::class) +class RelationshipImportHandlerShould { + + private val relationshipStore: RelationshipStore = mock() + + private val dataStatePropagator: DataStatePropagator = mock() + + private val relationshipCollectionRepository: RelationshipCollectionRepository = + mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) + + private val importSummary: RelationshipImportSummary = mock() + + private val relationship: Relationship = mock() + private val relationshipItem: RelationshipItem = mock() + + private val relationships: List = emptyList() + + // object to test + private lateinit var relationshipImportHandler: RelationshipImportHandler + + @Before + @Throws(Exception::class) + fun setUp() { + relationshipImportHandler = + RelationshipImportHandler(relationshipStore, dataStatePropagator, relationshipCollectionRepository) + + whenever(relationshipCollectionRepository.withItems().uid(any()).blockingGet()).doReturn(relationship) + whenever(relationship.from()).doReturn(relationshipItem) + } + + @Test + fun do_nothing_when_passing_null_argument() { + relationshipImportHandler.handleRelationshipImportSummaries(null, relationships) + + verify(relationshipStore, never()).setSyncStateOrDelete(anyString(), any()) + verify(dataStatePropagator, never()).propagateRelationshipUpdate(any()) + } + + @Test + fun setStatus_shouldUpdateRelationshipStatusSuccess() { + whenever(importSummary.status()).doReturn(ImportStatus.SUCCESS) + whenever(importSummary.reference()).doReturn("test_uid") + + relationshipImportHandler.handleRelationshipImportSummaries( + listOf(importSummary), relationships + ) + + verify(relationshipStore, times(1)).setSyncStateOrDelete("test_uid", State.SYNCED) + verify(dataStatePropagator, times(1)).propagateRelationshipUpdate(any()) + } + + @Test + fun setStatus_shouldUpdateRelationshipStatusError() { + whenever(importSummary.status()).doReturn(ImportStatus.ERROR) + whenever(importSummary.reference()).doReturn("test_uid") + + relationshipImportHandler.handleRelationshipImportSummaries( + listOf(importSummary), relationships + ) + + verify(relationshipStore, times(1)).setSyncStateOrDelete("test_uid", State.ERROR) + verify(dataStatePropagator, times(1)).propagateRelationshipUpdate(any()) + } + + @Test + fun mark_as_to_update_relationships_not_present_in_the_response() { + whenever(importSummary.status()).doReturn(ImportStatus.SUCCESS) + whenever(importSummary.reference()).doReturn("test_uid") + + val relationships = listOf(relationship) + whenever(relationship.uid()).doReturn("missing_uid") + + relationshipImportHandler.handleRelationshipImportSummaries( + listOf(importSummary), relationships + ) + + verify(relationshipStore, times(1)).setSyncStateOrDelete("test_uid", State.SYNCED) + verify(relationshipStore, times(1)).setSyncStateOrDelete("missing_uid", State.TO_UPDATE) + + verify(dataStatePropagator, times(2)).propagateRelationshipUpdate(any()) + } +} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java deleted file mode 100644 index f00a5ab092..0000000000 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.trackedentity.internal; - -import org.hisp.dhis.android.core.common.State; -import org.hisp.dhis.android.core.common.internal.DataStatePropagator; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler; -import org.hisp.dhis.android.core.imports.ImportStatus; -import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummaries; -import org.hisp.dhis.android.core.imports.internal.EnrollmentImportSummary; -import org.hisp.dhis.android.core.imports.internal.TEIImportSummary; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictParser; -import org.hisp.dhis.android.core.imports.internal.TrackerImportConflictStore; -import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository; -import org.hisp.dhis.android.core.relationship.internal.RelationshipDHISVersionManager; -import org.hisp.dhis.android.core.relationship.internal.RelationshipStore; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(JUnit4.class) -public class TrackedEntityInstanceImportHandlerShould { - - @Mock - private TrackedEntityInstanceStore trackedEntityInstanceStore; - - @Mock - private EnrollmentImportHandler enrollmentImportHandler; - - @Mock - private TEIImportSummary importSummary; - - @Mock - private EnrollmentImportSummary enrollmentSummary; - - @Mock - private EnrollmentImportSummaries importEnrollment; - - @Mock - private TrackerImportConflictStore trackerImportConflictStore; - - @Mock - private TrackerImportConflictParser trackerImportConflictParser; - - @Mock - private RelationshipStore relationshipStore; - - @Mock - private DataStatePropagator dataStatePropagator; - - @Mock - private RelationshipDHISVersionManager relationshipDHISVersionManager; - - @Mock - private RelationshipCollectionRepository relationshipCollectionRepository; - - @Mock - private TrackedEntityInstance trackedEntityInstance; - - private final List instances = new ArrayList<>(); - - // object to test - private TrackedEntityInstanceImportHandler trackedEntityInstanceImportHandler; - - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - trackedEntityInstanceImportHandler = - new TrackedEntityInstanceImportHandler(trackedEntityInstanceStore, enrollmentImportHandler, - trackerImportConflictStore, trackerImportConflictParser, relationshipStore, dataStatePropagator, - relationshipDHISVersionManager, relationshipCollectionRepository); - } - - @Test - public void do_nothing_when_passing_null_argument() { - trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries(null, instances); - - verify(trackedEntityInstanceStore, never()).setSyncStateOrDelete(anyString(), any(State.class)); - } - - @Test - public void setStatus_shouldUpdateTrackedEntityInstanceStatusSuccess() throws Exception { - when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); - when(importSummary.reference()).thenReturn("test_tei_uid"); - - trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( - Collections.singletonList(importSummary), instances - ); - - verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.SYNCED); - } - - @Test - public void setStatus_shouldUpdateTrackedEntityInstanceStatusError() throws Exception { - when(importSummary.status()).thenReturn(ImportStatus.ERROR); - when(importSummary.reference()).thenReturn("test_tei_uid"); - - trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( - Collections.singletonList(importSummary), instances - ); - - verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.ERROR); - } - - @Test - public void update_tracker_entity_instance_status_success_status_and_handle_import_enrollment_on_import_success() throws Exception { - when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); - when(importSummary.reference()).thenReturn("test_tei_uid"); - when(importSummary.enrollments()).thenReturn(importEnrollment); - List enrollmentSummaries = Collections.singletonList(enrollmentSummary); - when(importEnrollment.importSummaries()).thenReturn(enrollmentSummaries); - - trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( - Collections.singletonList(importSummary), instances - ); - - verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.SYNCED); - verify(enrollmentImportHandler, times(1)).handleEnrollmentImportSummary( - eq(enrollmentSummaries), anyList(), anyString()); - } - - @Test - public void mark_as_to_update_tracked_entity_instances_not_present_in_the_response() throws Exception { - when(importSummary.status()).thenReturn(ImportStatus.SUCCESS); - when(importSummary.reference()).thenReturn("test_tei_uid"); - - List instances = new ArrayList<>(); - instances.add(trackedEntityInstance); - when(trackedEntityInstance.uid()).thenReturn("missing_tei_uid"); - - trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( - Collections.singletonList(importSummary), instances - ); - - verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("test_tei_uid", State.SYNCED); - verify(trackedEntityInstanceStore, times(1)).setSyncStateOrDelete("missing_tei_uid", State.TO_UPDATE); - } -} \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt new file mode 100644 index 0000000000..f1dec8021e --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2004-2021, 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.core.trackedentity.internal + +import com.nhaarman.mockitokotlin2.* +import org.hisp.dhis.android.core.common.State +import org.hisp.dhis.android.core.common.internal.DataStatePropagator +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler +import org.hisp.dhis.android.core.imports.ImportStatus +import org.hisp.dhis.android.core.imports.internal.* +import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository +import org.hisp.dhis.android.core.relationship.internal.RelationshipDHISVersionManager +import org.hisp.dhis.android.core.relationship.internal.RelationshipStore +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.ArgumentMatchers.anyList +import org.mockito.ArgumentMatchers.anyString +import java.util.* + +@RunWith(JUnit4::class) +class TrackedEntityInstanceImportHandlerShould { + private val trackedEntityInstanceStore: TrackedEntityInstanceStore = mock() + + private val enrollmentImportHandler: EnrollmentImportHandler = mock() + + private val importSummary: TEIImportSummary = mock() + + private val enrollmentSummary: EnrollmentImportSummary = mock() + + private val importEnrollment: EnrollmentImportSummaries = mock() + + private val trackerImportConflictStore: TrackerImportConflictStore = mock() + + private val trackerImportConflictParser: TrackerImportConflictParser = mock() + + private val relationshipStore: RelationshipStore = mock() + + private val dataStatePropagator: DataStatePropagator = mock() + + private val relationshipDHISVersionManager: RelationshipDHISVersionManager = mock() + + private val relationshipCollectionRepository: RelationshipCollectionRepository = mock() + + private val trackedEntityInstance: TrackedEntityInstance = mock() + + private val instances: List = ArrayList() + + // object to test + private lateinit var trackedEntityInstanceImportHandler: TrackedEntityInstanceImportHandler + + @Before + @Throws(Exception::class) + fun setUp() { + trackedEntityInstanceImportHandler = TrackedEntityInstanceImportHandler( + trackedEntityInstanceStore, enrollmentImportHandler, + trackerImportConflictStore, trackerImportConflictParser, relationshipStore, dataStatePropagator, + relationshipDHISVersionManager, relationshipCollectionRepository + ) + } + + @Test + fun do_nothing_when_passing_null_argument() { + trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries(null, instances) + verify(trackedEntityInstanceStore, never()).setSyncStateOrDelete(anyString(), any()) + } + + @Test + @Throws(Exception::class) + fun setStatus_shouldUpdateTrackedEntityInstanceStatusSuccess() { + whenever(importSummary.status()).doReturn(ImportStatus.SUCCESS) + whenever(importSummary.reference()).doReturn("test_tei_uid") + + trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( + listOf(importSummary), instances + ) + + verify(trackedEntityInstanceStore, times(1)) + .setSyncStateOrDelete("test_tei_uid", State.SYNCED) + } + + @Test + @Throws(Exception::class) + fun setStatus_shouldUpdateTrackedEntityInstanceStatusError() { + whenever(importSummary.status()).doReturn(ImportStatus.ERROR) + whenever(importSummary.reference()).doReturn("test_tei_uid") + + trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( + listOf(importSummary), instances + ) + + verify(trackedEntityInstanceStore, times(1)) + .setSyncStateOrDelete("test_tei_uid", State.ERROR) + } + + @Test + @Throws(Exception::class) + fun update_tracker_entity_instance_status_success_status_and_handle_import_enrollment_on_import_success() { + whenever(importSummary.status()).doReturn(ImportStatus.SUCCESS) + whenever(importSummary.reference()).doReturn("test_tei_uid") + whenever(importSummary.enrollments()).thenReturn(importEnrollment) + + val enrollmentSummaries = listOf(enrollmentSummary) + whenever(importEnrollment.importSummaries()).doReturn(enrollmentSummaries) + + trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( + listOf(importSummary), instances + ) + + verify(trackedEntityInstanceStore, times(1)) + .setSyncStateOrDelete("test_tei_uid", State.SYNCED) + verify(enrollmentImportHandler, times(1)).handleEnrollmentImportSummary( + eq(enrollmentSummaries), anyList(), anyString() + ) + } + + @Test + @Throws(Exception::class) + fun mark_as_to_update_tracked_entity_instances_not_present_in_the_response() { + whenever(importSummary.status()).doReturn(ImportStatus.SUCCESS) + whenever(importSummary.reference()).doReturn("test_tei_uid") + + val instances = listOf(trackedEntityInstance) + whenever(trackedEntityInstance.uid()).thenReturn("missing_tei_uid") + + trackedEntityInstanceImportHandler.handleTrackedEntityInstanceImportSummaries( + listOf(importSummary), instances + ) + + verify(trackedEntityInstanceStore, times(1)) + .setSyncStateOrDelete("test_tei_uid", State.SYNCED) + verify(trackedEntityInstanceStore, times(1)) + .setSyncStateOrDelete("missing_tei_uid", State.TO_UPDATE) + } +} \ No newline at end of file From c7fa54e968ab0d25b4ee6acb39a3999012612b1d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 23 Aug 2021 17:09:45 +0200 Subject: [PATCH 274/308] [ANDROSDK-344] Set UPLOADING state in relationships --- .../core/event/internal/OldEventPostCall.kt | 12 ++++++--- .../internal/RelationshipPostCall.kt | 11 ++++++-- .../OldTrackedEntityInstancePostCall.kt | 9 ++++--- .../internal/OldTrackerImporterPostCall.kt | 16 ++++++++---- ...eManager.kt => TrackerPostStateManager.kt} | 25 +++++++++++++++---- 5 files changed, 54 insertions(+), 19 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/{TrackedEntityInstancePostStateManager.kt => TrackerPostStateManager.kt} (82%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt index 085d0dfc56..9e0e215d48 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt @@ -29,7 +29,6 @@ package org.hisp.dhis.android.core.event.internal import dagger.Reusable import io.reactivex.Observable -import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager @@ -38,6 +37,8 @@ import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.imports.internal.EventWebResponse import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.internal.OldTrackerImporterPostCall +import org.hisp.dhis.android.core.trackedentity.internal.TrackerPostStateManager +import javax.inject.Inject @Reusable internal class OldEventPostCall @Inject internal constructor( @@ -46,7 +47,7 @@ internal class OldEventPostCall @Inject internal constructor( private val eventService: EventService, private val apiCallExecutor: APICallExecutor, private val eventImportHandler: EventImportHandler, - private val stateManager: EventPostStateManager, + private val trackerPostStateManager: TrackerPostStateManager, private val oldTrackerImporterPostCall: OldTrackerImporterPostCall ) { @@ -64,7 +65,10 @@ internal class OldEventPostCall @Inject internal constructor( return Observable.defer { val eventPayload = EventPayload() val eventsToPost = payloadGenerator.getEvents(events) - stateManager.markObjectsAs(eventsToPost, State.UPLOADING) + trackerPostStateManager.setPayloadStates( + events = eventsToPost, + forcedState = State.UPLOADING + ) val progressManager = D2ProgressManager(1) @@ -80,7 +84,7 @@ internal class OldEventPostCall @Inject internal constructor( handleWebResponse(webResponse, eventsToPost) Observable.just(progressManager.increaseProgress(Event::class.java, true)) } catch (e: Exception) { - stateManager.markObjectsAs(eventsToPost, State.TO_UPDATE) + trackerPostStateManager.restorePayloadStates(events = eventsToPost) Observable.error(e) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt index 3a89a2da7d..93ea9d44f2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt @@ -45,6 +45,7 @@ import org.hisp.dhis.android.core.imports.internal.RelationshipWebResponse import org.hisp.dhis.android.core.relationship.Relationship import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor +import org.hisp.dhis.android.core.trackedentity.internal.TrackerPostStateManager import java.lang.Exception import javax.inject.Inject @@ -54,6 +55,7 @@ internal class RelationshipPostCall @Inject internal constructor( private val relationshipStore: RelationshipStore, private val relationshipImportHandler: RelationshipImportHandler, private val dataStatePropagator: DataStatePropagator, + private val trackerStateManager: TrackerPostStateManager, private val apiCallExecutor: APICallExecutor ) { @@ -88,9 +90,12 @@ internal class RelationshipPostCall @Inject internal constructor( Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) } else { Observable.defer { - val payload = RelationshipPayload.builder().relationships(relationships).build() - try { + val payload = RelationshipPayload.builder().relationships(relationships).build() + trackerStateManager.setPayloadStates( + relationships = relationships, + forcedState = State.UPLOADING + ) val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( relationshipService.postRelationship(payload), listOf(409), @@ -103,6 +108,8 @@ internal class RelationshipPostCall @Inject internal constructor( ) Observable.just(progressManager.increaseProgress(Relationship::class.java, false)) } catch (e: Exception) { + trackerStateManager.restorePayloadStates(relationships = relationships) + relationships.forEach { dataStatePropagator.propagateRelationshipUpdate(it.from()) } Observable.error(e) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt index 1a7525a2d4..d8ed3194cf 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt @@ -45,7 +45,7 @@ import javax.inject.Inject @Reusable internal class OldTrackedEntityInstancePostCall @Inject internal constructor( private val payloadGenerator29: TrackedEntityInstancePostPayloadGenerator29, - private val stateManager: TrackedEntityInstancePostStateManager, + private val stateManager: TrackerPostStateManager, private val versionManager: DHISVersionManager, private val trackedEntityInstanceService: TrackedEntityInstanceService, private val teiWebResponseHandler: TEIWebResponseHandler, @@ -71,7 +71,10 @@ internal class OldTrackedEntityInstancePostCall @Inject internal constructor( val teiPartitions = payloadGenerator29.getTrackedEntityInstancesPartitions29(filteredTrackedEntityInstances) val progressManager = D2ProgressManager(teiPartitions.size) for (partition in teiPartitions) { - stateManager.setPartitionStates(partition, State.UPLOADING) + stateManager.setPayloadStates( + trackedEntityInstances = partition, + forcedState = State.UPLOADING + ) val thisPartition = relationshipPostCall.postDeletedRelationships29(partition) try { val trackedEntityInstancePayload = TrackedEntityInstancePayload.create(thisPartition) @@ -86,7 +89,7 @@ internal class OldTrackedEntityInstancePostCall @Inject internal constructor( teiWebResponseHandler.handleWebResponse(webResponse, thisPartition) emitter.onNext(progressManager.increaseProgress(TrackedEntityInstance::class.java, false)) } catch (e: Exception) { - stateManager.restorePartitionStates(thisPartition) + stateManager.restorePayloadStates(trackedEntityInstances = thisPartition) if (e is D2Error && e.isOffline) { emitter.onError(e) break diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt index 8f7a6f8555..ce456a107e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt @@ -50,7 +50,7 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance @Reusable internal class OldTrackerImporterPostCall @Inject internal constructor( private val trackerImporterPayloadGenerator: OldTrackerImporterPayloadGenerator, - private val trackedEntityInstanceStateManager: TrackedEntityInstancePostStateManager, + private val trackerStateManager: TrackerPostStateManager, private val eventPostStateManager: EventPostStateManager, private val trackedEntityInstanceService: TrackedEntityInstanceService, private val eventService: EventService, @@ -98,7 +98,10 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( for (partition in teiPartitions) { try { - trackedEntityInstanceStateManager.setPartitionStates(partition, State.UPLOADING) + trackerStateManager.setPayloadStates( + trackedEntityInstances = partition, + forcedState = State.UPLOADING + ) val trackedEntityInstancePayload = TrackedEntityInstancePayload.create(partition) val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( trackedEntityInstanceService.postTrackedEntityInstances( @@ -111,7 +114,7 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( teiWebResponseHandler.handleWebResponse(webResponse, partition) emitter.onNext(progressManager.increaseProgress(TrackedEntityInstance::class.java, false)) } catch (e: Exception) { - trackedEntityInstanceStateManager.restorePartitionStates(partition) + trackerStateManager.restorePayloadStates(partition) if (e is D2Error && e.isOffline) { emitter.onError(e) break @@ -139,7 +142,10 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( } else { Observable.defer { val eventPayload = EventPayload() - eventPostStateManager.markObjectsAs(events, State.UPLOADING) + trackerStateManager.setPayloadStates( + events = events, + forcedState = State.UPLOADING + ) eventPayload.events = events val strategy = "SYNC" @@ -159,7 +165,7 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( ) Observable.just(progressManager.increaseProgress(Event::class.java, true)) } catch (e: Exception) { - eventPostStateManager.markObjectsAs(events, State.TO_UPDATE) + trackerStateManager.restorePayloadStates(events = events) Observable.error(e) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackerPostStateManager.kt similarity index 82% rename from core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt rename to core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackerPostStateManager.kt index 0afcc07183..d652f1cceb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostStateManager.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackerPostStateManager.kt @@ -34,14 +34,16 @@ import org.hisp.dhis.android.core.common.CoreColumns import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.EnrollmentInternalAccessor import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.relationship.Relationship import org.hisp.dhis.android.core.relationship.internal.RelationshipStore import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor @Reusable -internal class TrackedEntityInstancePostStateManager @Inject internal constructor( +internal class TrackerPostStateManager @Inject internal constructor( private val versionManager: DHISVersionManager, private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentStore: EnrollmentStore, @@ -50,18 +52,27 @@ internal class TrackedEntityInstancePostStateManager @Inject internal constructo private val h: StatePersistorHelper ) { - fun restorePartitionStates(partition: List) { - setPartitionStates(partition, null) + fun restorePayloadStates( + trackedEntityInstances: List = emptyList(), + events: List = emptyList(), + relationships: List = emptyList() + ) { + setPayloadStates(trackedEntityInstances, events, relationships, null) } @Suppress("NestedBlockDepth") - fun setPartitionStates(partition: List, forcedState: State?) { + fun setPayloadStates( + trackedEntityInstances: List = emptyList(), + events: List = emptyList(), + relationships: List = emptyList(), + forcedState: State? + ) { val teiMap: MutableMap> = mutableMapOf() val enrollmentMap: MutableMap> = mutableMapOf() val eventMap: MutableMap> = mutableMapOf() val relationshipMap: MutableMap> = mutableMapOf() - for (instance in partition) { + trackedEntityInstances.forEach { instance -> h.addState(teiMap, instance, forcedState) TrackedEntityInstanceInternalAccessor.accessEnrollments(instance)?.forEach { enrollment -> h.addState(enrollmentMap, enrollment, forcedState) @@ -80,6 +91,10 @@ internal class TrackedEntityInstancePostStateManager @Inject internal constructo } } + events.forEach { h.addState(eventMap, it, forcedState) } + + relationships.forEach { h.addState(relationshipMap, it, forcedState) } + h.persistStates(teiMap, trackedEntityInstanceStore) h.persistStates(enrollmentMap, enrollmentStore) h.persistStates(eventMap, eventStore) From 95074a2ff8dddfbbdabdac03fa0341b0085791fa Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 23 Aug 2021 17:35:14 +0200 Subject: [PATCH 275/308] [ANDROSDK-344] Ktlint --- ...erPayloadGeneratorMockIntegrationShould.kt | 2 +- ...PayloadGenerator29MockIntegrationShould.kt | 1 - .../core/event/internal/OldEventPostCall.kt | 3 ++- .../imports/internal/TEIWebResponseHandler.kt | 4 ++-- .../internal/RelationshipImportHandler.kt | 2 +- .../internal/RelationshipItemStore.kt | 2 +- .../internal/RelationshipItemStoreImpl.kt | 21 +++++++++++-------- .../internal/RelationshipPostCall.kt | 17 ++++++++------- .../internal/RelationshipService.kt | 2 +- .../OldTrackedEntityInstancePostCall.kt | 3 ++- .../internal/OldTrackerImporterPayload.kt | 2 +- .../OldTrackerImporterPayloadGenerator.kt | 16 ++++++++------ .../internal/OldTrackerImporterPostCall.kt | 9 ++++---- ...kedEntityInstancePostPayloadGenerator29.kt | 15 +++++++------ .../RelationshipImportHandlerShould.kt | 2 +- ...rackedEntityInstanceImportHandlerShould.kt | 4 ++-- 16 files changed, 59 insertions(+), 46 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt index d0efc2a507..4e2a103daf 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGeneratorMockIntegrationShould.kt @@ -156,7 +156,7 @@ class OldTrackerImporterPayloadGeneratorMockIntegrationShould : BasePayloadGener assertThat(payload.relationships.size).isEqualTo(1) payload.trackedEntityInstances.forEach { - when(it.uid()) { + when (it.uid()) { fromTei -> assertThat(TrackedEntityInstanceInternalAccessor.accessEnrollments(it)).isEmpty() toTei -> assertThat(TrackedEntityInstanceInternalAccessor.accessEnrollments(it)).isNotEmpty() else -> fail("Unexpected trackedEntityInstance uid: " + it.uid()) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt index cb6ac2df94..227a394794 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt @@ -277,5 +277,4 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BasePay assertThat(eventStore.selectByUid(event1Id)!!.syncState()).isEqualTo(State.TO_UPDATE) assertThat(eventStore.selectByUid(event2Id)!!.syncState()).isEqualTo(State.SYNCED) } - } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt index 9e0e215d48..ea28c5c54e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/OldEventPostCall.kt @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.event.internal import dagger.Reusable import io.reactivex.Observable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager @@ -38,7 +39,6 @@ import org.hisp.dhis.android.core.imports.internal.EventWebResponse import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.internal.OldTrackerImporterPostCall import org.hisp.dhis.android.core.trackedentity.internal.TrackerPostStateManager -import javax.inject.Inject @Reusable internal class OldEventPostCall @Inject internal constructor( @@ -59,6 +59,7 @@ internal class OldEventPostCall @Inject internal constructor( } } + @Suppress("TooGenericExceptionCaught") private fun uploadEvents29( events: List ): Observable { diff --git a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt index b8709c3215..0b622faa50 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/imports/internal/TEIWebResponseHandler.kt @@ -28,9 +28,9 @@ package org.hisp.dhis.android.core.imports.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceImportHandler -import javax.inject.Inject @Reusable internal class TEIWebResponseHandler @Inject constructor( @@ -47,4 +47,4 @@ internal class TEIWebResponseHandler @Inject constructor( ) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt index dc801acf25..03b92c5ff7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.relationship.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.StoreUtils.getSyncState import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.common.internal.DataStatePropagator @@ -35,7 +36,6 @@ import org.hisp.dhis.android.core.imports.internal.BaseImportSummaryHelper.getRe import org.hisp.dhis.android.core.imports.internal.RelationshipImportSummary import org.hisp.dhis.android.core.relationship.Relationship import org.hisp.dhis.android.core.relationship.RelationshipCollectionRepository -import javax.inject.Inject @Reusable class RelationshipImportHandler @Inject internal constructor( private val relationshipStore: RelationshipStore, diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt index 35063cdbb6..d0de03d020 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt @@ -41,4 +41,4 @@ internal interface RelationshipItemStore : ObjectWithoutUidStore): List -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt index ea4ffecc54..ee87d31a7f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.relationship.internal import android.database.Cursor +import java.util.* import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -39,7 +40,6 @@ import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidOrNull import org.hisp.dhis.android.core.relationship.RelationshipConstraintType import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.relationship.RelationshipItemTableInfo -import java.util.* internal class RelationshipItemStoreImpl private constructor( databaseAdapter: DatabaseAdapter, @@ -50,8 +50,11 @@ internal class RelationshipItemStoreImpl private constructor( BINDER, WHERE_UPDATE_BINDER, WHERE_DELETE_BINDER, - { cursor: Cursor -> RelationshipItem.create(cursor) }), RelationshipItemStore { + { cursor: Cursor -> RelationshipItem.create(cursor) } +), + RelationshipItemStore { + @Suppress("NestedBlockDepth") override fun getRelationshipUidsForItems(from: RelationshipItem, to: RelationshipItem): List { val relationships: MutableList = ArrayList() @@ -113,12 +116,12 @@ internal class RelationshipItemStoreImpl private constructor( private fun getAllItemsOfSameType(from: RelationshipItem, to: RelationshipItem): Cursor { val query = "SELECT " + RelationshipItemTableInfo.Columns.RELATIONSHIP + ", " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + - "THEN " + getItemElementColumn(from) + " END) AS fromElementUid, " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + - "THEN " + getItemElementColumn(to) + " END) AS toElementUid " + - "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + - " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + + "THEN " + getItemElementColumn(from) + " END) AS fromElementUid, " + + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + + "THEN " + getItemElementColumn(to) + " END) AS toElementUid " + + "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + + " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP return databaseAdapter.rawQuery(query) } @@ -162,4 +165,4 @@ internal class RelationshipItemStoreImpl private constructor( ) } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt index 93ea9d44f2..185e38b559 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipPostCall.kt @@ -31,6 +31,8 @@ import dagger.Reusable import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.ObservableEmitter +import java.net.HttpURLConnection.* +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager @@ -46,8 +48,6 @@ import org.hisp.dhis.android.core.relationship.Relationship import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor import org.hisp.dhis.android.core.trackedentity.internal.TrackerPostStateManager -import java.lang.Exception -import javax.inject.Inject @Reusable internal class RelationshipPostCall @Inject internal constructor( @@ -63,13 +63,14 @@ internal class RelationshipPostCall @Inject internal constructor( return Observable.create { emitter: ObservableEmitter -> for (relationship in relationships) { val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( - relationshipService.deleteRelationship(relationship.uid()!!), listOf(404), + relationshipService.deleteRelationship(relationship.uid()!!), + listOf(HTTP_NOT_FOUND), RelationshipDeleteWebResponse::class.java ) val status = httpResponse.response()?.status() - if ((httpResponse.httpStatusCode() == 200 && ImportStatus.SUCCESS == status) || - httpResponse.httpStatusCode() == 404 + if ((httpResponse.httpStatusCode() == HTTP_OK && ImportStatus.SUCCESS == status) || + httpResponse.httpStatusCode() == HTTP_NOT_FOUND ) { relationshipStore.delete(relationship.uid()!!) } else { @@ -83,6 +84,7 @@ internal class RelationshipPostCall @Inject internal constructor( } } + @Suppress("TooGenericExceptionCaught") fun postRelationships(relationships: List): Observable { val progressManager = D2ProgressManager(null) @@ -98,7 +100,7 @@ internal class RelationshipPostCall @Inject internal constructor( ) val httpResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( relationshipService.postRelationship(payload), - listOf(409), + listOf(HTTP_CONFLICT), RelationshipWebResponse::class.java ) @@ -142,7 +144,6 @@ internal class RelationshipPostCall @Inject internal constructor( .appendKeyStringValue(CoreColumns.ID, relationship.id()).build() relationshipStore.deleteWhereIfExists(whereClause) return@fromCallable RelationshipDeleteWebResponse.empty() - } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt index c22a850d9d..adcc2ec12b 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipService.kt @@ -46,4 +46,4 @@ internal interface RelationshipService { companion object { const val RELATIONSHIPS = "relationships" } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt index d8ed3194cf..98d71f17e2 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackedEntityInstancePostCall.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.ObservableEmitter +import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager @@ -40,7 +41,6 @@ import org.hisp.dhis.android.core.maintenance.D2Error import org.hisp.dhis.android.core.relationship.internal.RelationshipPostCall import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import javax.inject.Inject @Reusable internal class OldTrackedEntityInstancePostCall @Inject internal constructor( @@ -64,6 +64,7 @@ internal class OldTrackedEntityInstancePostCall @Inject internal constructor( } } + @Suppress("TooGenericExceptionCaught") private fun uploadTrackedEntityInstances29( filteredTrackedEntityInstances: List ): Observable { diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt index e1f95254aa..69d5ee8b38 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayload.kt @@ -48,4 +48,4 @@ internal data class OldTrackerImporterPayload( relationships = relationships + other.relationships ) } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt index 812ae43bad..b1db923bff 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPayloadGenerator.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.common.DataColumns @@ -47,9 +48,9 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor -import javax.inject.Inject @Reusable +@Suppress("TooManyFunctions") internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( private val versionManager: DHISVersionManager, private val relationshipRepository: RelationshipCollectionRepository, @@ -126,6 +127,7 @@ internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( return accPayload } + @Suppress("NestedBlockDepth") private fun getMissingItems( payload: OldTrackerImporterPayload, extraData: ExtraData @@ -224,11 +226,13 @@ internal class OldTrackerImporterPayloadGenerator @Inject internal constructor( eventMap = eventStore.queryEventsAttachedToEnrollmentToPost(), enrollmentMap = enrollmentStore.queryEnrollmentsToPost(), attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost(), - notes = noteStore.selectWhere(WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } - ) - .build()), + notes = noteStore.selectWhere( + WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } + ) + .build() + ), relationships = relationshipRepository.bySyncState() .`in`(State.uploadableStatesIncludingError().toList()) .withItems() diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt index ce456a107e..b36439b303 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/OldTrackerImporterPostCall.kt @@ -30,6 +30,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable import io.reactivex.Observable import io.reactivex.ObservableEmitter +import java.net.HttpURLConnection.HTTP_CONFLICT import javax.inject.Inject import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor import org.hisp.dhis.android.core.arch.call.D2Progress @@ -38,7 +39,6 @@ import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.event.internal.EventImportHandler import org.hisp.dhis.android.core.event.internal.EventPayload -import org.hisp.dhis.android.core.event.internal.EventPostStateManager import org.hisp.dhis.android.core.event.internal.EventService import org.hisp.dhis.android.core.imports.internal.EventWebResponse import org.hisp.dhis.android.core.imports.internal.TEIWebResponse @@ -51,7 +51,6 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance internal class OldTrackerImporterPostCall @Inject internal constructor( private val trackerImporterPayloadGenerator: OldTrackerImporterPayloadGenerator, private val trackerStateManager: TrackerPostStateManager, - private val eventPostStateManager: EventPostStateManager, private val trackedEntityInstanceService: TrackedEntityInstanceService, private val eventService: EventService, private val teiWebResponseHandler: TEIWebResponseHandler, @@ -89,6 +88,7 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( } } + @Suppress("TooGenericExceptionCaught") private fun postTrackedEntityInstances( trackedEntityInstances: List ): Observable { @@ -108,7 +108,7 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( trackedEntityInstancePayload, "SYNC" ), @Suppress("MagicNumber") - listOf(409), + listOf(HTTP_CONFLICT), TEIWebResponse::class.java ) teiWebResponseHandler.handleWebResponse(webResponse, partition) @@ -132,6 +132,7 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( } } + @Suppress("TooGenericExceptionCaught") private fun postEvents( events: List ): Observable { @@ -153,7 +154,7 @@ internal class OldTrackerImporterPostCall @Inject internal constructor( val webResponse = apiCallExecutor.executeObjectCallWithAcceptedErrorCodes( eventService.postEvents(eventPayload, strategy), @Suppress("MagicNumber") - listOf(409), + listOf(HTTP_CONFLICT), EventWebResponse::class.java ) eventImportHandler.handleEventImportSummaries( diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt index 52146c4539..94f8e578eb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidsList @@ -49,9 +50,9 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityAttributeValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor -import javax.inject.Inject @Reusable +@Suppress("LongParameterList") internal class TrackedEntityInstancePostPayloadGenerator29 @Inject internal constructor( private val versionManager: DHISVersionManager, private val relationshipDHISVersionManager: RelationshipDHISVersionManager, @@ -91,11 +92,13 @@ internal class TrackedEntityInstancePostPayloadGenerator29 @Inject internal cons eventMap = eventStore.queryEventsAttachedToEnrollmentToPost(), enrollmentMap = enrollmentStore.queryEnrollmentsToPost(), attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost(), - notes = noteStore.selectWhere(WhereClauseBuilder() - .appendInKeyStringValues( - DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } - ) - .build()) + notes = noteStore.selectWhere( + WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.SYNC_STATE, State.uploadableStatesIncludingError().map { it.name } + ) + .build() + ) ) } diff --git a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt index c785b2bfc2..a5de5d6c5f 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipImportHandlerShould.kt @@ -123,4 +123,4 @@ class RelationshipImportHandlerShould { verify(dataStatePropagator, times(2)).propagateRelationshipUpdate(any()) } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt index f1dec8021e..249590b390 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandlerShould.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.trackedentity.internal import com.nhaarman.mockitokotlin2.* +import java.util.* import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.common.internal.DataStatePropagator import org.hisp.dhis.android.core.enrollment.internal.EnrollmentImportHandler @@ -43,7 +44,6 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.mockito.ArgumentMatchers.anyList import org.mockito.ArgumentMatchers.anyString -import java.util.* @RunWith(JUnit4::class) class TrackedEntityInstanceImportHandlerShould { @@ -159,4 +159,4 @@ class TrackedEntityInstanceImportHandlerShould { verify(trackedEntityInstanceStore, times(1)) .setSyncStateOrDelete("missing_tei_uid", State.TO_UPDATE) } -} \ No newline at end of file +} From 40247cb269ae902357850a0c2bed5f3693dcc92d Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 23 Aug 2021 17:46:56 +0200 Subject: [PATCH 276/308] [ANDROSDK-344] Typo --- .../internal/TrackedEntityInstanceImportHandler.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt index 9864f9a310..3339f21d2e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstanceImportHandler.kt @@ -49,7 +49,8 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceTableInfo -@Reusable class TrackedEntityInstanceImportHandler @Inject internal constructor( +@Reusable +internal class TrackedEntityInstanceImportHandler @Inject internal constructor( private val trackedEntityInstanceStore: TrackedEntityInstanceStore, private val enrollmentImportHandler: EnrollmentImportHandler, private val trackerImportConflictStore: TrackerImportConflictStore, From f8bf18e6ac03da92cc5ee2563ad15df261ec1f85 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 24 Aug 2021 07:45:50 +0200 Subject: [PATCH 277/308] [androsdk-1378] Delete unused classes --- ...adWriteWithoutUidCollectionRepository.java | 56 ------------- ...iteWithoutUidCollectionRepositoryImpl.java | 79 ------------------- 2 files changed, 135 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java deleted file mode 100644 index a2e0edb6f2..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/ReadWriteWithoutUidCollectionRepository.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.repositories.collection; - -import org.hisp.dhis.android.core.common.CoreObject; -import org.hisp.dhis.android.core.maintenance.D2Error; - -import io.reactivex.Single; - -public interface ReadWriteWithoutUidCollectionRepository - extends ReadOnlyCollectionRepository { - - /** - * Adds a new object to the given collection in an asynchronous way. - * It returns a {@code Single}. - * @param m the object to add - * @return the Single with a Result - */ - Single add(M m); - - /** - * Adds a new object to the given collection in a synchronous way. - * It blocks the current thread and returns the generated UID. - * Adds a new object to the given collection in an asynchronous way. - * It returns a {@code Single}. Important: this is a blocking method - * and it should not be executed in the main thread. Consider the asynchronous version {@link #add}. - * @param m the object to add - * @return the Single with a Result - */ - M blockingAdd(M m) throws D2Error; -} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java deleted file mode 100644 index e2901b75b1..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/repositories/collection/internal/ReadWriteWithoutUidCollectionRepositoryImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.arch.repositories.collection.internal; - -import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectWithoutUidStore; -import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; -import org.hisp.dhis.android.core.arch.repositories.collection.ReadOnlyCollectionRepository; -import org.hisp.dhis.android.core.arch.repositories.collection.ReadWriteWithoutUidCollectionRepository; -import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; -import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; -import org.hisp.dhis.android.core.common.CoreObject; -import org.hisp.dhis.android.core.maintenance.D2Error; -import org.hisp.dhis.android.core.maintenance.D2ErrorCode; -import org.hisp.dhis.android.core.maintenance.D2ErrorComponent; - -import java.util.Map; - -import io.reactivex.Single; - -public abstract class ReadWriteWithoutUidCollectionRepositoryImpl - > - extends ReadOnlyCollectionRepositoryImpl - implements ReadWriteWithoutUidCollectionRepository { - - private final ObjectWithoutUidStore store; - - public ReadWriteWithoutUidCollectionRepositoryImpl(ObjectWithoutUidStore store, - Map> childrenAppenders, - RepositoryScope scope, - FilterConnectorFactory cf) { - super(store, childrenAppenders, scope, cf); - this.store = store; - } - - public Single add(M model) { - return Single.fromCallable(() -> blockingAdd(model)); - } - - @SuppressWarnings({"PMD.PreserveStackTrace"}) - public M blockingAdd(M object) throws D2Error { - try { - store.insert(object); - return object; - } catch (Exception e) { - throw D2Error - .builder() - .errorComponent(D2ErrorComponent.SDK) - .errorCode(D2ErrorCode.OBJECT_CANT_BE_INSERTED) - .errorDescription("Object can't be inserted") - .originalException(e) - .build(); - } - } -} \ No newline at end of file From 53a4ef24409d6c6c5290b81787f4093098c2bedd Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 24 Aug 2021 10:48:12 +0200 Subject: [PATCH 278/308] [androsdk-1412] Add a collection cleaner for visualizations --- .../internal/VisualizationEntityDIModule.kt | 9 +++++++++ .../core/visualization/internal/VisualizationHandler.kt | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt index 1c77ee9473..2677d3e564 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt @@ -30,12 +30,15 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Module import dagger.Provides import dagger.Reusable +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleanerImpl import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.di.internal.IdentifiableStoreProvider import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationTableInfo @Module internal class VisualizationEntityDIModule : IdentifiableStoreProvider { @@ -52,6 +55,12 @@ internal class VisualizationEntityDIModule : IdentifiableStoreProvider { + return CollectionCleanerImpl(VisualizationTableInfo.TABLE_INFO.name(), databaseAdapter) + } + @Provides @Reusable fun childrenAppenders(databaseAdapter: DatabaseAdapter): Map> { diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index 3224606b91..5fcfa96b84 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore @@ -43,6 +44,7 @@ import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLi @Reusable internal class VisualizationHandler @Inject constructor( store: IdentifiableObjectStore, + private val visualizationCollectionCleaner: CollectionCleaner, private val visualizationCategoryDimensionLinkStore: LinkStore, private val dataDimensionItemStore: LinkStore, private val visualizationCategoryDimensionLinkHandler: @@ -53,7 +55,6 @@ internal class VisualizationHandler @Inject constructor( override fun beforeCollectionHandled( oCollection: Collection ): Collection { - store.delete() visualizationCategoryDimensionLinkStore.delete() dataDimensionItemStore.delete() return oCollection @@ -78,4 +79,8 @@ internal class VisualizationHandler @Inject constructor( it.toBuilder().visualization(o.uid()).build() } } + + override fun afterCollectionHandled(oCollection: Collection?) { + visualizationCollectionCleaner.deleteNotPresent(oCollection) + } } From 4fa8a6cbf5239d82e3e6b1ca45caf14322868263 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 24 Aug 2021 10:48:12 +0200 Subject: [PATCH 279/308] fix: [androsdk-1412] Add a collection cleaner for visualizations --- .../internal/VisualizationEntityDIModule.kt | 9 +++++++++ .../core/visualization/internal/VisualizationHandler.kt | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt index 1c77ee9473..2677d3e564 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationEntityDIModule.kt @@ -30,12 +30,15 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Module import dagger.Provides import dagger.Reusable +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleanerImpl import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.di.internal.IdentifiableStoreProvider import org.hisp.dhis.android.core.arch.handlers.internal.Handler import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender import org.hisp.dhis.android.core.visualization.Visualization +import org.hisp.dhis.android.core.visualization.VisualizationTableInfo @Module internal class VisualizationEntityDIModule : IdentifiableStoreProvider { @@ -52,6 +55,12 @@ internal class VisualizationEntityDIModule : IdentifiableStoreProvider { + return CollectionCleanerImpl(VisualizationTableInfo.TABLE_INFO.name(), databaseAdapter) + } + @Provides @Reusable fun childrenAppenders(databaseAdapter: DatabaseAdapter): Map> { diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index 3224606b91..5fcfa96b84 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore @@ -43,6 +44,7 @@ import org.hisp.dhis.android.core.visualization.VisualizationCategoryDimensionLi @Reusable internal class VisualizationHandler @Inject constructor( store: IdentifiableObjectStore, + private val visualizationCollectionCleaner: CollectionCleaner, private val visualizationCategoryDimensionLinkStore: LinkStore, private val dataDimensionItemStore: LinkStore, private val visualizationCategoryDimensionLinkHandler: @@ -53,7 +55,6 @@ internal class VisualizationHandler @Inject constructor( override fun beforeCollectionHandled( oCollection: Collection ): Collection { - store.delete() visualizationCategoryDimensionLinkStore.delete() dataDimensionItemStore.delete() return oCollection @@ -78,4 +79,8 @@ internal class VisualizationHandler @Inject constructor( it.toBuilder().visualization(o.uid()).build() } } + + override fun afterCollectionHandled(oCollection: Collection?) { + visualizationCollectionCleaner.deleteNotPresent(oCollection) + } } From 9a4bc289c2427c8ccc026c63ecbf9b881db16949 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 24 Aug 2021 12:08:23 +0200 Subject: [PATCH 280/308] [androsdk-1412] KtlintFormat --- .../android/core/visualization/internal/VisualizationHandler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt index 5fcfa96b84..0ff6ce0ca7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandler.kt @@ -28,8 +28,8 @@ package org.hisp.dhis.android.core.visualization.internal import dagger.Reusable -import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner import javax.inject.Inject +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction From f47906d71bb429466e0138c021515b0f9ad84722 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 24 Aug 2021 13:07:47 +0200 Subject: [PATCH 281/308] [androsdk-1412] Fix tests --- .../visualization/internal/VisualizationHandlerShould.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java index 8f05d2055d..7d4d452750 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java @@ -27,6 +27,7 @@ */ package org.hisp.dhis.android.core.visualization.internal; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.db.stores.internal.LinkStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; @@ -58,6 +59,9 @@ public class VisualizationHandlerShould { @Mock private IdentifiableObjectStore visualizationStore; + @Mock + private CollectionCleaner visualizationCollectionCleaner; + @Mock private LinkStore dataDimensionItemStore; @@ -99,6 +103,7 @@ public void setUp() throws Exception { MockitoAnnotations.openMocks(this); visualizationHandler = new VisualizationHandler( visualizationStore, + visualizationCollectionCleaner, visualizationCategoryDimensionLinkStore, dataDimensionItemStore, visualizationCategoryDimensionLinkHandler, From 4a38d1402b5263101827393db19f90ce4579a23f Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Tue, 24 Aug 2021 13:14:28 +0200 Subject: [PATCH 282/308] [androsdk-1412] Fix another test --- .../core/visualization/internal/VisualizationHandlerShould.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java index 7d4d452750..fbbbf3c7db 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java @@ -127,7 +127,7 @@ public void setUp() throws Exception { @Test public void extend_identifiable_sync_handler_impl() { IdentifiableHandlerImpl genericHandler = new VisualizationHandler - (visualizationStore, visualizationCategoryDimensionLinkStore, dataDimensionItemStore, + (visualizationStore, visualizationCollectionCleaner, visualizationCategoryDimensionLinkStore, dataDimensionItemStore, visualizationCategoryDimensionLinkHandler, dataDimensionItemHandler); } From 187f8fd85ba0e81902dd76e93cb2341455f38f15 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 24 Aug 2021 13:16:02 +0200 Subject: [PATCH 283/308] [ANDROSDK-344] Do not execute base test --- .../internal/BasePayloadGeneratorMockIntegration.kt | 1 - ...EntityInstancePostPayloadGenerator29MockIntegrationShould.kt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt index 3f936afa30..665b6c9ff0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt @@ -58,7 +58,6 @@ import org.junit.After import org.junit.BeforeClass import org.junit.runner.RunWith -@RunWith(D2JunitRunner::class) open class BasePayloadGeneratorMockIntegration : BaseMockIntegrationTestMetadataEnqueable() { protected val teiId = "teiId" diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt index 227a394794..52f3f5e1d0 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould.kt @@ -134,7 +134,7 @@ class TrackedEntityInstancePostPayloadGenerator29MockIntegrationShould : BasePay d2.trackedEntityModule().trackedEntityInstances().blockingUpload() assertThat(d2.trackedEntityModule().trackedEntityInstances().blockingCount()).isEqualTo(0) assertThat(d2.enrollmentModule().enrollments().blockingCount()).isEqualTo(0) - assertThat(d2.eventModule().events().blockingCount()).isEqualTo(0) + assertThat(d2.eventModule().events().byEnrollmentUid().isNotNull.blockingCount()).isEqualTo(0) assertThat(d2.importModule().trackerImportConflicts().blockingCount()).isEqualTo(0) } From 786a8b972cc11684d97050a11f10ecb2f36e23c6 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 24 Aug 2021 13:34:01 +0200 Subject: [PATCH 284/308] [ANDROSDK-344] Unused imports --- .../internal/BasePayloadGeneratorMockIntegration.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt index 665b6c9ff0..cd4ac2fb2a 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/trackedentity/internal/BasePayloadGeneratorMockIntegration.kt @@ -53,10 +53,8 @@ import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeStore import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceInternalAccessor import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestMetadataEnqueable -import org.hisp.dhis.android.core.utils.runner.D2JunitRunner import org.junit.After import org.junit.BeforeClass -import org.junit.runner.RunWith open class BasePayloadGeneratorMockIntegration : BaseMockIntegrationTestMetadataEnqueable() { From 040bfc7ee50f3bb40f78be2ce05081a1730f731b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 24 Aug 2021 13:43:12 +0200 Subject: [PATCH 285/308] [ANDROAPP-2275-2] Support any kind of relationship in Helper --- .../RelationshipCollectionRepository.java | 9 ++- .../core/relationship/RelationshipHelper.java | 71 ++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index d27485ff0c..6f892390ae 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -106,7 +106,6 @@ public Single add(Relationship relationship) { @Override public String blockingAdd(Relationship relationship) throws D2Error { Relationship relationshipWithUid; - RelationshipItem from = relationship.from(); if (relationshipHandler.doesRelationshipExist(relationship)) { throw D2Error .builder() @@ -114,7 +113,15 @@ public String blockingAdd(Relationship relationship) throws D2Error { .errorCode(D2ErrorCode.CANT_CREATE_EXISTING_OBJECT) .errorDescription("Tried to create already existing Relationship: " + relationship) .build(); + } else if (relationship.from() == null || relationship.to() == null) { + throw D2Error + .builder() + .errorComponent(D2ErrorComponent.SDK) + .errorCode(D2ErrorCode.CANT_CREATE_EXISTING_OBJECT) + .errorDescription("Relationship is missing either 'from' or 'to' component.") + .build(); } else { + RelationshipItem from = relationship.from(); if (relationship.uid() == null) { String generatedUid = new UidGeneratorImpl().generate(); relationshipWithUid = relationship.toBuilder().uid(generatedUid).build(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java index b8b286bdb8..6e8d755152 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipHelper.java @@ -69,11 +69,76 @@ public static RelationshipItem eventItem(String uid) { } public static Relationship teiToTeiRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.teiItem(fromUid), + RelationshipHelper.teiItem(toUid), + relationshipTypeUid); + } + + public static Relationship teiToEnrollmentRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.teiItem(fromUid), + RelationshipHelper.enrollmentItem(toUid), + relationshipTypeUid); + } + + public static Relationship teiToEventRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.teiItem(fromUid), + RelationshipHelper.eventItem(toUid), + relationshipTypeUid); + } + + public static Relationship enrollmentToTeiRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.enrollmentItem(fromUid), + RelationshipHelper.teiItem(toUid), + relationshipTypeUid); + } + + public static Relationship enrollmentToEnrollmentRelationship(String fromUid, + String toUid, + String relationshipTypeUid) { + return relationship( + RelationshipHelper.enrollmentItem(fromUid), + RelationshipHelper.enrollmentItem(toUid), + relationshipTypeUid); + } + + public static Relationship enrollmentToEventRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.enrollmentItem(fromUid), + RelationshipHelper.eventItem(toUid), + relationshipTypeUid); + } + + public static Relationship eventToTeiRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.eventItem(fromUid), + RelationshipHelper.teiItem(toUid), + relationshipTypeUid); + } + + public static Relationship eventToEnrollmentRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.eventItem(fromUid), + RelationshipHelper.enrollmentItem(toUid), + relationshipTypeUid); + } + + public static Relationship eventToEventRelationship(String fromUid, String toUid, String relationshipTypeUid) { + return relationship( + RelationshipHelper.eventItem(fromUid), + RelationshipHelper.eventItem(toUid), + relationshipTypeUid); + } + + public static Relationship relationship(RelationshipItem from, RelationshipItem to, String type) { return Relationship.builder() .uid(new UidGeneratorImpl().generate()) - .from(RelationshipHelper.teiItem(fromUid)) - .to(RelationshipHelper.teiItem(toUid)) - .relationshipType(relationshipTypeUid) + .from(from) + .to(to) + .relationshipType(type) .build(); } From 6bcb55b83bd05b080bd14feabe6a172e11c2db7b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 24 Aug 2021 14:19:32 +0200 Subject: [PATCH 286/308] [ANDROAPP-2275-2] Improve performance of relationship repository --- .../RelationshipCollectionRepository.java | 87 +++++++------------ .../internal/RelationshipItemStore.kt | 2 + .../internal/RelationshipItemStoreImpl.kt | 38 ++++---- 3 files changed, 56 insertions(+), 71 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 6f892390ae..42e7910fb9 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -27,11 +27,14 @@ */ package org.hisp.dhis.android.core.relationship; +import static org.hisp.dhis.android.core.arch.helpers.CollectionsHelper.isDeleted; +import static org.hisp.dhis.android.core.relationship.RelationshipConstraintType.FROM; +import static org.hisp.dhis.android.core.relationship.RelationshipConstraintType.TO; + import androidx.annotation.NonNull; import org.hisp.dhis.android.core.arch.db.stores.internal.StoreWithState; import org.hisp.dhis.android.core.arch.helpers.UidGeneratorImpl; -import org.hisp.dhis.android.core.arch.helpers.UidsHelper; import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; import org.hisp.dhis.android.core.arch.repositories.collection.ReadWriteWithUidCollectionRepository; import org.hisp.dhis.android.core.arch.repositories.collection.internal.BaseReadOnlyWithUidCollectionRepositoryImpl; @@ -54,7 +57,6 @@ import org.hisp.dhis.android.core.relationship.internal.RelationshipStore; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -63,11 +65,6 @@ import dagger.Reusable; import io.reactivex.Single; -import static org.hisp.dhis.android.core.arch.helpers.CollectionsHelper.isDeleted; -import static org.hisp.dhis.android.core.relationship.RelationshipConstraintType.FROM; -import static org.hisp.dhis.android.core.relationship.RelationshipConstraintType.TO; -import static org.hisp.dhis.android.core.relationship.RelationshipHelper.areItemsEqual; - @Reusable @SuppressWarnings("PMD.ExcessiveImports") public class RelationshipCollectionRepository @@ -168,64 +165,42 @@ public List getByItem(@NonNull RelationshipItem searchItem) { public List getByItem(@NonNull RelationshipItem searchItem, Boolean includeDeleted) { - // TODO Create query to avoid retrieving the whole table - List relationshipItems = this.relationshipItemStore.selectAll(); - - List allRelationshipsFromDb = this.store.selectAll(); - List relationships = new ArrayList<>(); + List relationshipItems = this.relationshipItemStore.getByItem(searchItem); + for (RelationshipItem iterationItem : relationshipItems) { - if (areItemsEqual(searchItem, iterationItem)) { - Relationship relationshipFromDb = - UidsHelper.findByUid(allRelationshipsFromDb, iterationItem.relationship().uid()); - - if (relationshipFromDb == null) { - continue; - } - - if (!includeDeleted && isDeleted(relationshipFromDb)) { - continue; - } - - RelationshipConstraintType itemType = iterationItem.relationshipItemType(); - - RelationshipItem relatedItem = findRelatedTEI(relationshipItems, - iterationItem.relationship().uid(), itemType == FROM ? TO : FROM); - - if (relatedItem == null) { - continue; - } - - RelationshipItem from, to; - if (itemType == FROM) { - from = iterationItem; - to = relatedItem; - } else { - from = relatedItem; - to = iterationItem; - } - - Relationship relationship = relationshipFromDb.toBuilder() - .from(from) - .to(to) - .build(); + Relationship relationship = this.store.selectByUid(iterationItem.relationship().uid()); - relationships.add(relationship); + if (relationship == null) { + continue; } - } - return relationships; - } + if (!includeDeleted && isDeleted(relationship)) { + continue; + } + + RelationshipConstraintType relatedType = iterationItem.relationshipItemType() == FROM ? TO : FROM; - private RelationshipItem findRelatedTEI(Collection items, String relationshipUid, - RelationshipConstraintType type) { - for (RelationshipItem item : items) { - if (relationshipUid.equals(item.relationship().uid()) && item.relationshipItemType() == type) { - return item; + RelationshipItem relatedItem = this.relationshipItemStore + .getForRelationshipUidAndConstraintType(relationship.uid(), relatedType); + + RelationshipItem from, to; + if (iterationItem.relationshipItemType() == FROM) { + from = iterationItem; + to = relatedItem; + } else { + from = relatedItem; + to = iterationItem; } + + relationships.add(relationship.toBuilder() + .from(from) + .to(to) + .build()); } - return null; + + return relationships; } public StringFilterConnector byUid() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt index d0de03d020..9a5e757883 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt @@ -41,4 +41,6 @@ internal interface RelationshipItemStore : ObjectWithoutUidStore): List + + fun getByItem(item: RelationshipItem): List } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt index ee87d31a7f..04fb1db0c8 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt @@ -28,7 +28,6 @@ package org.hisp.dhis.android.core.relationship.internal import android.database.Cursor -import java.util.* import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -40,6 +39,7 @@ import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidOrNull import org.hisp.dhis.android.core.relationship.RelationshipConstraintType import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.relationship.RelationshipItemTableInfo +import java.util.* internal class RelationshipItemStoreImpl private constructor( databaseAdapter: DatabaseAdapter, @@ -114,25 +114,33 @@ internal class RelationshipItemStoreImpl private constructor( return relatedRelationshipItems.map { it.trackedEntityInstance()!!.trackedEntityInstance() } } + override fun getByItem(item: RelationshipItem): List { + val clauseBuilder = WhereClauseBuilder().apply { + appendKeyStringValue(item.elementType(), item.elementUid()) + + item.relationshipItemType()?.let { + appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE, it.name) + } + + item.relationship()?.let { + appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP, it.uid()) + } + } + + return selectWhere(clauseBuilder.build()) + } + private fun getAllItemsOfSameType(from: RelationshipItem, to: RelationshipItem): Cursor { val query = "SELECT " + RelationshipItemTableInfo.Columns.RELATIONSHIP + ", " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + - "THEN " + getItemElementColumn(from) + " END) AS fromElementUid, " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + - "THEN " + getItemElementColumn(to) + " END) AS toElementUid " + - "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + - " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + + "THEN " + from.elementType() + " END) AS fromElementUid, " + + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + + "THEN " + to.elementType() + " END) AS toElementUid " + + "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + + " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP return databaseAdapter.rawQuery(query) } - private fun getItemElementColumn(item: RelationshipItem): String { - return when { - item.hasTrackedEntityInstance() -> RelationshipItemTableInfo.Columns.TRACKED_ENTITY_INSTANCE - item.hasEnrollment() -> RelationshipItemTableInfo.Columns.ENROLLMENT - else -> RelationshipItemTableInfo.Columns.EVENT - } - } - companion object { private val BINDER = StatementBinder { o: RelationshipItem, w: StatementWrapper -> val trackedEntityInstance = if (o.trackedEntityInstance() == null) null else o.trackedEntityInstance()!! From fd187e948032a649f9b281e24fc879746cb872e3 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 24 Aug 2021 16:52:05 +0200 Subject: [PATCH 287/308] [ANDROAPP-2275-2] Include filter by entityType in RelationType repository --- ...ectionRepositoryMockIntegrationShould.java | 96 +++++++++++++++++++ .../RelationshipTypeCollectionRepository.java | 57 ++++++++++- ...ationshipTypeCollectionRepositoryHelper.kt | 90 +++++++++++++++++ .../relationship/relationship_types.json | 33 ++++++- 4 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java new file mode 100644 index 0000000000..b563920840 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship; + +import static com.google.common.truth.Truth.assertThat; + +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 java.util.List; + +@RunWith(D2JunitRunner.class) +public class RelationshipTypeCollectionRepositoryMockIntegrationShould extends BaseMockIntegrationTestFullDispatcher { + + @Test + public void find_all() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(4); + } + + @Test + public void find_with_constraints() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .byUid().eq("WiH6923nMtb") + .withConstraints() + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(1); + for (RelationshipType type : relationshipTypes) { + assertThat(type.fromConstraint()).isNotNull(); + assertThat(type.toConstraint()).isNotNull(); + } + } + + @Test + public void by_tracked_entity_instance() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .byTrackedEntityInstanceAvailability("nWrB0TfWlvh") + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(2); + } + + @Test + public void by_enrollment() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .byEnrollmentAvailability("enroll1") + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(1); + } + + @Test + public void by_event() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .byEventAvailability("single1") + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(1); + } +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java index 2267d1ee38..8d1b2fd5ce 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java @@ -36,7 +36,14 @@ import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; import org.hisp.dhis.android.core.common.IdentifiableColumns; +import org.hisp.dhis.android.core.enrollment.Enrollment; +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; +import org.hisp.dhis.android.core.event.Event; +import org.hisp.dhis.android.core.event.internal.EventStore; +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper; import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields; +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; import java.util.Map; @@ -48,12 +55,23 @@ public final class RelationshipTypeCollectionRepository extends ReadOnlyIdentifiableCollectionRepositoryImpl { + private final TrackedEntityInstanceStore teiStore; + private final EnrollmentStore enrollmentStore; + private final EventStore eventStore; + @Inject RelationshipTypeCollectionRepository(final IdentifiableObjectStore store, + final TrackedEntityInstanceStore teiStore, + final EnrollmentStore enrollmentStore, + final EventStore eventStore, final Map> childrenAppenders, final RepositoryScope scope) { super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, - s -> new RelationshipTypeCollectionRepository(store, childrenAppenders, s))); + s -> new RelationshipTypeCollectionRepository(store, teiStore, enrollmentStore, eventStore, + childrenAppenders, s))); + this.teiStore = teiStore; + this.enrollmentStore = enrollmentStore; + this.eventStore = eventStore; } public RelationshipTypeCollectionRepository byConstraint(@NonNull RelationshipEntityType relationshipEntityType, @@ -71,8 +89,39 @@ public RelationshipTypeCollectionRepository byConstraint( return cf.subQuery(IdentifiableColumns.UID).inTableWhere( RelationshipConstraintTableInfo.TABLE_INFO.name(), RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - constraintClauseBuilder(relationshipEntityType, relationshipEntityUid).appendKeyStringValue( - RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, relationshipConstraintType)); + constraintClauseBuilder(relationshipEntityType, relationshipEntityUid) + .appendKeyStringValue( + RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, + relationshipConstraintType + ) + ); + } + + public RelationshipTypeCollectionRepository byEventAvailability(@NonNull String eventUid) { + Event event = eventStore.selectByUid(eventUid); + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + RelationshipTypeCollectionRepositoryHelper.availabilityEventQuery(event) + ); + } + + public RelationshipTypeCollectionRepository byTrackedEntityInstanceAvailability(@NonNull String teiUid) { + TrackedEntityInstance trackedEntityInstance = teiStore.selectByUid(teiUid); + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + RelationshipTypeCollectionRepositoryHelper.availabilityTeiQuery(trackedEntityInstance) + ); + } + + public RelationshipTypeCollectionRepository byEnrollmentAvailability(@NonNull String enrollmentUid) { + Enrollment enrollment = enrollmentStore.selectByUid(enrollmentUid); + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + RelationshipTypeCollectionRepositoryHelper.availabilityEnrollmentQuery(enrollment) + ); } public RelationshipTypeCollectionRepository withConstraints() { @@ -86,7 +135,7 @@ private WhereClauseBuilder constraintClauseBuilder(RelationshipEntityType relati RelationshipConstraintTableInfo.Columns.RELATIONSHIP_ENTITY, relationshipEntityType) .appendKeyStringValue(getRelationshipEntityColumn(relationshipEntityType), relationshipEntityUid); } - + private String getRelationshipEntityColumn(@NonNull RelationshipEntityType relationshipEntityType) { switch (relationshipEntityType) { case TRACKED_ENTITY_INSTANCE: diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt new file mode 100644 index 0000000000..8852275051 --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.relationship.RelationshipConstraintTableInfo.Columns +import org.hisp.dhis.android.core.relationship.RelationshipEntityType +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance + + +object RelationshipTypeCollectionRepositoryHelper { + + @JvmStatic + fun availabilityTeiQuery(tei: TrackedEntityInstance?): WhereClauseBuilder { + return tei?.let { + WhereClauseBuilder() + .appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.TRACKED_ENTITY_INSTANCE) + .appendComplexQuery( + WhereClauseBuilder() + .appendKeyStringValue(Columns.TRACKED_ENTITY_TYPE, it.trackedEntityType()) + .appendComplexQuery( + appendOptionalEnrollmentInProgram(tei) + ).build() + ) + } ?: WhereClauseBuilder() + } + + private fun appendOptionalEnrollmentInProgram(tei: TrackedEntityInstance): String { + return WhereClauseBuilder() + .appendIsNullValue(Columns.PROGRAM) + .appendOrInSubQuery( + Columns.PROGRAM, + "SELECT ${EnrollmentTableInfo.Columns.PROGRAM} FROM ${EnrollmentTableInfo.TABLE_INFO.name()}" + + " WHERE ${EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE} == '${tei.uid()}'" + ) + .build() + } + + @JvmStatic + fun availabilityEnrollmentQuery(enrollment: Enrollment?): WhereClauseBuilder { + return enrollment?.let { + WhereClauseBuilder() + .appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.PROGRAM_INSTANCE) + .appendKeyStringValue(Columns.PROGRAM, enrollment.program()) + } ?: WhereClauseBuilder() + } + + @JvmStatic + fun availabilityEventQuery(event: Event?): WhereClauseBuilder { + return event?.let { + WhereClauseBuilder() + .appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.PROGRAM_STAGE_INSTANCE) + .appendComplexQuery( + WhereClauseBuilder() + .appendOrKeyStringValue(Columns.PROGRAM, it.program()) + .appendOrKeyStringValue(Columns.PROGRAM_STAGE, it.programStage()) + .build() + ) + } ?: WhereClauseBuilder() + } +} \ No newline at end of file diff --git a/core/src/sharedTest/resources/relationship/relationship_types.json b/core/src/sharedTest/resources/relationship/relationship_types.json index 2c6e3c9f79..cdef158247 100644 --- a/core/src/sharedTest/resources/relationship/relationship_types.json +++ b/core/src/sharedTest/resources/relationship/relationship_types.json @@ -38,11 +38,36 @@ { "created": "2013-09-19T15:17:41.000", "lastUpdated": "2014-04-14T13:53:20.166", - "name": "Mother-Child", + "name": "Mother-Child_b-to-a_(Person-Person)", "id": "V2kkHafqs8G", - "displayName": "Mother-Child", - "bIsToA": "Child", - "aIsToB": "Mother" + "displayName": "Mother-Child_b-to-a_(Person-Person)", + "access": { + "read": true, + "update": true, + "externalize": false, + "delete": true, + "write": true, + "manage": true, + "data": { + "read": true, + "write": false + } + }, + "fromConstraint": { + "relationshipEntity": "TRACKED_ENTITY_INSTANCE", + "trackedEntityType": { + "id": "nEenWmSyUEp" + }, + "program": { + "id": "lxAQ7Zs9VYR" + } + }, + "toConstraint": { + "relationshipEntity": "PROGRAM_STAGE_INSTANCE", + "program": { + "id": "lxAQ7Zs9VYR" + } + } }, { "created": "2014-04-14T13:53:38.659", From 65ef73097f7f92c22a361dc0c13fddb859c5f414 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 24 Aug 2021 17:30:47 +0200 Subject: [PATCH 288/308] [ANDROAPP-2275-2] Include constraintType filter --- ...ectionRepositoryMockIntegrationShould.java | 10 ++ .../RelationshipTypeCollectionRepository.java | 151 ----------------- .../RelationshipTypeCollectionRepository.kt | 153 ++++++++++++++++++ ...ationshipTypeCollectionRepositoryHelper.kt | 49 +++--- ...java => RelationshipTypeEntityDIModule.kt} | 49 +++--- .../relationship/relationship_types.json | 4 +- 6 files changed, 221 insertions(+), 195 deletions(-) delete mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java create mode 100644 core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt rename core/src/main/java/org/hisp/dhis/android/core/relationship/internal/{RelationshipTypeEntityDIModule.java => RelationshipTypeEntityDIModule.kt} (60%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java index b563920840..7bf604a3fd 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java @@ -74,6 +74,16 @@ public void by_tracked_entity_instance() { assertThat(relationshipTypes.size()).isEqualTo(2); } + @Test + public void by_tracked_entity_instance_with_constraint_type() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .byTrackedEntityInstanceAvailability("nWrB0TfWlvh", RelationshipConstraintType.FROM) + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(1); + } + @Test public void by_enrollment() { List relationshipTypes = diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java deleted file mode 100644 index 8d1b2fd5ce..0000000000 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2004-2021, 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.core.relationship; - -import androidx.annotation.NonNull; - -import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; -import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnlyIdentifiableCollectionRepositoryImpl; -import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory; -import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope; -import org.hisp.dhis.android.core.common.IdentifiableColumns; -import org.hisp.dhis.android.core.enrollment.Enrollment; -import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; -import org.hisp.dhis.android.core.event.Event; -import org.hisp.dhis.android.core.event.internal.EventStore; -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper; -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields; -import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; -import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore; - -import java.util.Map; - -import javax.inject.Inject; - -import dagger.Reusable; - -@Reusable -public final class RelationshipTypeCollectionRepository - extends ReadOnlyIdentifiableCollectionRepositoryImpl { - - private final TrackedEntityInstanceStore teiStore; - private final EnrollmentStore enrollmentStore; - private final EventStore eventStore; - - @Inject - RelationshipTypeCollectionRepository(final IdentifiableObjectStore store, - final TrackedEntityInstanceStore teiStore, - final EnrollmentStore enrollmentStore, - final EventStore eventStore, - final Map> childrenAppenders, - final RepositoryScope scope) { - super(store, childrenAppenders, scope, new FilterConnectorFactory<>(scope, - s -> new RelationshipTypeCollectionRepository(store, teiStore, enrollmentStore, eventStore, - childrenAppenders, s))); - this.teiStore = teiStore; - this.enrollmentStore = enrollmentStore; - this.eventStore = eventStore; - } - - public RelationshipTypeCollectionRepository byConstraint(@NonNull RelationshipEntityType relationshipEntityType, - @NonNull String relationshipEntityUid) { - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - constraintClauseBuilder(relationshipEntityType, relationshipEntityUid)); - } - - public RelationshipTypeCollectionRepository byConstraint( - @NonNull RelationshipEntityType relationshipEntityType, - @NonNull String relationshipEntityUid, - @NonNull RelationshipConstraintType relationshipConstraintType) { - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - constraintClauseBuilder(relationshipEntityType, relationshipEntityUid) - .appendKeyStringValue( - RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, - relationshipConstraintType - ) - ); - } - - public RelationshipTypeCollectionRepository byEventAvailability(@NonNull String eventUid) { - Event event = eventStore.selectByUid(eventUid); - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - RelationshipTypeCollectionRepositoryHelper.availabilityEventQuery(event) - ); - } - - public RelationshipTypeCollectionRepository byTrackedEntityInstanceAvailability(@NonNull String teiUid) { - TrackedEntityInstance trackedEntityInstance = teiStore.selectByUid(teiUid); - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - RelationshipTypeCollectionRepositoryHelper.availabilityTeiQuery(trackedEntityInstance) - ); - } - - public RelationshipTypeCollectionRepository byEnrollmentAvailability(@NonNull String enrollmentUid) { - Enrollment enrollment = enrollmentStore.selectByUid(enrollmentUid); - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - RelationshipTypeCollectionRepositoryHelper.availabilityEnrollmentQuery(enrollment) - ); - } - - public RelationshipTypeCollectionRepository withConstraints() { - return cf.withChild(RelationshipTypeFields.CONSTRAINTS); - } - - private WhereClauseBuilder constraintClauseBuilder(RelationshipEntityType relationshipEntityType, - String relationshipEntityUid) { - return new WhereClauseBuilder() - .appendKeyStringValue( - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_ENTITY, relationshipEntityType) - .appendKeyStringValue(getRelationshipEntityColumn(relationshipEntityType), relationshipEntityUid); - } - - private String getRelationshipEntityColumn(@NonNull RelationshipEntityType relationshipEntityType) { - switch (relationshipEntityType) { - case TRACKED_ENTITY_INSTANCE: - return RelationshipConstraintTableInfo.Columns.TRACKED_ENTITY_TYPE; - case PROGRAM_INSTANCE: - return RelationshipConstraintTableInfo.Columns.PROGRAM; - case PROGRAM_STAGE_INSTANCE: - return RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE; - default: - return null; - } - } -} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt new file mode 100644 index 0000000000..3f8b451e7b --- /dev/null +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship + +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender +import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnlyIdentifiableCollectionRepositoryImpl +import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory +import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope +import org.hisp.dhis.android.core.common.IdentifiableColumns +import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore +import org.hisp.dhis.android.core.event.internal.EventStore +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityEnrollmentQuery +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityEventQuery +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityTeiQuery +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields +import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore +import javax.inject.Inject + +@Reusable +class RelationshipTypeCollectionRepository @Inject internal constructor( + store: IdentifiableObjectStore, + private val teiStore: TrackedEntityInstanceStore, + private val enrollmentStore: EnrollmentStore, + private val eventStore: EventStore, + childrenAppenders: MutableMap>, + scope: RepositoryScope +) : ReadOnlyIdentifiableCollectionRepositoryImpl(store, + childrenAppenders, + scope, + FilterConnectorFactory(scope) { s: RepositoryScope -> + RelationshipTypeCollectionRepository( + store, teiStore, enrollmentStore, eventStore, + childrenAppenders, s + ) + } +) { + fun byConstraint( + relationshipEntityType: RelationshipEntityType, + relationshipEntityUid: String + ): RelationshipTypeCollectionRepository { + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + constraintClauseBuilder(relationshipEntityType, relationshipEntityUid) + ) + } + + fun byConstraint( + relationshipEntityType: RelationshipEntityType, + relationshipEntityUid: String, + relationshipConstraintType: RelationshipConstraintType + ): RelationshipTypeCollectionRepository { + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + constraintClauseBuilder(relationshipEntityType, relationshipEntityUid) + .appendKeyStringValue( + RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, + relationshipConstraintType + ) + ) + } + + @JvmOverloads + fun byEventAvailability( + eventUid: String, + type: RelationshipConstraintType? = null + ): RelationshipTypeCollectionRepository { + val event = eventStore.selectByUid(eventUid) + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + availabilityEventQuery(event, type) + ) + } + + @JvmOverloads + fun byTrackedEntityInstanceAvailability( + teiUid: String, + type: RelationshipConstraintType? = null + ): RelationshipTypeCollectionRepository { + val trackedEntityInstance = teiStore.selectByUid(teiUid) + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + availabilityTeiQuery(trackedEntityInstance, type) + ) + } + + @JvmOverloads + fun byEnrollmentAvailability( + enrollmentUid: String, + type: RelationshipConstraintType? = null + ): RelationshipTypeCollectionRepository { + val enrollment = enrollmentStore.selectByUid(enrollmentUid) + return cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + availabilityEnrollmentQuery(enrollment, type) + ) + } + + fun withConstraints(): RelationshipTypeCollectionRepository { + return cf.withChild(RelationshipTypeFields.CONSTRAINTS)!! + } + + private fun constraintClauseBuilder( + relationshipEntityType: RelationshipEntityType, + relationshipEntityUid: String + ): WhereClauseBuilder { + return WhereClauseBuilder() + .appendKeyStringValue( + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_ENTITY, relationshipEntityType + ) + .appendKeyStringValue(getRelationshipEntityColumn(relationshipEntityType), relationshipEntityUid) + } + + private fun getRelationshipEntityColumn(relationshipEntityType: RelationshipEntityType): String { + return when (relationshipEntityType) { + RelationshipEntityType.TRACKED_ENTITY_INSTANCE -> RelationshipConstraintTableInfo.Columns.TRACKED_ENTITY_TYPE + RelationshipEntityType.PROGRAM_INSTANCE -> RelationshipConstraintTableInfo.Columns.PROGRAM + RelationshipEntityType.PROGRAM_STAGE_INSTANCE -> RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt index 8852275051..9000d7dfda 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt @@ -33,6 +33,7 @@ import org.hisp.dhis.android.core.enrollment.Enrollment import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.relationship.RelationshipConstraintTableInfo.Columns +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType import org.hisp.dhis.android.core.relationship.RelationshipEntityType import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance @@ -40,18 +41,22 @@ import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance object RelationshipTypeCollectionRepositoryHelper { @JvmStatic - fun availabilityTeiQuery(tei: TrackedEntityInstance?): WhereClauseBuilder { - return tei?.let { - WhereClauseBuilder() - .appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.TRACKED_ENTITY_INSTANCE) - .appendComplexQuery( + fun availabilityTeiQuery(tei: TrackedEntityInstance?, type: RelationshipConstraintType?): WhereClauseBuilder { + return WhereClauseBuilder().apply { + tei?.let { + if (type != null) { + appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) + } + appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.TRACKED_ENTITY_INSTANCE) + appendComplexQuery( WhereClauseBuilder() .appendKeyStringValue(Columns.TRACKED_ENTITY_TYPE, it.trackedEntityType()) .appendComplexQuery( appendOptionalEnrollmentInProgram(tei) ).build() ) - } ?: WhereClauseBuilder() + } + } } private fun appendOptionalEnrollmentInProgram(tei: TrackedEntityInstance): String { @@ -66,25 +71,33 @@ object RelationshipTypeCollectionRepositoryHelper { } @JvmStatic - fun availabilityEnrollmentQuery(enrollment: Enrollment?): WhereClauseBuilder { - return enrollment?.let { - WhereClauseBuilder() - .appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.PROGRAM_INSTANCE) - .appendKeyStringValue(Columns.PROGRAM, enrollment.program()) - } ?: WhereClauseBuilder() + fun availabilityEnrollmentQuery(enrollment: Enrollment?, type: RelationshipConstraintType?): WhereClauseBuilder { + return WhereClauseBuilder().apply { + enrollment?.let { + if (type != null) { + appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) + } + appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.PROGRAM_INSTANCE) + appendKeyStringValue(Columns.PROGRAM, enrollment.program()) + } + } } @JvmStatic - fun availabilityEventQuery(event: Event?): WhereClauseBuilder { - return event?.let { - WhereClauseBuilder() - .appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.PROGRAM_STAGE_INSTANCE) - .appendComplexQuery( + fun availabilityEventQuery(event: Event?, type: RelationshipConstraintType?): WhereClauseBuilder { + return WhereClauseBuilder().apply { + event?.let { + if (type != null) { + appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) + } + appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.PROGRAM_STAGE_INSTANCE) + appendComplexQuery( WhereClauseBuilder() .appendOrKeyStringValue(Columns.PROGRAM, it.program()) .appendOrKeyStringValue(Columns.PROGRAM_STAGE, it.programStage()) .build() ) - } ?: WhereClauseBuilder() + } + } } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt similarity index 60% rename from core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.java rename to core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt index 509fe69e9b..3b495f3702 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt @@ -25,43 +25,44 @@ * (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.relationship.internal -package org.hisp.dhis.android.core.relationship.internal; - -import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; -import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; -import org.hisp.dhis.android.core.arch.handlers.internal.Handler; -import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; -import org.hisp.dhis.android.core.relationship.RelationshipType; - -import java.util.Collections; -import java.util.Map; - -import dagger.Module; -import dagger.Provides; -import dagger.Reusable; +import dagger.Module +import dagger.Provides +import dagger.Reusable +import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore +import org.hisp.dhis.android.core.arch.handlers.internal.Handler +import org.hisp.dhis.android.core.relationship.RelationshipType +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeStore +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeHandler +import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender +import org.hisp.dhis.android.core.relationship.internal.RelationshipConstraintChildrenAppender +import org.hisp.dhis.android.core.relationship.internal.RelationshipConstraintStore +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields +import java.util.* @Module -public final class RelationshipTypeEntityDIModule { +internal class RelationshipTypeEntityDIModule { @Provides @Reusable - IdentifiableObjectStore store(DatabaseAdapter databaseAdapter) { - return RelationshipTypeStore.create(databaseAdapter); + fun store(databaseAdapter: DatabaseAdapter): IdentifiableObjectStore { + return RelationshipTypeStore.create(databaseAdapter) } @Provides @Reusable - Handler handler(RelationshipTypeHandler impl) { - return impl; + fun handler(impl: RelationshipTypeHandler): Handler { + return impl } @Provides @Reusable - Map> childrenAppenders(DatabaseAdapter databaseAdapter) { - ChildrenAppender childrenAppender = new RelationshipConstraintChildrenAppender( - RelationshipConstraintStore.create(databaseAdapter) - ); - return Collections.singletonMap(RelationshipTypeFields.CONSTRAINTS, childrenAppender); + fun childrenAppenders(databaseAdapter: DatabaseAdapter): MutableMap> { + val childrenAppender: ChildrenAppender = RelationshipConstraintChildrenAppender( + RelationshipConstraintStore.create(databaseAdapter) + ) + return Collections.singletonMap(RelationshipTypeFields.CONSTRAINTS, childrenAppender) } } \ No newline at end of file diff --git a/core/src/sharedTest/resources/relationship/relationship_types.json b/core/src/sharedTest/resources/relationship/relationship_types.json index cdef158247..5a85e4f44e 100644 --- a/core/src/sharedTest/resources/relationship/relationship_types.json +++ b/core/src/sharedTest/resources/relationship/relationship_types.json @@ -22,13 +22,13 @@ "write": false } }, - "toConstraint": { + "fromConstraint": { "relationshipEntity": "PROGRAM_INSTANCE", "program": { "id": "lxAQ7Zs9VYR" } }, - "fromConstraint": { + "toConstraint": { "relationshipEntity": "TRACKED_ENTITY_INSTANCE", "trackedEntityType": { "id": "nEenWmSyUEp" From 1cbd62e9415a14a4f27b8b952e204d0c150b3b45 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 25 Aug 2021 10:17:42 +0200 Subject: [PATCH 289/308] [androsdk-1412] Add collection cleaner test --- .../internal/VisualizationHandlerShould.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java index fbbbf3c7db..7a5beba296 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java @@ -53,6 +53,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.collect.Lists; + @RunWith(JUnit4.class) public class VisualizationHandlerShould { @@ -83,9 +85,6 @@ public class VisualizationHandlerShould { @Mock private ObjectWithUid category; - @Mock - private ObjectWithUid categoryOption; - @Mock private Visualization visualization; @@ -134,20 +133,26 @@ public void extend_identifiable_sync_handler_impl() { @Test public void call_stores_to_delete_before_collection_handled() { visualizationHandler.handleMany(Collections.singletonList(visualization)); - verify(visualizationStore).delete(); verify(visualizationCategoryDimensionLinkStore).delete(); verify(dataDimensionItemStore).delete(); } @Test public void call_data_dimension_items_handler() { - visualizationHandler.handle(visualization); + visualizationHandler.handleMany(Collections.singletonList(visualization)); verify(dataDimensionItemHandler).handleMany(any(), any(), any()); } @Test public void call_category_dimensions_link_handler() { - visualizationHandler.handle(visualization); + visualizationHandler.handleMany(Collections.singletonList(visualization)); verify(visualizationCategoryDimensionLinkHandler).handleMany(any(), any(), any()); } + + @Test + public void call_collection_cleaner() { + visualizationHandler.handleMany(Collections.singletonList(visualization)); + verify(visualizationCollectionCleaner).deleteNotPresent(any()); + } } +0 \ No newline at end of file From cdc5cd17c720a4a10653aa7b096e60204bca5a7a Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 25 Aug 2021 10:17:42 +0200 Subject: [PATCH 290/308] [androsdk-1412] Add collection cleaner test --- .../internal/VisualizationHandlerShould.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java index fbbbf3c7db..7a5beba296 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/visualization/internal/VisualizationHandlerShould.java @@ -53,6 +53,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.collect.Lists; + @RunWith(JUnit4.class) public class VisualizationHandlerShould { @@ -83,9 +85,6 @@ public class VisualizationHandlerShould { @Mock private ObjectWithUid category; - @Mock - private ObjectWithUid categoryOption; - @Mock private Visualization visualization; @@ -134,20 +133,26 @@ public void extend_identifiable_sync_handler_impl() { @Test public void call_stores_to_delete_before_collection_handled() { visualizationHandler.handleMany(Collections.singletonList(visualization)); - verify(visualizationStore).delete(); verify(visualizationCategoryDimensionLinkStore).delete(); verify(dataDimensionItemStore).delete(); } @Test public void call_data_dimension_items_handler() { - visualizationHandler.handle(visualization); + visualizationHandler.handleMany(Collections.singletonList(visualization)); verify(dataDimensionItemHandler).handleMany(any(), any(), any()); } @Test public void call_category_dimensions_link_handler() { - visualizationHandler.handle(visualization); + visualizationHandler.handleMany(Collections.singletonList(visualization)); verify(visualizationCategoryDimensionLinkHandler).handleMany(any(), any(), any()); } + + @Test + public void call_collection_cleaner() { + visualizationHandler.handleMany(Collections.singletonList(visualization)); + verify(visualizationCollectionCleaner).deleteNotPresent(any()); + } } +0 \ No newline at end of file From 3d5fed5f96fa8998204b828f417cd4165aa8cfd2 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 25 Aug 2021 11:58:09 +0200 Subject: [PATCH 291/308] [androsdk-1393] Clean deleted orgUnits on second sync --- .../OrganisationUnitCallMockIntegrationShould.java | 8 +++++++- .../organisationunit/internal/OrganisationUnitCall.java | 7 ++++++- .../internal/OrganisationUnitEntityDIModule.java | 9 +++++++++ .../internal/OrganisationUnitHandlerImpl.java | 6 ++++++ .../internal/OrganisationUnitCallUnitShould.java | 6 +++++- 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallMockIntegrationShould.java index b0b539cb06..2d7ecee670 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallMockIntegrationShould.java @@ -30,6 +30,8 @@ import android.content.ContentValues; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleanerImpl; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.db.tableinfos.TableInfo; import org.hisp.dhis.android.core.category.CategoryComboTableInfo; @@ -37,6 +39,7 @@ import org.hisp.dhis.android.core.data.organisationunit.OrganisationUnitSamples; import org.hisp.dhis.android.core.dataset.DataSetTableInfo; import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo; import org.hisp.dhis.android.core.program.ProgramTableInfo; import org.hisp.dhis.android.core.user.User; import org.hisp.dhis.android.core.user.UserInternalAccessor; @@ -104,10 +107,13 @@ public void setUp() throws IOException { OrganisationUnitHandler organisationUnitHandler = OrganisationUnitHandlerImpl.create(databaseAdapter); + CollectionCleaner organisationUnitCollectionCleaner = + new CollectionCleanerImpl<>(OrganisationUnitTableInfo.TABLE_INFO.name(), databaseAdapter); + OrganisationUnitDisplayPathTransformer pathTransformer = new OrganisationUnitDisplayPathTransformer(); organisationUnitCall = new OrganisationUnitCall(organisationUnitService, - organisationUnitHandler, pathTransformer) + organisationUnitHandler, pathTransformer, organisationUnitCollectionCleaner) .download(user); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCall.java b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCall.java index fa2bd84767..def77af6fd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCall.java +++ b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCall.java @@ -30,6 +30,7 @@ import androidx.annotation.NonNull; import org.hisp.dhis.android.core.arch.api.payload.internal.Payload; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner; import org.hisp.dhis.android.core.arch.helpers.UidsHelper; import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; import org.hisp.dhis.android.core.user.User; @@ -57,15 +58,18 @@ class OrganisationUnitCall { private final OrganisationUnitService organisationUnitService; private final OrganisationUnitHandler handler; private final OrganisationUnitDisplayPathTransformer pathTransformer; + private final CollectionCleaner collectionCleaner; @Inject OrganisationUnitCall(@NonNull OrganisationUnitService organisationUnitService, @NonNull OrganisationUnitHandler handler, - @NonNull OrganisationUnitDisplayPathTransformer pathTransformer) { + @NonNull OrganisationUnitDisplayPathTransformer pathTransformer, + @NonNull CollectionCleaner collectionCleaner) { this.organisationUnitService = organisationUnitService; this.handler = handler; this.pathTransformer = pathTransformer; + this.collectionCleaner = collectionCleaner; } public Single> download(final User user) { @@ -77,6 +81,7 @@ public Single> download(final User user) { return downloadSearchOrgUnits(rootSearchOrgUnits, user).flatMap(searchOrgUnits -> downloadDataCaptureOrgUnits(rootSearchOrgUnits, searchOrgUnits, user).map(dataCaptureOrgUnits -> { searchOrgUnits.addAll(dataCaptureOrgUnits); + collectionCleaner.deleteNotPresent(searchOrgUnits); return searchOrgUnits; })); }); diff --git a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitEntityDIModule.java b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitEntityDIModule.java index 9fafb6509b..e85ac64b6c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitEntityDIModule.java +++ b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitEntityDIModule.java @@ -28,11 +28,14 @@ package org.hisp.dhis.android.core.organisationunit.internal; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleanerImpl; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.di.internal.IdentifiableStoreProvider; import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender; import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; +import org.hisp.dhis.android.core.organisationunit.OrganisationUnitTableInfo; import java.util.HashMap; import java.util.Map; @@ -57,6 +60,12 @@ public OrganisationUnitHandler handler(DatabaseAdapter databaseAdapter) { return OrganisationUnitHandlerImpl.create(databaseAdapter); } + @Provides + @Reusable + public CollectionCleaner collectionCleaner(DatabaseAdapter databaseAdapter) { + return new CollectionCleanerImpl<>(OrganisationUnitTableInfo.TABLE_INFO.name(), databaseAdapter); + } + @Provides @Reusable public OrganisationUnitDisplayPathTransformer pathTransformer() { diff --git a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java index 0e37a24fca..9809be4b96 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java @@ -30,6 +30,7 @@ import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; @@ -122,6 +123,11 @@ protected void afterObjectHandled(OrganisationUnit organisationUnit, HandleActio addOrganisationUnitOrganisationUnitGroupLink(organisationUnit); } + @Override + protected void afterCollectionHandled(@Nullable Collection organisationUnits) { + super.afterCollectionHandled(organisationUnits); + } + private void addOrganisationUnitProgramLink(@NonNull OrganisationUnit organisationUnit) { List orgUnitPrograms = organisationUnit.programs(); if (orgUnitPrograms != null) { diff --git a/core/src/test/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallUnitShould.java b/core/src/test/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallUnitShould.java index d32af5e718..d667828add 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallUnitShould.java +++ b/core/src/test/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitCallUnitShould.java @@ -30,6 +30,7 @@ import org.hisp.dhis.android.core.arch.api.fields.internal.Fields; import org.hisp.dhis.android.core.arch.api.filters.internal.Filter; import org.hisp.dhis.android.core.arch.api.payload.internal.Payload; +import org.hisp.dhis.android.core.arch.cleaners.internal.CollectionCleaner; import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; import org.hisp.dhis.android.core.user.User; import org.hisp.dhis.android.core.user.UserInternalAccessor; @@ -97,6 +98,9 @@ public class OrganisationUnitCallUnitShould { @Mock private Date lastUpdated; + @Mock + private CollectionCleaner collectionCleaner; + @Mock private OrganisationUnitHandler organisationUnitHandler; @@ -151,7 +155,7 @@ public void setUp() throws IOException { when(user.nationality()).thenReturn("user_nationality"); organisationUnitCall = new OrganisationUnitCall(organisationUnitService, organisationUnitHandler, - organisationUnitDisplayPathTransformer) + organisationUnitDisplayPathTransformer, collectionCleaner) .download(user); //Return only one organisationUnit. From 3bc60d90a269c7fa001f4d8fbc46eceba51e86e7 Mon Sep 17 00:00:00 2001 From: Marcos Campos Date: Wed, 25 Aug 2021 12:21:57 +0200 Subject: [PATCH 292/308] [androsdk-1393] PMD --- .../internal/OrganisationUnitHandlerImpl.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java index 9809be4b96..0e37a24fca 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/organisationunit/internal/OrganisationUnitHandlerImpl.java @@ -30,7 +30,6 @@ import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter; import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; @@ -123,11 +122,6 @@ protected void afterObjectHandled(OrganisationUnit organisationUnit, HandleActio addOrganisationUnitOrganisationUnitGroupLink(organisationUnit); } - @Override - protected void afterCollectionHandled(@Nullable Collection organisationUnits) { - super.afterCollectionHandled(organisationUnits); - } - private void addOrganisationUnitProgramLink(@NonNull OrganisationUnit organisationUnit) { List orgUnitPrograms = organisationUnit.programs(); if (orgUnitPrograms != null) { From a2d519ed5144ae6d373c95cdbaf12bec4a4583e5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 25 Aug 2021 12:23:49 +0200 Subject: [PATCH 293/308] [ANDROAPP-2275-2] Add byBidirectional filter --- ...ectionRepositoryMockIntegrationShould.java | 10 +++ .../RelationshipTypeCollectionRepository.kt | 77 ++++++++++++------- .../relationship/relationship_types.json | 1 + 3 files changed, 62 insertions(+), 26 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java index 7bf604a3fd..2a02c16264 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java @@ -49,6 +49,16 @@ public void find_all() { assertThat(relationshipTypes.size()).isEqualTo(4); } + @Test + public void filter_by_bidirectional() { + List relationshipTypes = + d2.relationshipModule().relationshipTypes() + .byBidirectional().eq(true) + .blockingGet(); + + assertThat(relationshipTypes.size()).isEqualTo(1); + } + @Test public void find_with_constraints() { List relationshipTypes = diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt index 3f8b451e7b..a5bdf8bcae 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt @@ -32,6 +32,7 @@ import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuil import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnlyIdentifiableCollectionRepositoryImpl +import org.hisp.dhis.android.core.arch.repositories.filters.internal.BooleanFilterConnector import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope import org.hisp.dhis.android.core.common.IdentifiableColumns @@ -41,6 +42,7 @@ import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollecti import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityEventQuery import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityTeiQuery import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields +import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore import javax.inject.Inject @@ -50,6 +52,7 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( private val teiStore: TrackedEntityInstanceStore, private val enrollmentStore: EnrollmentStore, private val eventStore: EventStore, + private val dhisVersionManager: DHISVersionManager, childrenAppenders: MutableMap>, scope: RepositoryScope ) : ReadOnlyIdentifiableCollectionRepositoryImpl(store, @@ -58,10 +61,14 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( FilterConnectorFactory(scope) { s: RepositoryScope -> RelationshipTypeCollectionRepository( store, teiStore, enrollmentStore, eventStore, - childrenAppenders, s + dhisVersionManager, childrenAppenders, s ) } ) { + fun byBidirectional(): BooleanFilterConnector { + return cf.bool(RelationshipTypeTableInfo.Columns.BIDIRECTIONAL); + } + fun byConstraint( relationshipEntityType: RelationshipEntityType, relationshipEntityUid: String @@ -90,29 +97,39 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( } @JvmOverloads - fun byEventAvailability( - eventUid: String, + fun byTrackedEntityInstanceAvailability( + teiUid: String, type: RelationshipConstraintType? = null ): RelationshipTypeCollectionRepository { - val event = eventStore.selectByUid(eventUid) - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - availabilityEventQuery(event, type) - ) + return if (dhisVersionManager.is2_29) { + // All relationships are allowed for TEIs in 2.29 + this + } else { + val trackedEntityInstance = teiStore.selectByUid(teiUid) + cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + availabilityTeiQuery(trackedEntityInstance, type) + ) + } } @JvmOverloads - fun byTrackedEntityInstanceAvailability( - teiUid: String, + fun byEventAvailability( + eventUid: String, type: RelationshipConstraintType? = null ): RelationshipTypeCollectionRepository { - val trackedEntityInstance = teiStore.selectByUid(teiUid) - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - availabilityTeiQuery(trackedEntityInstance, type) - ) + return if (dhisVersionManager.is2_29) { + // Event relationships are not supported in 2.29 + cf.string(IdentifiableColumns.UID).`in`(emptyList()) + } else { + val event = eventStore.selectByUid(eventUid) + cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + availabilityEventQuery(event, type) + ) + } } @JvmOverloads @@ -120,12 +137,17 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( enrollmentUid: String, type: RelationshipConstraintType? = null ): RelationshipTypeCollectionRepository { - val enrollment = enrollmentStore.selectByUid(enrollmentUid) - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - availabilityEnrollmentQuery(enrollment, type) - ) + return if (dhisVersionManager.is2_29) { + // Enrollment relationships are not supported in 2.29 + cf.string(IdentifiableColumns.UID).`in`(emptyList()) + } else { + val enrollment = enrollmentStore.selectByUid(enrollmentUid) + cf.subQuery(IdentifiableColumns.UID).inTableWhere( + RelationshipConstraintTableInfo.TABLE_INFO.name(), + RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, + availabilityEnrollmentQuery(enrollment, type) + ) + } } fun withConstraints(): RelationshipTypeCollectionRepository { @@ -145,9 +167,12 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( private fun getRelationshipEntityColumn(relationshipEntityType: RelationshipEntityType): String { return when (relationshipEntityType) { - RelationshipEntityType.TRACKED_ENTITY_INSTANCE -> RelationshipConstraintTableInfo.Columns.TRACKED_ENTITY_TYPE - RelationshipEntityType.PROGRAM_INSTANCE -> RelationshipConstraintTableInfo.Columns.PROGRAM - RelationshipEntityType.PROGRAM_STAGE_INSTANCE -> RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE + RelationshipEntityType.TRACKED_ENTITY_INSTANCE -> + RelationshipConstraintTableInfo.Columns.TRACKED_ENTITY_TYPE + RelationshipEntityType.PROGRAM_INSTANCE -> + RelationshipConstraintTableInfo.Columns.PROGRAM + RelationshipEntityType.PROGRAM_STAGE_INSTANCE -> + RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE } } } \ No newline at end of file diff --git a/core/src/sharedTest/resources/relationship/relationship_types.json b/core/src/sharedTest/resources/relationship/relationship_types.json index 5a85e4f44e..bb27d42217 100644 --- a/core/src/sharedTest/resources/relationship/relationship_types.json +++ b/core/src/sharedTest/resources/relationship/relationship_types.json @@ -40,6 +40,7 @@ "lastUpdated": "2014-04-14T13:53:20.166", "name": "Mother-Child_b-to-a_(Person-Person)", "id": "V2kkHafqs8G", + "bidirectional": false, "displayName": "Mother-Child_b-to-a_(Person-Person)", "access": { "read": true, From 73a31c1044add60b577b0a4e5bd91e34ce092507 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 25 Aug 2021 13:17:30 +0200 Subject: [PATCH 294/308] [ANDROAPP-2275-2] Add bidirectional logic in RelationshpType --- ...ectionRepositoryMockIntegrationShould.java | 10 ---- .../RelationshipTypeCollectionRepository.kt | 56 +++++++------------ ...ationshipTypeCollectionRepositoryHelper.kt | 48 ++++++++++++++-- .../relationship/relationship_types.json | 34 +++++++++-- 4 files changed, 93 insertions(+), 55 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java index 2a02c16264..ed806c94fd 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java @@ -84,16 +84,6 @@ public void by_tracked_entity_instance() { assertThat(relationshipTypes.size()).isEqualTo(2); } - @Test - public void by_tracked_entity_instance_with_constraint_type() { - List relationshipTypes = - d2.relationshipModule().relationshipTypes() - .byTrackedEntityInstanceAvailability("nWrB0TfWlvh", RelationshipConstraintType.FROM) - .blockingGet(); - - assertThat(relationshipTypes.size()).isEqualTo(1); - } - @Test public void by_enrollment() { List relationshipTypes = diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt index a5bdf8bcae..61d05f0f49 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt @@ -35,12 +35,13 @@ import org.hisp.dhis.android.core.arch.repositories.collection.internal.ReadOnly import org.hisp.dhis.android.core.arch.repositories.filters.internal.BooleanFilterConnector import org.hisp.dhis.android.core.arch.repositories.filters.internal.FilterConnectorFactory import org.hisp.dhis.android.core.arch.repositories.scope.RepositoryScope +import org.hisp.dhis.android.core.arch.repositories.scope.internal.FilterItemOperator import org.hisp.dhis.android.core.common.IdentifiableColumns import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore import org.hisp.dhis.android.core.event.internal.EventStore -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityEnrollmentQuery -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityEventQuery -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availabilityTeiQuery +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availableForEnrollmentRawQuery +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availableForEventRawQuery +import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollectionRepositoryHelper.availableForTrackedEntityInstanceRawQuery import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore @@ -96,56 +97,41 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( ) } - @JvmOverloads - fun byTrackedEntityInstanceAvailability( - teiUid: String, - type: RelationshipConstraintType? = null - ): RelationshipTypeCollectionRepository { + fun byTrackedEntityInstanceAvailability(trackedEntityInstanceUid: String): RelationshipTypeCollectionRepository { return if (dhisVersionManager.is2_29) { // All relationships are allowed for TEIs in 2.29 this } else { - val trackedEntityInstance = teiStore.selectByUid(teiUid) - cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - availabilityTeiQuery(trackedEntityInstance, type) + val trackedEntityInstance = teiStore.selectByUid(trackedEntityInstanceUid) + cf.subQuery(IdentifiableColumns.UID).rawSubQuery( + FilterItemOperator.IN, + availableForTrackedEntityInstanceRawQuery(trackedEntityInstance) ) } } - @JvmOverloads - fun byEventAvailability( - eventUid: String, - type: RelationshipConstraintType? = null - ): RelationshipTypeCollectionRepository { + fun byEnrollmentAvailability(enrollmentUid: String): RelationshipTypeCollectionRepository { return if (dhisVersionManager.is2_29) { - // Event relationships are not supported in 2.29 + // Enrollment relationships are not supported in 2.29 cf.string(IdentifiableColumns.UID).`in`(emptyList()) } else { - val event = eventStore.selectByUid(eventUid) - cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - availabilityEventQuery(event, type) + val enrollment = enrollmentStore.selectByUid(enrollmentUid) + cf.subQuery(IdentifiableColumns.UID).rawSubQuery( + FilterItemOperator.IN, + availableForEnrollmentRawQuery(enrollment) ) } } - @JvmOverloads - fun byEnrollmentAvailability( - enrollmentUid: String, - type: RelationshipConstraintType? = null - ): RelationshipTypeCollectionRepository { + fun byEventAvailability(eventUid: String): RelationshipTypeCollectionRepository { return if (dhisVersionManager.is2_29) { - // Enrollment relationships are not supported in 2.29 + // Event relationships are not supported in 2.29 cf.string(IdentifiableColumns.UID).`in`(emptyList()) } else { - val enrollment = enrollmentStore.selectByUid(enrollmentUid) - cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - availabilityEnrollmentQuery(enrollment, type) + val event = eventStore.selectByUid(eventUid) + cf.subQuery(IdentifiableColumns.UID).rawSubQuery( + FilterItemOperator.IN, + availableForEventRawQuery(event) ) } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt index 9000d7dfda..9775aa5149 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt @@ -32,17 +32,24 @@ import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuil import org.hisp.dhis.android.core.enrollment.Enrollment import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.relationship.RelationshipConstraintTableInfo import org.hisp.dhis.android.core.relationship.RelationshipConstraintTableInfo.Columns import org.hisp.dhis.android.core.relationship.RelationshipConstraintType import org.hisp.dhis.android.core.relationship.RelationshipEntityType +import org.hisp.dhis.android.core.relationship.RelationshipTypeTableInfo import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType.FROM object RelationshipTypeCollectionRepositoryHelper { @JvmStatic - fun availabilityTeiQuery(tei: TrackedEntityInstance?, type: RelationshipConstraintType?): WhereClauseBuilder { - return WhereClauseBuilder().apply { + fun availableForTrackedEntityInstanceRawQuery(tei: TrackedEntityInstance?): String { + return availableForItemRawQuery(tei, availabilityTeiQuery) + } + + private val availabilityTeiQuery = {tei: TrackedEntityInstance?, type: RelationshipConstraintType? -> + val whereClause = WhereClauseBuilder().apply { tei?.let { if (type != null) { appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) @@ -57,6 +64,8 @@ object RelationshipTypeCollectionRepositoryHelper { ) } } + + relationshipTypeInConstraint(whereClause.build()) } private fun appendOptionalEnrollmentInProgram(tei: TrackedEntityInstance): String { @@ -71,8 +80,12 @@ object RelationshipTypeCollectionRepositoryHelper { } @JvmStatic - fun availabilityEnrollmentQuery(enrollment: Enrollment?, type: RelationshipConstraintType?): WhereClauseBuilder { - return WhereClauseBuilder().apply { + fun availableForEnrollmentRawQuery(enrollment: Enrollment?): String { + return availableForItemRawQuery(enrollment, availableForEnrollment) + } + + private val availableForEnrollment = { enrollment: Enrollment?, type: RelationshipConstraintType? -> + val whereClause = WhereClauseBuilder().apply { enrollment?.let { if (type != null) { appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) @@ -81,11 +94,17 @@ object RelationshipTypeCollectionRepositoryHelper { appendKeyStringValue(Columns.PROGRAM, enrollment.program()) } } + + relationshipTypeInConstraint(whereClause.build()) } @JvmStatic - fun availabilityEventQuery(event: Event?, type: RelationshipConstraintType?): WhereClauseBuilder { - return WhereClauseBuilder().apply { + fun availableForEventRawQuery(event: Event?): String { + return availableForItemRawQuery(event, availableForEvent) + } + + private val availableForEvent = { event: Event?, type: RelationshipConstraintType? -> + val whereClause = WhereClauseBuilder().apply { event?.let { if (type != null) { appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) @@ -99,5 +118,22 @@ object RelationshipTypeCollectionRepositoryHelper { ) } } + + relationshipTypeInConstraint(whereClause.build()) + } + + private fun availableForItemRawQuery(t: T?, availableForItem: (T, RelationshipConstraintType?) -> String): String { + return t?.let { + "SELECT DISTINCT ${RelationshipTypeTableInfo.Columns.UID} " + + "FROM ${RelationshipTypeTableInfo.TABLE_INFO.name()} " + + "WHERE ${RelationshipTypeTableInfo.Columns.UID} IN (${availableForItem(it, FROM)}) " + + "OR (${RelationshipTypeTableInfo.Columns.BIDIRECTIONAL} = 1 " + + "AND ${RelationshipTypeTableInfo.Columns.UID} IN (${availableForItem(it, null)})) " + } ?: "" + } + + private fun relationshipTypeInConstraint(whereClause: String): String { + return "SELECT ${Columns.RELATIONSHIP_TYPE} FROM ${RelationshipConstraintTableInfo.TABLE_INFO.name()} " + + "WHERE $whereClause" } } \ No newline at end of file diff --git a/core/src/sharedTest/resources/relationship/relationship_types.json b/core/src/sharedTest/resources/relationship/relationship_types.json index bb27d42217..1be02ebd65 100644 --- a/core/src/sharedTest/resources/relationship/relationship_types.json +++ b/core/src/sharedTest/resources/relationship/relationship_types.json @@ -71,13 +71,39 @@ } }, { - "created": "2014-04-14T13:53:38.659", - "lastUpdated": "2014-04-14T13:53:41.066", + "created": "2013-09-19T15:17:41.000", + "lastUpdated": "2014-04-14T13:53:20.166", "name": "Sibling", "id": "o51cUNONthg", + "bidirectional": false, "displayName": "Sibling", - "bIsToA": "Sibling", - "aIsToB": "Sibling" + "access": { + "read": true, + "update": true, + "externalize": false, + "delete": true, + "write": true, + "manage": true, + "data": { + "read": true, + "write": false + } + }, + "fromConstraint": { + "relationshipEntity": "PROGRAM_STAGE_INSTANCE", + "program": { + "id": "lxAQ7Zs9VYR" + } + }, + "toConstraint": { + "relationshipEntity": "TRACKED_ENTITY_INSTANCE", + "trackedEntityType": { + "id": "nEenWmSyUEp" + }, + "program": { + "id": "lxAQ7Zs9VYR" + } + } }, { "created": "2014-04-14T13:53:38.659", From 3c35176d61c5a3df8cd6187df47e071ed93c1a3f Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 25 Aug 2021 14:09:23 +0200 Subject: [PATCH 295/308] [ANDROAPP-2275-2] Add RelationshipTypeCollectionRepositoryHelper unit test --- .../RelationshipTypeCollectionRepository.kt | 9 +- .../internal/RelationshipItemStoreImpl.kt | 14 ++-- ...ationshipTypeCollectionRepositoryHelper.kt | 33 ++++---- .../RelationshipTypeEntityDIModule.kt | 11 +-- ...hipTypeCollectionRepositoryHelperShould.kt | 83 +++++++++++++++++++ 5 files changed, 113 insertions(+), 37 deletions(-) create mode 100644 core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt index 61d05f0f49..fa506d1758 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.relationship import dagger.Reusable +import javax.inject.Inject import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender @@ -45,7 +46,6 @@ import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeCollecti import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields import org.hisp.dhis.android.core.systeminfo.DHISVersionManager import org.hisp.dhis.android.core.trackedentity.internal.TrackedEntityInstanceStore -import javax.inject.Inject @Reusable class RelationshipTypeCollectionRepository @Inject internal constructor( @@ -56,7 +56,8 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( private val dhisVersionManager: DHISVersionManager, childrenAppenders: MutableMap>, scope: RepositoryScope -) : ReadOnlyIdentifiableCollectionRepositoryImpl(store, +) : ReadOnlyIdentifiableCollectionRepositoryImpl( + store, childrenAppenders, scope, FilterConnectorFactory(scope) { s: RepositoryScope -> @@ -67,7 +68,7 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( } ) { fun byBidirectional(): BooleanFilterConnector { - return cf.bool(RelationshipTypeTableInfo.Columns.BIDIRECTIONAL); + return cf.bool(RelationshipTypeTableInfo.Columns.BIDIRECTIONAL) } fun byConstraint( @@ -161,4 +162,4 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( RelationshipConstraintTableInfo.Columns.PROGRAM_STAGE } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt index 04fb1db0c8..63d5f9348c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt @@ -28,6 +28,7 @@ package org.hisp.dhis.android.core.relationship.internal import android.database.Cursor +import java.util.* import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.querybuilders.internal.SQLStatementBuilderImpl import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder @@ -39,7 +40,6 @@ import org.hisp.dhis.android.core.arch.helpers.UidsHelper.getUidOrNull import org.hisp.dhis.android.core.relationship.RelationshipConstraintType import org.hisp.dhis.android.core.relationship.RelationshipItem import org.hisp.dhis.android.core.relationship.RelationshipItemTableInfo -import java.util.* internal class RelationshipItemStoreImpl private constructor( databaseAdapter: DatabaseAdapter, @@ -132,12 +132,12 @@ internal class RelationshipItemStoreImpl private constructor( private fun getAllItemsOfSameType(from: RelationshipItem, to: RelationshipItem): Cursor { val query = "SELECT " + RelationshipItemTableInfo.Columns.RELATIONSHIP + ", " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + - "THEN " + from.elementType() + " END) AS fromElementUid, " + - "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + - "THEN " + to.elementType() + " END) AS toElementUid " + - "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + - " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'FROM' " + + "THEN " + from.elementType() + " END) AS fromElementUid, " + + "MAX(CASE WHEN " + RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE + " = 'TO' " + + "THEN " + to.elementType() + " END) AS toElementUid " + + "FROM " + RelationshipItemTableInfo.TABLE_INFO.name() + + " GROUP BY " + RelationshipItemTableInfo.Columns.RELATIONSHIP return databaseAdapter.rawQuery(query) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt index 9775aa5149..8922d7488c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelper.kt @@ -35,11 +35,10 @@ import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.relationship.RelationshipConstraintTableInfo import org.hisp.dhis.android.core.relationship.RelationshipConstraintTableInfo.Columns import org.hisp.dhis.android.core.relationship.RelationshipConstraintType +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType.FROM import org.hisp.dhis.android.core.relationship.RelationshipEntityType import org.hisp.dhis.android.core.relationship.RelationshipTypeTableInfo import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance -import org.hisp.dhis.android.core.relationship.RelationshipConstraintType.FROM - object RelationshipTypeCollectionRepositoryHelper { @@ -48,20 +47,15 @@ object RelationshipTypeCollectionRepositoryHelper { return availableForItemRawQuery(tei, availabilityTeiQuery) } - private val availabilityTeiQuery = {tei: TrackedEntityInstance?, type: RelationshipConstraintType? -> + private val availabilityTeiQuery = { tei: TrackedEntityInstance?, type: RelationshipConstraintType? -> val whereClause = WhereClauseBuilder().apply { tei?.let { if (type != null) { appendKeyStringValue(Columns.CONSTRAINT_TYPE, type.name) } appendKeyStringValue(Columns.RELATIONSHIP_ENTITY, RelationshipEntityType.TRACKED_ENTITY_INSTANCE) - appendComplexQuery( - WhereClauseBuilder() - .appendKeyStringValue(Columns.TRACKED_ENTITY_TYPE, it.trackedEntityType()) - .appendComplexQuery( - appendOptionalEnrollmentInProgram(tei) - ).build() - ) + appendKeyStringValue(Columns.TRACKED_ENTITY_TYPE, it.trackedEntityType()) + appendComplexQuery(appendOptionalEnrollmentInProgram(tei)) } } @@ -74,7 +68,7 @@ object RelationshipTypeCollectionRepositoryHelper { .appendOrInSubQuery( Columns.PROGRAM, "SELECT ${EnrollmentTableInfo.Columns.PROGRAM} FROM ${EnrollmentTableInfo.TABLE_INFO.name()}" + - " WHERE ${EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE} == '${tei.uid()}'" + " WHERE ${EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE} == '${tei.uid()}'" ) .build() } @@ -122,18 +116,21 @@ object RelationshipTypeCollectionRepositoryHelper { relationshipTypeInConstraint(whereClause.build()) } - private fun availableForItemRawQuery(t: T?, availableForItem: (T, RelationshipConstraintType?) -> String): String { + private fun availableForItemRawQuery( + t: T?, + availableForItem: (T, RelationshipConstraintType?) -> String + ): String { return t?.let { "SELECT DISTINCT ${RelationshipTypeTableInfo.Columns.UID} " + - "FROM ${RelationshipTypeTableInfo.TABLE_INFO.name()} " + - "WHERE ${RelationshipTypeTableInfo.Columns.UID} IN (${availableForItem(it, FROM)}) " + - "OR (${RelationshipTypeTableInfo.Columns.BIDIRECTIONAL} = 1 " + - "AND ${RelationshipTypeTableInfo.Columns.UID} IN (${availableForItem(it, null)})) " + "FROM ${RelationshipTypeTableInfo.TABLE_INFO.name()} " + + "WHERE ${RelationshipTypeTableInfo.Columns.UID} IN (${availableForItem(it, FROM)}) " + + "OR (${RelationshipTypeTableInfo.Columns.BIDIRECTIONAL} = 1 " + + "AND ${RelationshipTypeTableInfo.Columns.UID} IN (${availableForItem(it, null)}))" } ?: "" } private fun relationshipTypeInConstraint(whereClause: String): String { return "SELECT ${Columns.RELATIONSHIP_TYPE} FROM ${RelationshipConstraintTableInfo.TABLE_INFO.name()} " + - "WHERE $whereClause" + "WHERE $whereClause" } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt index 3b495f3702..4ce4b6d178 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeEntityDIModule.kt @@ -30,17 +30,12 @@ package org.hisp.dhis.android.core.relationship.internal import dagger.Module import dagger.Provides import dagger.Reusable +import java.util.* import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore import org.hisp.dhis.android.core.arch.handlers.internal.Handler -import org.hisp.dhis.android.core.relationship.RelationshipType -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeStore -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeHandler import org.hisp.dhis.android.core.arch.repositories.children.internal.ChildrenAppender -import org.hisp.dhis.android.core.relationship.internal.RelationshipConstraintChildrenAppender -import org.hisp.dhis.android.core.relationship.internal.RelationshipConstraintStore -import org.hisp.dhis.android.core.relationship.internal.RelationshipTypeFields -import java.util.* +import org.hisp.dhis.android.core.relationship.RelationshipType @Module internal class RelationshipTypeEntityDIModule { @@ -65,4 +60,4 @@ internal class RelationshipTypeEntityDIModule { ) return Collections.singletonMap(RelationshipTypeFields.CONSTRAINTS, childrenAppender) } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt new file mode 100644 index 0000000000..9cf6f48708 --- /dev/null +++ b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004-2021, 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.core.relationship.internal + +import com.google.common.truth.Truth.assertThat +import com.nhaarman.mockitokotlin2.doReturn +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import org.hisp.dhis.android.core.enrollment.Enrollment +import org.hisp.dhis.android.core.event.Event +import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class RelationshipTypeCollectionRepositoryHelperShould { + + private val trackedEntityInstance: TrackedEntityInstance = mock() + + /** + * Test to showcase the generated sql query + */ + @Test + fun create_tracked_entity_instance_raw_query() { + val teiUid = "tei_uid" + val teiTypeUid = "tei_type_uid" + whenever(trackedEntityInstance.uid()).doReturn(teiUid) + whenever(trackedEntityInstance.trackedEntityType()).doReturn(teiTypeUid) + + val rawQuery = + RelationshipTypeCollectionRepositoryHelper.availableForTrackedEntityInstanceRawQuery(trackedEntityInstance) + + assertThat(rawQuery).isEqualTo( + "SELECT DISTINCT uid FROM RelationshipType " + + "WHERE uid IN " + + "(" + + "SELECT relationshipType FROM RelationshipConstraint " + + "WHERE constraintType = 'FROM' " + + "AND relationshipEntity = 'TRACKED_ENTITY_INSTANCE' " + + "AND trackedEntityType = '$teiTypeUid' " + + "AND (program IS NULL " + + "OR program IN (SELECT program FROM Enrollment WHERE trackedEntityInstance == '$teiUid'))" + + ") " + + "OR " + + "(" + + "bidirectional = 1 " + + "AND uid IN " + + "(" + + "SELECT relationshipType FROM RelationshipConstraint " + + "WHERE relationshipEntity = 'TRACKED_ENTITY_INSTANCE' " + + "AND trackedEntityType = '$teiTypeUid' " + + "AND (program IS NULL " + + "OR program IN (SELECT program FROM Enrollment WHERE trackedEntityInstance == '$teiUid'))" + + ")" + + ")") + } +} From e40a646ebba9830fc520b9118c109a7e539b5265 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 25 Aug 2021 14:17:06 +0200 Subject: [PATCH 296/308] [ANDROAPP-2275-2] Refactor filter names --- ...ectionRepositoryMockIntegrationShould.java | 6 +-- .../RelationshipTypeCollectionRepository.kt | 48 +++++++++++-------- ...hipTypeCollectionRepositoryHelperShould.kt | 45 +++++++++-------- 3 files changed, 53 insertions(+), 46 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java index ed806c94fd..9f9d5b7cbc 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepositoryMockIntegrationShould.java @@ -78,7 +78,7 @@ public void find_with_constraints() { public void by_tracked_entity_instance() { List relationshipTypes = d2.relationshipModule().relationshipTypes() - .byTrackedEntityInstanceAvailability("nWrB0TfWlvh") + .byAvailableForTrackedEntityInstance("nWrB0TfWlvh") .blockingGet(); assertThat(relationshipTypes.size()).isEqualTo(2); @@ -88,7 +88,7 @@ public void by_tracked_entity_instance() { public void by_enrollment() { List relationshipTypes = d2.relationshipModule().relationshipTypes() - .byEnrollmentAvailability("enroll1") + .byAvailableForEnrollment("enroll1") .blockingGet(); assertThat(relationshipTypes.size()).isEqualTo(1); @@ -98,7 +98,7 @@ public void by_enrollment() { public void by_event() { List relationshipTypes = d2.relationshipModule().relationshipTypes() - .byEventAvailability("single1") + .byAvailableForEvent("single1") .blockingGet(); assertThat(relationshipTypes.size()).isEqualTo(1); diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt index fa506d1758..4cac78f453 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipTypeCollectionRepository.kt @@ -71,34 +71,32 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( return cf.bool(RelationshipTypeTableInfo.Columns.BIDIRECTIONAL) } - fun byConstraint( - relationshipEntityType: RelationshipEntityType, - relationshipEntityUid: String - ): RelationshipTypeCollectionRepository { - return cf.subQuery(IdentifiableColumns.UID).inTableWhere( - RelationshipConstraintTableInfo.TABLE_INFO.name(), - RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - constraintClauseBuilder(relationshipEntityType, relationshipEntityUid) - ) - } - + @JvmOverloads fun byConstraint( relationshipEntityType: RelationshipEntityType, relationshipEntityUid: String, - relationshipConstraintType: RelationshipConstraintType + relationshipConstraintType: RelationshipConstraintType? = null ): RelationshipTypeCollectionRepository { return cf.subQuery(IdentifiableColumns.UID).inTableWhere( RelationshipConstraintTableInfo.TABLE_INFO.name(), RelationshipConstraintTableInfo.Columns.RELATIONSHIP_TYPE, - constraintClauseBuilder(relationshipEntityType, relationshipEntityUid) - .appendKeyStringValue( - RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, - relationshipConstraintType - ) + constraintClauseBuilder(relationshipEntityType, relationshipEntityUid).apply { + if (relationshipConstraintType != null) { + appendKeyStringValue( + RelationshipConstraintTableInfo.Columns.CONSTRAINT_TYPE, + relationshipConstraintType + ) + } + } ) } - fun byTrackedEntityInstanceAvailability(trackedEntityInstanceUid: String): RelationshipTypeCollectionRepository { + /** + * Filter RelationshipTypes by those that meets the requirements for this trackedEntityInstance: + * - the TEI might be assigned to the FROM component + * - or the TEI might be assigned to the TO component and the RelationshipType is bidirectional + */ + fun byAvailableForTrackedEntityInstance(trackedEntityInstanceUid: String): RelationshipTypeCollectionRepository { return if (dhisVersionManager.is2_29) { // All relationships are allowed for TEIs in 2.29 this @@ -111,7 +109,12 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( } } - fun byEnrollmentAvailability(enrollmentUid: String): RelationshipTypeCollectionRepository { + /** + * Filter RelationshipTypes by those that meets the requirements for this enrollment: + * - the enrollment might be assigned to the FROM component + * - or the enrollment might be assigned to the TO component and the RelationshipType is bidirectional + */ + fun byAvailableForEnrollment(enrollmentUid: String): RelationshipTypeCollectionRepository { return if (dhisVersionManager.is2_29) { // Enrollment relationships are not supported in 2.29 cf.string(IdentifiableColumns.UID).`in`(emptyList()) @@ -124,7 +127,12 @@ class RelationshipTypeCollectionRepository @Inject internal constructor( } } - fun byEventAvailability(eventUid: String): RelationshipTypeCollectionRepository { + /** + * Filter RelationshipTypes by those that meets the requirements for this event: + * - the event might be assigned to the FROM component + * - or the event might be assigned to the TO component and the RelationshipType is bidirectional + */ + fun byAvailableForEvent(eventUid: String): RelationshipTypeCollectionRepository { return if (dhisVersionManager.is2_29) { // Event relationships are not supported in 2.29 cf.string(IdentifiableColumns.UID).`in`(emptyList()) diff --git a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt index 9cf6f48708..c858b3a051 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt +++ b/core/src/test/java/org/hisp/dhis/android/core/relationship/internal/RelationshipTypeCollectionRepositoryHelperShould.kt @@ -31,8 +31,6 @@ import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.doReturn import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever -import org.hisp.dhis.android.core.enrollment.Enrollment -import org.hisp.dhis.android.core.event.Event import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance import org.junit.Test import org.junit.runner.RunWith @@ -58,26 +56,27 @@ class RelationshipTypeCollectionRepositoryHelperShould { assertThat(rawQuery).isEqualTo( "SELECT DISTINCT uid FROM RelationshipType " + - "WHERE uid IN " + - "(" + - "SELECT relationshipType FROM RelationshipConstraint " + - "WHERE constraintType = 'FROM' " + - "AND relationshipEntity = 'TRACKED_ENTITY_INSTANCE' " + - "AND trackedEntityType = '$teiTypeUid' " + - "AND (program IS NULL " + - "OR program IN (SELECT program FROM Enrollment WHERE trackedEntityInstance == '$teiUid'))" + - ") " + - "OR " + - "(" + - "bidirectional = 1 " + - "AND uid IN " + - "(" + - "SELECT relationshipType FROM RelationshipConstraint " + - "WHERE relationshipEntity = 'TRACKED_ENTITY_INSTANCE' " + - "AND trackedEntityType = '$teiTypeUid' " + - "AND (program IS NULL " + - "OR program IN (SELECT program FROM Enrollment WHERE trackedEntityInstance == '$teiUid'))" + - ")" + - ")") + "WHERE uid IN " + + "(" + + "SELECT relationshipType FROM RelationshipConstraint " + + "WHERE constraintType = 'FROM' " + + "AND relationshipEntity = 'TRACKED_ENTITY_INSTANCE' " + + "AND trackedEntityType = '$teiTypeUid' " + + "AND (program IS NULL " + + "OR program IN (SELECT program FROM Enrollment WHERE trackedEntityInstance == '$teiUid'))" + + ") " + + "OR " + + "(" + + "bidirectional = 1 " + + "AND uid IN " + + "(" + + "SELECT relationshipType FROM RelationshipConstraint " + + "WHERE relationshipEntity = 'TRACKED_ENTITY_INSTANCE' " + + "AND trackedEntityType = '$teiTypeUid' " + + "AND (program IS NULL " + + "OR program IN (SELECT program FROM Enrollment WHERE trackedEntityInstance == '$teiUid'))" + + ")" + + ")" + ) } } From 6391edb0a3cf6d7ab45adc307c15241052e4483e Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 27 Aug 2021 10:18:23 +0200 Subject: [PATCH 297/308] [ANDROSDK-1417] Propagate attribute value update to enrollments --- .../common/internal/DataStatePropagatorImpl.kt | 13 ++++++++++++- .../enrollment/internal/EnrollmentStore.kt | 2 ++ .../enrollment/internal/EnrollmentStoreImpl.kt | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index f85cd4c8f9..76a7a46e21 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -93,7 +93,18 @@ internal class DataStatePropagatorImpl @Inject internal constructor( } override fun propagateTrackedEntityAttributeUpdate(trackedEntityAttributeValue: TrackedEntityAttributeValue?) { - setTeiSyncState(trackedEntityAttributeValue!!.trackedEntityInstance(), getStateForUpdate) + trackedEntityAttributeValue!!.trackedEntityInstance()?.let { trackedEntityInstanceUid -> + val enrollments = enrollmentStore.selectByTrackedEntityInstanceAndAttribute( + trackedEntityInstanceUid, + trackedEntityAttributeValue.trackedEntityAttribute()!! + ) + enrollments.forEach { + enrollmentStore.setSyncState(it.uid(), getStateForUpdate(it.syncState())) + refreshEnrollmentAggregatedSyncState(it.uid()) + refreshEnrollmentLastUpdated(it.uid()) + } + setTeiSyncState(trackedEntityInstanceUid, getStateForUpdate) + } } override fun propagateNoteCreation(note: Note?) { diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt index f09b01b412..6c5c4212e4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStore.kt @@ -40,4 +40,6 @@ internal interface EnrollmentStore : IdentifiableDeletableDataObjectStore + + fun selectByTrackedEntityInstanceAndAttribute(teiUid: String, attributeUid: String): List } diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt index 0fb6846f5b..9ab83f3fc1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt @@ -42,6 +42,7 @@ import org.hisp.dhis.android.core.common.State import org.hisp.dhis.android.core.enrollment.Enrollment import org.hisp.dhis.android.core.enrollment.EnrollmentTableInfo import org.hisp.dhis.android.core.event.EventTableInfo +import org.hisp.dhis.android.core.program.ProgramTrackedEntityAttributeTableInfo internal class EnrollmentStoreImpl private constructor( databaseAdapter: DatabaseAdapter, @@ -87,6 +88,23 @@ internal class EnrollmentStoreImpl private constructor( return statesStr.map { State.valueOf(it) } } + override fun selectByTrackedEntityInstanceAndAttribute( + teiUid: String, + attributeUid: String + ): List { + val whereClause = WhereClauseBuilder() + .appendKeyStringValue(EnrollmentTableInfo.Columns.TRACKED_ENTITY_INSTANCE, teiUid) + .appendInSubQuery( + EnrollmentTableInfo.Columns.PROGRAM, + "SELECT ${ProgramTrackedEntityAttributeTableInfo.Columns.PROGRAM} " + + "FROM ${ProgramTrackedEntityAttributeTableInfo.TABLE_INFO.name()} " + + "WHERE ${ProgramTrackedEntityAttributeTableInfo.Columns.TRACKED_ENTITY_ATTRIBUTE} = " + + "'$attributeUid'" + ).build() + + return selectWhere(whereClause) + } + companion object { private val BINDER = StatementBinder { o: Enrollment, w: StatementWrapper -> w.bind(1, o.uid()) From 694063ca9921d1726cdb3c1d96eb9049582248f2 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 27 Aug 2021 10:23:43 +0200 Subject: [PATCH 298/308] [ANDROSDK-1417] Ktlint --- .../android/core/enrollment/internal/EnrollmentStoreImpl.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt index 9ab83f3fc1..eaf7ec69a4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentStoreImpl.kt @@ -97,9 +97,9 @@ internal class EnrollmentStoreImpl private constructor( .appendInSubQuery( EnrollmentTableInfo.Columns.PROGRAM, "SELECT ${ProgramTrackedEntityAttributeTableInfo.Columns.PROGRAM} " + - "FROM ${ProgramTrackedEntityAttributeTableInfo.TABLE_INFO.name()} " + - "WHERE ${ProgramTrackedEntityAttributeTableInfo.Columns.TRACKED_ENTITY_ATTRIBUTE} = " + - "'$attributeUid'" + "FROM ${ProgramTrackedEntityAttributeTableInfo.TABLE_INFO.name()} " + + "WHERE ${ProgramTrackedEntityAttributeTableInfo.Columns.TRACKED_ENTITY_ATTRIBUTE} = " + + "'$attributeUid'" ).build() return selectWhere(whereClause) From eb535a2ee962bd7141ab2a7cfc8279743f304c84 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 27 Aug 2021 13:05:35 +0200 Subject: [PATCH 299/308] [ANDROSDK-1418] Adapt SMS repository to aggregatedSyncState model --- .../internal/DataStatePropagatorImpl.kt | 4 +- .../internal/LocalDbRepositoryImpl.java | 47 +++++++++++++++---- .../converter/internal/DeletionConverter.java | 11 ++--- .../internal/RelationshipConverter.java | 3 +- .../internal/LocalDbRepository.java | 2 + .../sms/mockrepos/MockLocalDbRepository.java | 5 ++ 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index 76a7a46e21..ab9ad6e14c 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -332,10 +332,10 @@ internal class DataStatePropagatorImpl @Inject internal constructor( states.contains(State.ERROR) -> State.ERROR states.contains(State.WARNING) -> State.WARNING states.contains(State.UPLOADING) || - states.contains(State.SENT_VIA_SMS) || - states.contains(State.SYNCED_VIA_SMS) || states.contains(State.TO_POST) || states.contains(State.TO_UPDATE) -> State.TO_UPDATE + states.contains(State.SENT_VIA_SMS) -> State.SENT_VIA_SMS + states.contains(State.SYNCED_VIA_SMS) -> State.SYNCED_VIA_SMS else -> State.SYNCED } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java index e38aaf3d89..67a3ea51e0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/data/localdbrepository/internal/LocalDbRepositoryImpl.java @@ -32,9 +32,9 @@ import android.content.SharedPreferences; import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; -import org.hisp.dhis.android.core.arch.helpers.UidsHelper; import org.hisp.dhis.android.core.arch.json.internal.ObjectMapperFactory; import org.hisp.dhis.android.core.common.State; +import org.hisp.dhis.android.core.common.internal.DataStatePropagator; import org.hisp.dhis.android.core.dataset.DataSetCompleteRegistrationTableInfo; import org.hisp.dhis.android.core.dataset.internal.DataSetCompleteRegistrationStore; import org.hisp.dhis.android.core.enrollment.Enrollment; @@ -45,6 +45,9 @@ import org.hisp.dhis.android.core.event.EventModule; import org.hisp.dhis.android.core.event.internal.EventStore; import org.hisp.dhis.android.core.relationship.Relationship; +import org.hisp.dhis.android.core.relationship.RelationshipConstraintType; +import org.hisp.dhis.android.core.relationship.RelationshipItem; +import org.hisp.dhis.android.core.relationship.internal.RelationshipItemStore; import org.hisp.dhis.android.core.relationship.internal.RelationshipStore; import org.hisp.dhis.android.core.sms.domain.model.internal.SMSDataValueSet; import org.hisp.dhis.android.core.sms.domain.repository.WebApiRepository; @@ -68,7 +71,7 @@ import io.reactivex.Observable; import io.reactivex.Single; -@SuppressWarnings("PMD.ExcessiveImports") +@SuppressWarnings({"PMD.ExcessiveImports", "PMD.TooManyFields"}) public class LocalDbRepositoryImpl implements LocalDbRepository { private final Context context; private final AuthenticatedUserObjectRepository userRepository; @@ -89,9 +92,11 @@ public class LocalDbRepositoryImpl implements LocalDbRepository { private final MetadataIdsStore metadataIdsStore; private final OngoingSubmissionsStore ongoingSubmissionsStore; private final RelationshipStore relationshipStore; + private final RelationshipItemStore relationshipItemStore; private final DataSetsStore dataSetsStore; private final TrackedEntityInstanceStore trackedEntityInstanceStore; private final DataSetCompleteRegistrationStore dataSetCompleteRegistrationStore; + private final DataStatePropagator dataStatePropagator; @Inject LocalDbRepositoryImpl(Context ctx, @@ -103,9 +108,11 @@ public class LocalDbRepositoryImpl implements LocalDbRepository { EventStore eventStore, EnrollmentStore enrollmentStore, RelationshipStore relationshipStore, + RelationshipItemStore relationshipItemStore, DataSetsStore dataSetsStore, TrackedEntityInstanceStore trackedEntityInstanceStore, - DataSetCompleteRegistrationStore dataSetCompleteRegistrationStore) { + DataSetCompleteRegistrationStore dataSetCompleteRegistrationStore, + DataStatePropagator dataStatePropagator) { this.context = ctx; this.userRepository = userRepository; this.trackedEntityModule = trackedEntityModule; @@ -115,9 +122,11 @@ public class LocalDbRepositoryImpl implements LocalDbRepository { this.eventStore = eventStore; this.enrollmentStore = enrollmentStore; this.relationshipStore = relationshipStore; + this.relationshipItemStore = relationshipItemStore; this.dataSetsStore = dataSetsStore; this.trackedEntityInstanceStore = trackedEntityInstanceStore; this.dataSetCompleteRegistrationStore = dataSetCompleteRegistrationStore; + this.dataStatePropagator = dataStatePropagator; metadataIdsStore = new MetadataIdsStore(context); ongoingSubmissionsStore = new OngoingSubmissionsStore(context); } @@ -267,21 +276,41 @@ private Single> getEventsForEnrollment(String enrollmentUid) { @Override public Completable updateEventSubmissionState(String eventUid, State state) { - return Completable.fromAction(() -> eventStore.setSyncState(eventUid, state)); + return Completable.fromAction(() -> { + eventStore.setSyncState(eventUid, state); + Event event = eventStore.selectByUid(eventUid); + dataStatePropagator.propagateEventUpdate(event); + }); } @Override public Completable updateEnrollmentSubmissionState(TrackedEntityInstance tei, State state) { return Completable.fromAction(() -> { Enrollment enrollment = TrackedEntityInstanceInternalAccessor.accessEnrollments(tei).get(0); - enrollmentStore.setSyncState(enrollment.uid(), state); - trackedEntityInstanceStore.setSyncState(enrollment.trackedEntityInstance(), state); - List events = EnrollmentInternalAccessor.accessEvents(enrollment); + if (events != null && !events.isEmpty()) { - List eventUids = UidsHelper.getUidsList(events); - eventStore.setSyncState(eventUids, state); + for (Event event : events) { + eventStore.setSyncState(event.uid(), state); + dataStatePropagator.propagateEventUpdate(event); + } } + + enrollmentStore.setSyncState(enrollment.uid(), state); + dataStatePropagator.propagateEnrollmentUpdate(enrollment); + + trackedEntityInstanceStore.setSyncState(enrollment.trackedEntityInstance(), state); + dataStatePropagator.propagateTrackedEntityInstanceUpdate(tei); + }); + } + + @Override + public Completable updateRelationshipSubmissionState(String relationshipUid, State state) { + return Completable.fromAction(() -> { + relationshipStore.setSyncState(relationshipUid, state); + RelationshipItem fromItem = relationshipItemStore + .getForRelationshipUidAndConstraintType(relationshipUid, RelationshipConstraintType.FROM); + dataStatePropagator.propagateRelationshipUpdate(fromItem); }); } diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/DeletionConverter.java b/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/DeletionConverter.java index 5dbfd1ce2c..089ee41b6f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/DeletionConverter.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/DeletionConverter.java @@ -40,13 +40,13 @@ import io.reactivex.Single; public class DeletionConverter extends Converter { - private final String uid; + private final String eventUid; public DeletionConverter(LocalDbRepository localDbRepository, DHISVersionManager dhisVersionManager, - String uid) { + String eventUid) { super(localDbRepository, dhisVersionManager); - this.uid = uid; + this.eventUid = eventUid; } @Override @@ -62,12 +62,11 @@ Single convert(@NonNull String uid, String user, int su @Override public Completable updateSubmissionState(State state) { - // there is no submission state update for deletion - return Completable.complete(); + return getLocalDbRepository().updateEventSubmissionState(eventUid, state).onErrorComplete(); } @Override Single readItemFromDb() { - return Single.just(uid); + return Single.just(eventUid); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/RelationshipConverter.java b/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/RelationshipConverter.java index 239b797e61..421f9bfbec 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/RelationshipConverter.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/domain/converter/internal/RelationshipConverter.java @@ -66,8 +66,7 @@ Single convert(@NonNull Relationship relationship, Stri @Override public Completable updateSubmissionState(State state) { - // there is no submission state update for RelationShip - return Completable.complete(); + return getLocalDbRepository().updateRelationshipSubmissionState(relationshipUid, state); } @Override diff --git a/core/src/main/java/org/hisp/dhis/android/core/sms/domain/repository/internal/LocalDbRepository.java b/core/src/main/java/org/hisp/dhis/android/core/sms/domain/repository/internal/LocalDbRepository.java index 5fd584cebd..9652656713 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/sms/domain/repository/internal/LocalDbRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/sms/domain/repository/internal/LocalDbRepository.java @@ -77,6 +77,8 @@ public interface LocalDbRepository { Completable updateEnrollmentSubmissionState(TrackedEntityInstance tei, State state); + Completable updateRelationshipSubmissionState(String relationshipUid, State state); + Completable setMetadataDownloadConfig(WebApiRepository.GetMetadataIdsConfig metadataIdsConfig); Single getMetadataDownloadConfig(); diff --git a/core/src/test/java/org/hisp/dhis/android/core/sms/mockrepos/MockLocalDbRepository.java b/core/src/test/java/org/hisp/dhis/android/core/sms/mockrepos/MockLocalDbRepository.java index e921a3bd79..bdc8b788a0 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/sms/mockrepos/MockLocalDbRepository.java +++ b/core/src/test/java/org/hisp/dhis/android/core/sms/mockrepos/MockLocalDbRepository.java @@ -159,6 +159,11 @@ public Completable updateEnrollmentSubmissionState(TrackedEntityInstance tracked return Completable.complete(); } + @Override + public Completable updateRelationshipSubmissionState(String relationshipUid, State state) { + return Completable.complete(); + } + @Override public Completable setMetadataDownloadConfig(WebApiRepository.GetMetadataIdsConfig metadataIdsConfig) { return Completable.fromAction(() -> this.metadataIdsConfig = metadataIdsConfig); From ab1566ef4aab6d359f83cabd3c851fc1850701bb Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 30 Aug 2021 13:40:20 +0200 Subject: [PATCH 300/308] [1.4.3-RC] Remove support for 2.37 in DHIS2Version --- .../hisp/dhis/android/core/systeminfo/DHISVersion.java | 8 ++------ .../dhis/android/core/systeminfo/DHISVersionManager.java | 2 -- .../core/systeminfo/internal/DHISVersionManagerImpl.java | 5 ----- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java index e1e14c4597..e2729010b5 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersion.java @@ -36,8 +36,7 @@ public enum DHISVersion { V2_33, V2_34, V2_35, - V2_36, - V2_37; + V2_36; private static final String V2_29_STR = "2.29"; private static final String V2_30_STR = "2.30"; @@ -47,7 +46,6 @@ public enum DHISVersion { private static final String V2_34_STR = "2.34"; private static final String V2_35_STR = "2.35"; private static final String V2_36_STR = "2.36"; - private static final String V2_37_STR = "2.37"; public static DHISVersion getValue(String versionStr) { if (versionStr.startsWith(V2_29_STR)) { @@ -66,8 +64,6 @@ public static DHISVersion getValue(String versionStr) { return V2_35; } else if (versionStr.startsWith(V2_36_STR)) { return V2_36; - } else if (versionStr.startsWith(V2_37_STR)) { - return V2_37; } else { return null; } @@ -79,6 +75,6 @@ public static boolean isAllowedVersion(String versionStr) { public static String[] allowedVersionsAsStr() { return new String[]{V2_29_STR, V2_30_STR, V2_31_STR, V2_32_STR, V2_33_STR, V2_34_STR, V2_35_STR, - V2_36_STR, V2_37_STR}; + V2_36_STR}; } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java index 8df9edf3a2..cceda5171f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/DHISVersionManager.java @@ -50,8 +50,6 @@ public interface DHISVersionManager { boolean is2_36(); - boolean is2_37(); - /** * Check if the current version is strictly greater than the parameter. * diff --git a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java index 0a2bb83018..9d9fa25943 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java +++ b/core/src/main/java/org/hisp/dhis/android/core/systeminfo/internal/DHISVersionManagerImpl.java @@ -126,11 +126,6 @@ public boolean is2_36() { return getVersion() == DHISVersion.V2_36; } - @Override - public boolean is2_37() { - return getVersion() == DHISVersion.V2_37; - } - @Override public boolean isGreaterThan(DHISVersion version) { return version.compareTo(getVersion()) < 0; From 91c7d8948325e77e3ed50d01b0d3f3a535210288 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 1 Sep 2021 13:40:03 +0200 Subject: [PATCH 301/308] [ANDROSDK-1420] Accept incomplete Relationships --- .../android/core/common/internal/DataStatePropagatorImpl.kt | 2 +- .../core/relationship/RelationshipCollectionRepository.java | 4 ++++ .../core/relationship/internal/RelationshipItemStore.kt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt index ab9ad6e14c..d59a07bedd 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/internal/DataStatePropagatorImpl.kt @@ -310,7 +310,7 @@ internal class DataStatePropagatorImpl @Inject internal constructor( val trackedEntitiesFromEnrollments = enrollments.mapNotNull { it.trackedEntityInstance() } - val relationshipItems = relationshipUids.map { + val relationshipItems = relationshipUids.mapNotNull { relationshipItemStore.getForRelationshipUidAndConstraintType(it, RelationshipConstraintType.FROM) } diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java index 42e7910fb9..59fa8dbce4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/RelationshipCollectionRepository.java @@ -185,6 +185,10 @@ public List getByItem(@NonNull RelationshipItem searchItem, Boolea RelationshipItem relatedItem = this.relationshipItemStore .getForRelationshipUidAndConstraintType(relationship.uid(), relatedType); + if (relatedItem == null) { + continue; + } + RelationshipItem from, to; if (iterationItem.relationshipItemType() == FROM) { from = iterationItem; diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt index 9a5e757883..cd0619247a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStore.kt @@ -38,7 +38,7 @@ internal interface RelationshipItemStore : ObjectWithoutUidStore): List From b762b37eb209494e1d9392966cb771ace6a42fd5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 1 Sep 2021 14:03:08 +0200 Subject: [PATCH 302/308] [ANDROSDK-1420] Modify store --- .../core/relationship/internal/RelationshipItemStoreImpl.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt index 63d5f9348c..2a7ebeac46 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/relationship/internal/RelationshipItemStoreImpl.kt @@ -77,12 +77,12 @@ internal class RelationshipItemStoreImpl private constructor( override fun getForRelationshipUidAndConstraintType( uid: String, constraintType: RelationshipConstraintType - ): RelationshipItem { + ): RelationshipItem? { val whereClause = WhereClauseBuilder() .appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP, uid) .appendKeyStringValue(RelationshipItemTableInfo.Columns.RELATIONSHIP_ITEM_TYPE, constraintType) .build() - return selectOneWhere(whereClause)!! + return selectOneWhere(whereClause) } override fun getRelatedTeiUids(trackedEntityInstanceUids: List): List { From c2394f586c94931eb699ee57c9abaa158a3ef0ca Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 1 Sep 2021 15:06:48 +0200 Subject: [PATCH 303/308] [1.4.3-RC] Update to version 1.4.3 --- core/build.gradle | 4 ++-- core/gradle.properties | 4 ++-- docs/content/developer/getting-started.md | 2 +- docs/dhis2_android_sdk_developer_guide_INDEX.md | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 88538b6ac8..6beae70e86 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -43,8 +43,8 @@ ext { buildToolsVersion: "29.0.3", minSdkVersion : 19, targetSdkVersion : 29, - versionCode : 242, - versionName : "1.4.2" + versionCode : 243, + versionName : "1.4.3" ] libraries = [ diff --git a/core/gradle.properties b/core/gradle.properties index f0e060f276..1cd5fd5b8a 100644 --- a/core/gradle.properties +++ b/core/gradle.properties @@ -29,8 +29,8 @@ # Properties which are consumed by plugins/gradle-mvn-push.gradle plugin. # They are used for publishing artifact to snapshot repository. -VERSION_NAME=1.4.2 -VERSION_CODE=242 +VERSION_NAME=1.4.3 +VERSION_CODE=243 GROUP=org.hisp.dhis diff --git a/docs/content/developer/getting-started.md b/docs/content/developer/getting-started.md index d78a8accfc..c8423724db 100644 --- a/docs/content/developer/getting-started.md +++ b/docs/content/developer/getting-started.md @@ -6,7 +6,7 @@ Include dependency in build.gradle. ```gradle dependencies { - implementation "org.hisp.dhis:android-core:1.4.2" + implementation "org.hisp.dhis:android-core:1.4.3" ... } ``` diff --git a/docs/dhis2_android_sdk_developer_guide_INDEX.md b/docs/dhis2_android_sdk_developer_guide_INDEX.md index 326d8ea284..5979c97a52 100644 --- a/docs/dhis2_android_sdk_developer_guide_INDEX.md +++ b/docs/dhis2_android_sdk_developer_guide_INDEX.md @@ -3,11 +3,11 @@ title: 'DHIS 2 Android SDK Developer Guide' author: 'DHIS 2' date: year: 2021 -month: June +month: September keywords: [DHIS2, Android] commit: version: master -applicable_txt: 'Applicable to version 1.4.2' +applicable_txt: 'Applicable to version 1.4.3' --- From 5fc460f113edc6c093303f4b215bf37a3a1455cd Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 2 Sep 2021 17:40:50 +0200 Subject: [PATCH 304/308] fix: [ANDROSDK-1422] Send createdAtClient and lastUpdatedAtClient properties --- .../org/hisp/dhis/android/core/enrollment/Enrollment.java | 4 ++-- .../android/core/enrollment/NewTrackerImporterEnrollment.java | 4 ++-- .../src/main/java/org/hisp/dhis/android/core/event/Event.java | 4 ++-- .../hisp/dhis/android/core/event/NewTrackerImporterEvent.java | 4 ++-- .../core/trackedentity/NewTrackerImporterTrackedEntity.java | 4 ++-- .../android/core/trackedentity/TrackedEntityInstance.java | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java index b89f017fa0..96efcb00b4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/Enrollment.java @@ -84,12 +84,12 @@ public abstract class Enrollment extends BaseDeletableDataObject implements Obje public abstract Date lastUpdated(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date createdAtClient(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date lastUpdatedAtClient(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java index f67fb683ca..e8f75df247 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java @@ -79,12 +79,12 @@ public abstract class NewTrackerImporterEnrollment extends BaseDeletableDataObje public abstract Date updatedAt(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date createdAtClient(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date updatedAtClient(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java index 8206ad33e5..5abd76a7c6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java @@ -88,12 +88,12 @@ public abstract class Event extends BaseDeletableDataObject implements ObjectWit public abstract Date lastUpdated(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date createdAtClient(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date lastUpdatedAtClient(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java index 68888ff487..1b5f60f397 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java @@ -84,12 +84,12 @@ public abstract class NewTrackerImporterEvent extends BaseDeletableDataObject im public abstract Date updatedAt(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date createdAtClient(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date updatedAtClient(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java index 68859ed51a..27f58c233f 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java @@ -76,12 +76,12 @@ public abstract class NewTrackerImporterTrackedEntity extends BaseDeletableDataO public abstract Date updatedAt(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date createdAtClient(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date updatedAtClient(); diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java index a80b44ccca..67c14adda6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java @@ -80,12 +80,12 @@ public abstract class TrackedEntityInstance extends BaseDeletableDataObject impl public abstract Date lastUpdated(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date createdAtClient(); @Nullable - @JsonIgnore() + @JsonProperty() @ColumnAdapter(DbDateColumnAdapter.class) public abstract Date lastUpdatedAtClient(); From 5c3b3c433159d21bedc37e79d2fda86910b558f0 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Fri, 3 Sep 2021 07:25:42 +0200 Subject: [PATCH 305/308] [ANDROSDK-1422] Ktlint --- .../android/core/enrollment/NewTrackerImporterEnrollment.java | 1 - core/src/main/java/org/hisp/dhis/android/core/event/Event.java | 1 - .../hisp/dhis/android/core/event/NewTrackerImporterEvent.java | 1 - .../core/trackedentity/NewTrackerImporterTrackedEntity.java | 1 - .../dhis/android/core/trackedentity/TrackedEntityInstance.java | 1 - 5 files changed, 5 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java index e8f75df247..0425c6f8fe 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/NewTrackerImporterEnrollment.java @@ -32,7 +32,6 @@ import androidx.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java index 5abd76a7c6..022d5bfc98 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/Event.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/Event.java @@ -32,7 +32,6 @@ import androidx.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java index 1b5f60f397..f85b436203 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/NewTrackerImporterEvent.java @@ -32,7 +32,6 @@ import androidx.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java index 27f58c233f..0bb119a4a7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/NewTrackerImporterTrackedEntity.java @@ -32,7 +32,6 @@ import androidx.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java index 67c14adda6..a521a7ff31 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/TrackedEntityInstance.java @@ -32,7 +32,6 @@ import androidx.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; From e34dbb43eed44ae25bb58b51ab35a93a014115ea Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 7 Sep 2021 09:47:04 +0200 Subject: [PATCH 306/308] fix: [ANDROSDK-1425] Do not overwrite data if syncState is not valid --- .../core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt index 9bf523e715..94653dea1e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/handlers/internal/IdentifiableDataHandlerImpl.kt @@ -255,6 +255,7 @@ internal abstract class IdentifiableDataHandlerImpl( val syncedObjectUidsWhereClause2 = WhereClauseBuilder() .appendInKeyStringValues(IdentifiableColumns.UID, storedObjectUids) .appendInKeyStringValues(DataColumns.SYNC_STATE, states) + .appendInKeyStringValues(DataColumns.AGGREGATED_SYNC_STATE, states) .build() return store.selectUidsWhere(syncedObjectUidsWhereClause2) } From 9b037fb540966f063bbe324f143cd7e7c2f1d8aa Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 9 Sep 2021 12:39:27 +0200 Subject: [PATCH 307/308] fix: [ANDROSDK-1427] Add missing aggregation types --- ...ggregationType.java => AggregationType.kt} | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) rename core/src/main/java/org/hisp/dhis/android/core/common/{AggregationType.java => AggregationType.kt} (78%) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.java b/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt similarity index 78% rename from core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.java rename to core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt index 924764f62c..39f9c115b6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.java +++ b/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt @@ -25,10 +25,28 @@ * (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.common -package org.hisp.dhis.android.core.common; +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue -public enum AggregationType { - SUM, AVERAGE, AVERAGE_SUM_ORG_UNIT, LAST, LAST_AVERAGE_ORG_UNIT, COUNT, - STDDEV, VARIANCE, MIN, MAX, NONE, CUSTOM, DEFAULT +enum class AggregationType { + SUM, + AVERAGE, + AVERAGE_SUM_ORG_UNIT, + LAST, + LAST_AVERAGE_ORG_UNIT, + LAST_IN_PERIOD, + LAST_IN_PERIOD_AVERAGE_ORG_UNIT, + FIRST, + FIRST_AVERAGE_ORG_UNIT, + COUNT, + STDDEV, + VARIANCE, + MIN, + MAX, + NONE, + CUSTOM, + + @JsonEnumDefaultValue + DEFAULT } \ No newline at end of file From ed311e98036986a22d9d09132b803be942f655a3 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 9 Sep 2021 12:52:50 +0200 Subject: [PATCH 308/308] [ANDROSDK-1427] Ktlint --- .../java/org/hisp/dhis/android/core/common/AggregationType.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt b/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt index 39f9c115b6..ca7973c1f0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/common/AggregationType.kt @@ -49,4 +49,4 @@ enum class AggregationType { @JsonEnumDefaultValue DEFAULT -} \ No newline at end of file +}