-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #144 from dhis2/download_teis
Download TrackedEntityInstances per Org.Unit
- Loading branch information
Showing
11 changed files
with
497 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
186 changes: 186 additions & 0 deletions
186
core/src/main/java/org/hisp/dhis/android/core/calls/TrackerEntitiesDataCall.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package org.hisp.dhis.android.core.calls; | ||
|
||
|
||
import android.support.annotation.NonNull; | ||
import android.util.Log; | ||
|
||
import org.hisp.dhis.android.core.common.Payload; | ||
import org.hisp.dhis.android.core.data.api.Fields; | ||
import org.hisp.dhis.android.core.data.database.DatabaseAdapter; | ||
import org.hisp.dhis.android.core.data.database.Transaction; | ||
import org.hisp.dhis.android.core.organisationunit.OrganisationUnit; | ||
import org.hisp.dhis.android.core.organisationunit.OrganisationUnitStore; | ||
import org.hisp.dhis.android.core.resource.ResourceHandler; | ||
import org.hisp.dhis.android.core.resource.ResourceStore; | ||
import org.hisp.dhis.android.core.systeminfo.SystemInfo; | ||
import org.hisp.dhis.android.core.systeminfo.SystemInfoCall; | ||
import org.hisp.dhis.android.core.systeminfo.SystemInfoService; | ||
import org.hisp.dhis.android.core.systeminfo.SystemInfoStore; | ||
import org.hisp.dhis.android.core.trackedentity.TeiQuery; | ||
import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstance; | ||
import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceEndPointCall; | ||
import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceHandler; | ||
import org.hisp.dhis.android.core.trackedentity.TrackedEntityInstanceService; | ||
|
||
import java.util.Date; | ||
import java.util.List; | ||
|
||
import retrofit2.Response; | ||
|
||
@SuppressWarnings("PMD") | ||
public class TrackerEntitiesDataCall implements Call<Response> { | ||
|
||
private boolean isExecuted; | ||
private final int teiLimitByOrgUnit; | ||
private final OrganisationUnitStore organisationUnitStore; | ||
private final TrackedEntityInstanceService trackedEntityInstanceService; | ||
private final DatabaseAdapter databaseAdapter; | ||
private final TrackedEntityInstanceHandler trackedEntityInstanceHandler; | ||
private final ResourceHandler resourceHandler; | ||
private final ResourceStore resourceStore; | ||
private final SystemInfoService systemInfoService; | ||
private final SystemInfoStore systemInfoStore; | ||
|
||
public TrackerEntitiesDataCall(@NonNull OrganisationUnitStore organisationUnitStore, | ||
@NonNull TrackedEntityInstanceService trackedEntityInstanceService, | ||
@NonNull DatabaseAdapter databaseAdapter, | ||
@NonNull TrackedEntityInstanceHandler trackedEntityInstanceHandler, | ||
@NonNull ResourceHandler resourceHandler, | ||
@NonNull ResourceStore resourceStore, | ||
@NonNull SystemInfoService systemInfoService, | ||
@NonNull SystemInfoStore systemInfoStore, | ||
int teiLimitByOrgUnit) { | ||
|
||
this.teiLimitByOrgUnit = teiLimitByOrgUnit; | ||
this.organisationUnitStore = organisationUnitStore; | ||
this.trackedEntityInstanceService = trackedEntityInstanceService; | ||
this.databaseAdapter = databaseAdapter; | ||
this.trackedEntityInstanceHandler = trackedEntityInstanceHandler; | ||
this.resourceHandler = resourceHandler; | ||
this.resourceStore = resourceStore; | ||
this.systemInfoService = systemInfoService; | ||
this.systemInfoStore = systemInfoStore; | ||
} | ||
|
||
@Override | ||
public boolean isExecuted() { | ||
synchronized (this) { | ||
return isExecuted; | ||
} | ||
} | ||
|
||
@Override | ||
public Response call() throws Exception { | ||
synchronized (this) { | ||
if (isExecuted) { | ||
throw new IllegalStateException("Already executed"); | ||
} | ||
isExecuted = true; | ||
} | ||
|
||
Response response = null; | ||
|
||
Transaction transaction = databaseAdapter.beginNewTransaction(); | ||
|
||
try { | ||
|
||
response = new SystemInfoCall( | ||
databaseAdapter, systemInfoStore, | ||
systemInfoService, resourceStore | ||
).call(); | ||
|
||
if (!response.isSuccessful()) { | ||
return response; | ||
} | ||
|
||
SystemInfo systemInfo = (SystemInfo) response.body(); | ||
Date serverDate = systemInfo.serverDate(); | ||
|
||
response = trackerCall(serverDate); | ||
|
||
if (response == null || !response.isSuccessful()) { | ||
return response; | ||
} | ||
|
||
transaction.setSuccessful(); | ||
|
||
return response; | ||
} finally { | ||
transaction.end(); | ||
} | ||
} | ||
|
||
//TODO We may need to refactor the code here. Right now it is not very optimize. | ||
// We need a better sync mechanism, based on? lastupdated? | ||
private Response trackerCall(Date serverDate) throws Exception { | ||
Response<Payload<TrackedEntityInstance>> response = null; | ||
|
||
List<OrganisationUnit> organisationUnits = organisationUnitStore.queryOrganisationUnits(); | ||
|
||
int pageSize = TeiQuery.Builder.create().build().getPageSize(); | ||
|
||
int numPages = (int) Math.ceil((double) teiLimitByOrgUnit / pageSize); | ||
|
||
int teisDownloaded = 0; | ||
|
||
int pageLimit = 0; | ||
|
||
for (OrganisationUnit orgUnit : organisationUnits) { | ||
|
||
for (int page = 1; page <= numPages; page++) { | ||
|
||
if (page == numPages && teiLimitByOrgUnit > 0) { | ||
pageLimit = teiLimitByOrgUnit - teisDownloaded; | ||
} | ||
|
||
TeiQuery teiQuery = TeiQuery. | ||
Builder.create() | ||
.withOrgUnit(orgUnit.uid()) | ||
.withPage(page) | ||
.withPageLimit(pageLimit) | ||
.build(); | ||
|
||
response = trackedEntityInstanceService.getTEIs(teiQuery.getOrgUnit(), fields(), | ||
Boolean.TRUE, teiQuery.getPage(), teiQuery.getPageLimit()).execute(); | ||
|
||
if (response.isSuccessful() && response.body().items() != null) { | ||
List<TrackedEntityInstance> trackedEntityInstances = response.body().items(); | ||
int size = trackedEntityInstances.size(); | ||
Response<TrackedEntityInstance> apiResponse = null; | ||
|
||
if (teiQuery.getPageLimit() > 0) { | ||
size = teiQuery.getPageLimit(); | ||
} | ||
|
||
for (int i = 0; i < size; i++) { | ||
apiResponse = new TrackedEntityInstanceEndPointCall(trackedEntityInstanceService, | ||
databaseAdapter, trackedEntityInstanceHandler, resourceHandler, serverDate, | ||
trackedEntityInstances.get(i).uid()).call(); | ||
|
||
if (apiResponse == null || !apiResponse.isSuccessful()) { | ||
Log.d(this.getClass().getSimpleName(), trackedEntityInstances.get(i).uid() + " conflict"); | ||
} | ||
} | ||
|
||
} | ||
|
||
teisDownloaded = teisDownloaded + teiQuery.getPageSize(); | ||
} | ||
|
||
} | ||
|
||
return response; | ||
} | ||
|
||
private Fields<TrackedEntityInstance> fields() { | ||
return Fields.<TrackedEntityInstance>builder().fields( | ||
TrackedEntityInstance.uid, TrackedEntityInstance.created, | ||
TrackedEntityInstance.lastUpdated, | ||
TrackedEntityInstance.organisationUnit, | ||
TrackedEntityInstance.trackedEntity, | ||
TrackedEntityInstance.deleted | ||
).build(); | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
core/src/main/java/org/hisp/dhis/android/core/trackedentity/TeiQuery.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package org.hisp.dhis.android.core.trackedentity; | ||
|
||
import android.support.annotation.Nullable; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
public class TeiQuery { | ||
|
||
private final int page; | ||
private final int pageSize; | ||
private final boolean paging; | ||
private final String orgUnit; | ||
private final int pageLimit; | ||
|
||
@Nullable | ||
private final Set<String> uIds; | ||
|
||
|
||
public TeiQuery(boolean paging, int page, int pageSize, | ||
String orgUnit, int pageLimit) { | ||
this.paging = paging; | ||
this.page = page; | ||
this.pageSize = pageSize; | ||
this.orgUnit = orgUnit; | ||
this.pageLimit = pageLimit; | ||
uIds = null; | ||
} | ||
|
||
public TeiQuery(boolean paging, int page, int pageSize, | ||
String orgUnit, @Nullable Set<String> uIds, int pageLimit) { | ||
this.paging = paging; | ||
this.page = page; | ||
this.pageSize = pageSize; | ||
this.orgUnit = orgUnit; | ||
this.uIds = uIds; | ||
this.pageLimit = pageLimit; | ||
} | ||
|
||
@Nullable | ||
public Set<String> getUIds() { | ||
return uIds; | ||
} | ||
|
||
public int getPage() { | ||
return page; | ||
} | ||
|
||
public int getPageSize() { | ||
return pageSize; | ||
} | ||
|
||
public boolean isPaging() { | ||
return paging; | ||
} | ||
|
||
public String getOrgUnit() { | ||
return orgUnit; | ||
} | ||
|
||
public int getPageLimit() { | ||
return pageLimit; | ||
} | ||
|
||
public static class Builder { | ||
private int page = 1; | ||
private int pageSize = 50; | ||
private boolean paging; | ||
private String orgUnit; | ||
int pageLimit; | ||
|
||
private Set<String> uIds = new HashSet<>(); | ||
|
||
private Builder() { | ||
} | ||
|
||
public static TeiQuery.Builder create() { | ||
return new TeiQuery.Builder(); | ||
} | ||
|
||
public TeiQuery.Builder withPaging(boolean paging) { | ||
this.paging = paging; | ||
return this; | ||
} | ||
|
||
public TeiQuery.Builder withPage(int page) { | ||
this.page = page; | ||
return this; | ||
} | ||
|
||
public TeiQuery.Builder withPageSize(int pageSize) { | ||
this.pageSize = pageSize; | ||
return this; | ||
} | ||
|
||
public TeiQuery.Builder withOrgUnit(String orgUnit) { | ||
this.orgUnit = orgUnit; | ||
return this; | ||
} | ||
|
||
public TeiQuery.Builder withUIds(Set<String> uIds) { | ||
this.uIds = uIds; | ||
return this; | ||
} | ||
|
||
public TeiQuery.Builder withPageLimit(int pageLimit) { | ||
this.pageLimit = pageLimit; | ||
return this; | ||
} | ||
|
||
public TeiQuery build() { | ||
if (pageLimit > pageSize) { | ||
throw new IllegalArgumentException( | ||
"pageLimit can not be more greater than pageSize"); | ||
} | ||
|
||
return new TeiQuery(paging, page, pageSize, | ||
orgUnit, uIds, pageLimit); | ||
} | ||
} | ||
} |
Oops, something went wrong.