Search in sources :

Example 1 with DHIS2SyncError

use of net.geoprism.registry.dhis2.DHIS2FeatureService.DHIS2SyncError in project geoprism-registry by terraframe.

the class DHIS2SynchronizationManager method synchronize.

public void synchronize() {
    this.init();
    final ExternalSystem es = dhis2Config.getSystem();
    long rowIndex = 0;
    long total = 0;
    long exportCount = 0;
    SortedSet<DHIS2SyncLevel> levels = dhis2Config.getLevels();
    Boolean includeTranslations = LocalizationFacade.getInstalledLocales().size() > 0;
    // First calculate the total number of records
    HashMap<Integer, Long> countAtLevel = new HashMap<Integer, Long>();
    int expectedLevel = 0;
    for (DHIS2SyncLevel level : levels) {
        if (level.getLevel() != expectedLevel) {
            throw new ProgrammingErrorException("Unexpected level number [" + level.getLevel() + "].");
        }
        if (level.getSyncType() != null && !DHIS2SyncLevel.Type.NONE.equals(level.getSyncType())) {
            long count = this.getCount(level.getGeoObjectType());
            total += count;
            countAtLevel.put(level.getLevel(), count);
        }
        expectedLevel++;
    }
    history.appLock();
    history.setWorkTotal(total);
    history.apply();
    // Now do the work
    for (DHIS2SyncLevel level : levels) {
        if (level.getSyncType() != null && !DHIS2SyncLevel.Type.NONE.equals(level.getSyncType())) {
            long skip = 0;
            long pageSize = 1000;
            long count = countAtLevel.get(level.getLevel());
            while (skip < count) {
                List<VertexServerGeoObject> objects = this.query(level.getGeoObjectType(), skip, pageSize);
                for (VertexServerGeoObject go : objects) {
                    try {
                        this.exportGeoObject(dhis2Config, level, levels, rowIndex, go, includeTranslations);
                        exportCount++;
                        history.appLock();
                        history.setWorkProgress(rowIndex);
                        history.setExportedRecords(exportCount);
                        history.apply();
                        if (level.getOrgUnitGroupId() != null && level.getOrgUnitGroupId().length() > 0) {
                            final String externalId = go.getExternalId(es);
                            level.getOrCreateOrgUnitGroupIdSet(level.getOrgUnitGroupId()).add(externalId);
                        }
                    } catch (DHIS2SyncError ee) {
                        recordExportError(ee, history);
                    }
                    rowIndex++;
                }
                ;
                // Export OrgUnitGroup changes
                if (level.getOrgUnitGroupIdSet().size() > 0) {
                    try {
                        Map<String, Set<String>> orgUnitGroupIdSet = level.getOrgUnitGroupIdSet();
                        // Fetch and populate all the org unit groups with the ids of org units that we will be exporting
                        MetadataGetResponse<OrganisationUnitGroup> resp = dhis2.metadataGet(OrganisationUnitGroup.class);
                        this.service.validateDhis2Response(resp);
                        List<OrganisationUnitGroup> orgUnitGroups = resp.getObjects();
                        if (orgUnitGroups != null) {
                            Iterator<? extends OrganisationUnitGroup> it = orgUnitGroups.iterator();
                            while (it.hasNext()) {
                                OrganisationUnitGroup group = it.next();
                                if (orgUnitGroupIdSet.containsKey(group.getId())) {
                                    orgUnitGroupIdSet.get(group.getId()).addAll(group.getOrgUnitIds());
                                    group.setOrgUnitIds(orgUnitGroupIdSet.get(group.getId()));
                                    orgUnitGroupIdSet.remove(group.getId());
                                } else {
                                    it.remove();
                                }
                            }
                            if (orgUnitGroups.size() > 0) {
                                JsonObject payload = new JsonObject();
                                JsonArray jaOrgUnitGroups = new JsonArray();
                                for (OrganisationUnitGroup group : orgUnitGroups) {
                                    GsonBuilder builder = new GsonBuilder();
                                    JsonObject joOrgUnitGroup = builder.create().toJsonTree(group, group.getClass()).getAsJsonObject();
                                    joOrgUnitGroup.remove("created");
                                    joOrgUnitGroup.remove("lastUpdated");
                                    joOrgUnitGroup.remove("symbol");
                                    joOrgUnitGroup.remove("publicAccess");
                                    joOrgUnitGroup.remove("user");
                                    joOrgUnitGroup.remove("userGroupAccesses");
                                    joOrgUnitGroup.remove("attributeValues");
                                    joOrgUnitGroup.remove("translations");
                                    joOrgUnitGroup.remove("userAccesses");
                                    jaOrgUnitGroups.add(joOrgUnitGroup);
                                }
                                payload.add(DHIS2Objects.ORGANISATION_UNIT_GROUPS, jaOrgUnitGroups);
                                List<NameValuePair> params = new ArrayList<NameValuePair>();
                                MetadataImportResponse resp2 = dhis2.metadataPost(params, new StringEntity(payload.toString(), Charset.forName("UTF-8")));
                                this.service.validateDhis2Response(resp2);
                            }
                        }
                    } catch (InvalidLoginException e) {
                        LoginException cgrlogin = new LoginException(e);
                        throw cgrlogin;
                    } catch (HTTPException | BadServerUriException e) {
                        HttpError cgrhttp = new HttpError(e);
                        throw cgrhttp;
                    }
                }
                skip += pageSize;
                NotificationFacade.queue(new GlobalNotificationMessage(MessageType.DATA_EXPORT_JOB_CHANGE, null));
            }
        }
    }
    history.appLock();
    history.setWorkProgress(rowIndex);
    history.setExportedRecords(exportCount);
    history.clearStage();
    history.addStage(ExportStage.COMPLETE);
    history.apply();
    NotificationFacade.queue(new GlobalNotificationMessage(MessageType.DATA_EXPORT_JOB_CHANGE, null));
    handleExportErrors();
}
Also used : SortedSet(java.util.SortedSet) Set(java.util.Set) HTTPException(net.geoprism.dhis2.dhis2adapter.exception.HTTPException) HashMap(java.util.HashMap) ExternalSystem(net.geoprism.registry.graph.ExternalSystem) DHIS2SyncLevel(net.geoprism.registry.etl.DHIS2SyncLevel) ArrayList(java.util.ArrayList) MetadataImportResponse(net.geoprism.dhis2.dhis2adapter.response.MetadataImportResponse) JsonObject(com.google.gson.JsonObject) StringEntity(org.apache.http.entity.StringEntity) NameValuePair(org.apache.http.NameValuePair) BasicNameValuePair(org.apache.http.message.BasicNameValuePair) GsonBuilder(com.google.gson.GsonBuilder) BadServerUriException(net.geoprism.dhis2.dhis2adapter.exception.BadServerUriException) ProgrammingErrorException(com.runwaysdk.dataaccess.ProgrammingErrorException) DHIS2SyncError(net.geoprism.registry.dhis2.DHIS2FeatureService.DHIS2SyncError) OrganisationUnitGroup(net.geoprism.dhis2.dhis2adapter.response.model.OrganisationUnitGroup) JsonArray(com.google.gson.JsonArray) InvalidLoginException(net.geoprism.dhis2.dhis2adapter.exception.InvalidLoginException) LoginException(net.geoprism.registry.etl.export.LoginException) InvalidLoginException(net.geoprism.dhis2.dhis2adapter.exception.InvalidLoginException) VertexServerGeoObject(net.geoprism.registry.model.graph.VertexServerGeoObject) HttpError(net.geoprism.registry.etl.export.HttpError) GlobalNotificationMessage(net.geoprism.registry.ws.GlobalNotificationMessage)

Example 2 with DHIS2SyncError

use of net.geoprism.registry.dhis2.DHIS2FeatureService.DHIS2SyncError in project geoprism-registry by terraframe.

the class DHIS2SynchronizationManager method exportGeoObject.

/**
 * It's important that we try our best to maintain an accurate state between
 * our database and the DHIS2 database. The DHIS2Serailizer will create new
 * ids and save them as externalIds for GeoObjects that do not have
 * externalIds. If our push to DHIS2 for this new GeoObject fails for whatever
 * reason, then we want to rollback our database so that we do not store the
 * id which does not exist in the DHIS2 database.
 *
 * TODO : In the future perhaps we should directly ask DHIS2 if an object
 * exists and then we'll know
 *
 * @param level
 * @param go
 * @return
 * @throws ExportError
 */
@Transaction
private void exportGeoObject(DHIS2SyncConfig dhis2Config, DHIS2SyncLevel level, SortedSet<DHIS2SyncLevel> levels, Long rowIndex, VertexServerGeoObject serverGo, Boolean includeTranslations) throws DHIS2SyncError {
    DHIS2ImportResponse resp = null;
    JsonObject orgUnitJsonTree = null;
    String orgUnitJson = null;
    String externalId = null;
    try {
        externalId = serverGo.getExternalId(dhis2Config.getSystem());
        boolean isNew = (externalId == null);
        if (isNew && level.getSyncType() != DHIS2SyncLevel.Type.ALL) {
            NewGeoObjectInvalidSyncTypeError err = new NewGeoObjectInvalidSyncTypeError();
            err.setGeoObject(serverGo.getDisplayLabel().getValue());
            throw err;
        }
        if (isNew && level.getLevel() == 0 && this.ouLevel1.size() > 0) {
            throw new MultipleLevelOneOrgUnitException();
        }
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(VertexServerGeoObject.class, new DHIS2GeoObjectJsonAdapters.DHIS2Serializer(dhis2, dhis2Config, level, this.date));
        orgUnitJsonTree = builder.create().toJsonTree(serverGo, serverGo.getClass()).getAsJsonObject();
        orgUnitJson = orgUnitJsonTree.toString();
        externalId = serverGo.getExternalId(dhis2Config.getSystem());
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("mergeMode", "MERGE"));
        try {
            JsonObject metadataPayload = new JsonObject();
            JsonArray orgUnits = new JsonArray();
            metadataPayload.add("organisationUnits", orgUnits);
            if (level.getSyncType() == DHIS2SyncLevel.Type.ALL) {
                orgUnits.add(orgUnitJsonTree);
            } else if (level.getSyncType() == DHIS2SyncLevel.Type.RELATIONSHIPS) {
                if (!orgUnitJsonTree.has("parent")) {
                    // Root level types do not have parents.
                    return;
                }
                JsonObject orgUnitRelationships = new JsonObject();
                // These attributes must be included at the requirement of DHIS2 API
                orgUnitRelationships.addProperty("id", orgUnitJsonTree.get("id").getAsString());
                orgUnitRelationships.addProperty("name", orgUnitJsonTree.get("name").getAsString());
                orgUnitRelationships.addProperty("shortName", orgUnitJsonTree.get("shortName").getAsString());
                orgUnitRelationships.addProperty("openingDate", orgUnitJsonTree.get("openingDate").getAsString());
                // We don't want to actually update any of these attributes, so if we can fetch the object from DHIS2
                // then use the values they have in their server instead.
                DHIS2Response orgUnitGetResp = dhis2.entityIdGet(DHIS2Objects.ORGANISATION_UNITS, externalId, params);
                if (orgUnitGetResp.isSuccess()) {
                    JsonObject jo = JsonParser.parseString(orgUnitGetResp.getResponse()).getAsJsonObject();
                    orgUnitRelationships.addProperty("name", jo.get("name").getAsString());
                    orgUnitRelationships.addProperty("shortName", jo.get("shortName").getAsString());
                    orgUnitRelationships.addProperty("openingDate", jo.get("openingDate").getAsString());
                }
                // These attributes are the ones we need to include to change the relationship
                orgUnitRelationships.add("parent", orgUnitJsonTree.get("parent").getAsJsonObject());
                orgUnitRelationships.addProperty("path", orgUnitJsonTree.get("path").getAsString());
                orgUnitRelationships.addProperty("level", orgUnitJsonTree.get("level").getAsInt());
                orgUnits.add(orgUnitRelationships);
            } else if (level.getSyncType() == DHIS2SyncLevel.Type.ORG_UNITS) {
                JsonObject orgUnitAttributes = orgUnitJsonTree.deepCopy();
                // Drop all attributes related to the parent / hierarchy
                orgUnitAttributes.remove("parent");
                orgUnitAttributes.remove("path");
                orgUnitAttributes.remove("level");
                orgUnits.add(orgUnitAttributes);
            }
            ImportStrategy strategy = isNew ? ImportStrategy.CREATE : ImportStrategy.UPDATE;
            params.add(new BasicNameValuePair("importStrategy", strategy.name()));
            resp = dhis2.metadataPost(params, new StringEntity(metadataPayload.toString(), Charset.forName("UTF-8")));
        } catch (InvalidLoginException e) {
            LoginException cgrlogin = new LoginException(e);
            throw cgrlogin;
        } catch (HTTPException e) {
            HttpError cgrhttp = new HttpError(e);
            throw cgrhttp;
        }
        this.service.validateDhis2Response(resp);
        if (isNew && level.getLevel() == 1 && this.ouLevel1.size() > 0) {
            this.ouLevel1.add(new OrganisationUnit());
        }
    } catch (Throwable t) {
        DHIS2SyncError er = new DHIS2SyncError(rowIndex, resp, orgUnitJson, t, serverGo.getCode());
        throw er;
    }
}
Also used : MultipleLevelOneOrgUnitException(net.geoprism.registry.etl.export.dhis2.MultipleLevelOneOrgUnitException) DHIS2GeoObjectJsonAdapters(net.geoprism.registry.etl.export.dhis2.DHIS2GeoObjectJsonAdapters) NameValuePair(org.apache.http.NameValuePair) BasicNameValuePair(org.apache.http.message.BasicNameValuePair) OrganisationUnit(net.geoprism.dhis2.dhis2adapter.response.model.OrganisationUnit) HTTPException(net.geoprism.dhis2.dhis2adapter.exception.HTTPException) GsonBuilder(com.google.gson.GsonBuilder) ArrayList(java.util.ArrayList) JsonObject(com.google.gson.JsonObject) DHIS2SyncError(net.geoprism.registry.dhis2.DHIS2FeatureService.DHIS2SyncError) JsonArray(com.google.gson.JsonArray) StringEntity(org.apache.http.entity.StringEntity) ImportStrategy(net.geoprism.dhis2.dhis2adapter.response.model.ImportStrategy) NewGeoObjectInvalidSyncTypeError(net.geoprism.registry.etl.NewGeoObjectInvalidSyncTypeError) BasicNameValuePair(org.apache.http.message.BasicNameValuePair) InvalidLoginException(net.geoprism.dhis2.dhis2adapter.exception.InvalidLoginException) LoginException(net.geoprism.registry.etl.export.LoginException) InvalidLoginException(net.geoprism.dhis2.dhis2adapter.exception.InvalidLoginException) DHIS2ImportResponse(net.geoprism.dhis2.dhis2adapter.response.DHIS2ImportResponse) HttpError(net.geoprism.registry.etl.export.HttpError) DHIS2Response(net.geoprism.dhis2.dhis2adapter.response.DHIS2Response) Transaction(com.runwaysdk.dataaccess.transaction.Transaction)

Aggregations

GsonBuilder (com.google.gson.GsonBuilder)2 JsonArray (com.google.gson.JsonArray)2 JsonObject (com.google.gson.JsonObject)2 ArrayList (java.util.ArrayList)2 HTTPException (net.geoprism.dhis2.dhis2adapter.exception.HTTPException)2 InvalidLoginException (net.geoprism.dhis2.dhis2adapter.exception.InvalidLoginException)2 DHIS2SyncError (net.geoprism.registry.dhis2.DHIS2FeatureService.DHIS2SyncError)2 HttpError (net.geoprism.registry.etl.export.HttpError)2 LoginException (net.geoprism.registry.etl.export.LoginException)2 NameValuePair (org.apache.http.NameValuePair)2 StringEntity (org.apache.http.entity.StringEntity)2 BasicNameValuePair (org.apache.http.message.BasicNameValuePair)2 ProgrammingErrorException (com.runwaysdk.dataaccess.ProgrammingErrorException)1 Transaction (com.runwaysdk.dataaccess.transaction.Transaction)1 HashMap (java.util.HashMap)1 Set (java.util.Set)1 SortedSet (java.util.SortedSet)1 BadServerUriException (net.geoprism.dhis2.dhis2adapter.exception.BadServerUriException)1 DHIS2ImportResponse (net.geoprism.dhis2.dhis2adapter.response.DHIS2ImportResponse)1 DHIS2Response (net.geoprism.dhis2.dhis2adapter.response.DHIS2Response)1