Search in sources :

Example 1 with UploadException

use of org.odk.collect.android.upload.UploadException in project collect by opendatakit.

the class InstanceServerUploaderTask method doInBackground.

@Override
public Outcome doInBackground(Long... instanceIdsToUpload) {
    Outcome outcome = new Outcome();
    InstanceServerUploader uploader = new InstanceServerUploader(httpInterface, webCredentialsUtils, new HashMap<>(), settingsProvider.getUnprotectedSettings());
    List<Instance> instancesToUpload = uploader.getInstancesFromIds(instanceIdsToUpload);
    String deviceId = new PropertyManager().getSingularProperty(PropertyManager.PROPMGR_DEVICE_ID);
    for (int i = 0; i < instancesToUpload.size(); i++) {
        if (isCancelled()) {
            return outcome;
        }
        Instance instance = instancesToUpload.get(i);
        publishProgress(i + 1, instancesToUpload.size());
        try {
            String destinationUrl = uploader.getUrlToSubmitTo(instance, deviceId, completeDestinationUrl, null);
            String customMessage = uploader.uploadOneSubmission(instance, destinationUrl);
            outcome.messagesByInstanceId.put(instance.getDbId().toString(), customMessage != null ? customMessage : getLocalizedString(Collect.getInstance(), R.string.success));
            analytics.logEvent(SUBMISSION, "HTTP", Collect.getFormIdentifierHash(instance.getFormId(), instance.getFormVersion()));
        } catch (UploadAuthRequestedException e) {
            outcome.authRequestingServer = e.getAuthRequestingServer();
        // Don't add the instance that caused an auth request to the map because we want to
        // retry. Items present in the map are considered already attempted and won't be
        // retried.
        } catch (UploadException e) {
            outcome.messagesByInstanceId.put(instance.getDbId().toString(), e.getDisplayMessage());
        }
    }
    return outcome;
}
Also used : InstanceServerUploader(org.odk.collect.android.upload.InstanceServerUploader) Instance(org.odk.collect.forms.instances.Instance) PropertyManager(org.odk.collect.android.logic.PropertyManager) UploadException(org.odk.collect.android.upload.UploadException) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) UploadAuthRequestedException(org.odk.collect.android.upload.UploadAuthRequestedException)

Example 2 with UploadException

use of org.odk.collect.android.upload.UploadException in project collect by opendatakit.

the class InstanceSubmitter method submitInstances.

public Pair<Boolean, String> submitInstances(List<Instance> toUpload) throws SubmitException {
    if (toUpload.isEmpty()) {
        throw new SubmitException(Type.NOTHING_TO_SUBMIT);
    }
    String protocol = generalSettings.getString(ProjectKeys.KEY_PROTOCOL);
    InstanceUploader uploader;
    Map<String, String> resultMessagesByInstanceId = new HashMap<>();
    String deviceId = null;
    boolean anyFailure = false;
    if (protocol.equals(ProjectKeys.PROTOCOL_GOOGLE_SHEETS)) {
        if (permissionsProvider.isGetAccountsPermissionGranted()) {
            String googleUsername = googleAccountsManager.getLastSelectedAccountIfValid();
            if (googleUsername.isEmpty()) {
                throw new SubmitException(Type.GOOGLE_ACCOUNT_NOT_SET);
            }
            googleAccountsManager.selectAccount(googleUsername);
            uploader = new InstanceGoogleSheetsUploader(googleApiProvider.getDriveApi(googleUsername), googleApiProvider.getSheetsApi(googleUsername));
        } else {
            throw new SubmitException(Type.GOOGLE_ACCOUNT_NOT_PERMITTED);
        }
    } else {
        OpenRosaHttpInterface httpInterface = Collect.getInstance().getComponent().openRosaHttpInterface();
        uploader = new InstanceServerUploader(httpInterface, new WebCredentialsUtils(generalSettings), new HashMap<>(), generalSettings);
        deviceId = new PropertyManager().getSingularProperty(PropertyManager.PROPMGR_DEVICE_ID);
    }
    for (Instance instance : toUpload) {
        try {
            String destinationUrl;
            if (protocol.equals(ProjectKeys.PROTOCOL_GOOGLE_SHEETS)) {
                destinationUrl = uploader.getUrlToSubmitTo(instance, null, null, generalSettings.getString(KEY_GOOGLE_SHEETS_URL));
                if (!InstanceUploaderUtils.doesUrlRefersToGoogleSheetsFile(destinationUrl)) {
                    anyFailure = true;
                    resultMessagesByInstanceId.put(instance.getDbId().toString(), SPREADSHEET_UPLOADED_TO_GOOGLE_DRIVE);
                    continue;
                }
            } else {
                destinationUrl = uploader.getUrlToSubmitTo(instance, deviceId, null, null);
            }
            String customMessage = uploader.uploadOneSubmission(instance, destinationUrl);
            resultMessagesByInstanceId.put(instance.getDbId().toString(), customMessage != null ? customMessage : getLocalizedString(Collect.getInstance(), R.string.success));
            // communicated to the user. Maybe successful delete should also be communicated?
            if (InstanceUploaderUtils.shouldFormBeDeleted(formsRepository, instance.getFormId(), instance.getFormVersion(), generalSettings.getBoolean(ProjectKeys.KEY_DELETE_AFTER_SEND))) {
                new InstanceDeleter(new InstancesRepositoryProvider(Collect.getInstance()).get(), new FormsRepositoryProvider(Collect.getInstance()).get()).delete(instance.getDbId());
            }
            String action = protocol.equals(ProjectKeys.PROTOCOL_GOOGLE_SHEETS) ? "HTTP-Sheets auto" : "HTTP auto";
            String label = Collect.getFormIdentifierHash(instance.getFormId(), instance.getFormVersion());
            analytics.logEvent(SUBMISSION, action, label);
        } catch (UploadException e) {
            Timber.d(e);
            anyFailure = true;
            resultMessagesByInstanceId.put(instance.getDbId().toString(), e.getDisplayMessage());
        }
    }
    return new Pair<>(anyFailure, InstanceUploaderUtils.getUploadResultMessage(instancesRepository, Collect.getInstance(), resultMessagesByInstanceId));
}
Also used : InstanceServerUploader(org.odk.collect.android.upload.InstanceServerUploader) InstancesRepositoryProvider(org.odk.collect.android.utilities.InstancesRepositoryProvider) HashMap(java.util.HashMap) Instance(org.odk.collect.forms.instances.Instance) PropertyManager(org.odk.collect.android.logic.PropertyManager) UploadException(org.odk.collect.android.upload.UploadException) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) FormsRepositoryProvider(org.odk.collect.android.utilities.FormsRepositoryProvider) InstanceUploader(org.odk.collect.android.upload.InstanceUploader) OpenRosaHttpInterface(org.odk.collect.android.openrosa.OpenRosaHttpInterface) InstanceGoogleSheetsUploader(org.odk.collect.android.gdrive.InstanceGoogleSheetsUploader) WebCredentialsUtils(org.odk.collect.android.utilities.WebCredentialsUtils) Pair(android.util.Pair)

Example 3 with UploadException

use of org.odk.collect.android.upload.UploadException in project collect by opendatakit.

the class InstanceGoogleSheetsUploader method getInstanceElement.

private TreeElement getInstanceElement(String formFilePath, File instanceFile) throws UploadException {
    FormDef formDef;
    File formXml = new File(formFilePath);
    String lastSavedSrc = FileUtils.getOrCreateLastSavedSrc(formXml);
    try {
        formDef = XFormUtils.getFormFromFormXml(formFilePath, lastSavedSrc);
        FormLoaderTask.importData(instanceFile, new FormEntryController(new FormEntryModel(formDef)));
    } catch (IOException | RuntimeException e) {
        throw new UploadException(e);
    }
    return formDef.getMainInstance().getRoot();
}
Also used : FormEntryController(org.javarosa.form.api.FormEntryController) FormEntryModel(org.javarosa.form.api.FormEntryModel) FormDef(org.javarosa.core.model.FormDef) UploadException(org.odk.collect.android.upload.UploadException) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) IOException(java.io.IOException) File(java.io.File)

Example 4 with UploadException

use of org.odk.collect.android.upload.UploadException in project collect by opendatakit.

the class InstanceGoogleSheetsUploader method uploadOneSubmission.

@Override
public String uploadOneSubmission(Instance instance, String spreadsheetUrl) throws UploadException {
    File instanceFile = new File(instance.getInstanceFilePath());
    if (!instanceFile.exists()) {
        throw new UploadException(FAIL + "instance XML file does not exist!");
    }
    // Get corresponding blank form and verify there is exactly 1
    List<Form> forms = new FormsRepositoryProvider(Collect.getInstance()).get().getAllByFormIdAndVersion(instance.getFormId(), instance.getFormVersion());
    try {
        if (forms.size() != 1) {
            throw new UploadException(getLocalizedString(Collect.getInstance(), R.string.not_exactly_one_blank_form_for_this_form_id));
        }
        Form form = forms.get(0);
        if (form.getBASE64RSAPublicKey() != null) {
            submissionComplete(instance, false);
            throw new UploadException(getLocalizedString(Collect.getInstance(), R.string.google_sheets_encrypted_message));
        }
        String formFilePath = PathUtils.getAbsoluteFilePath(new StoragePathProvider().getOdkDirPath(StorageSubdirectory.FORMS), form.getFormFilePath());
        TreeElement instanceElement = getInstanceElement(formFilePath, instanceFile);
        setUpSpreadsheet(spreadsheetUrl);
        sheetsHelper.updateSpreadsheetLocaleForNewSpreadsheet(spreadsheet.getSpreadsheetId(), spreadsheet.getSheets().get(0).getProperties().getTitle());
        if (hasRepeatableGroups(instanceElement)) {
            createSheetsIfNeeded(instanceElement);
        }
        String key = getInstanceID(getChildElements(instanceElement, false));
        if (key == null) {
            key = PropertyUtils.genUUID();
        }
        insertRows(instance, instanceElement, null, key, instanceFile, spreadsheet.getSheets().get(0).getProperties().getTitle());
    } catch (UploadException e) {
        submissionComplete(instance, false);
        throw e;
    } catch (GoogleJsonResponseException e) {
        submissionComplete(instance, false);
        throw new UploadException(getErrorMessageFromGoogleJsonResponseException(e));
    }
    submissionComplete(instance, true);
    // Google Sheets can't provide a custom success message
    return null;
}
Also used : GoogleJsonResponseException(com.google.api.client.googleapis.json.GoogleJsonResponseException) StoragePathProvider(org.odk.collect.android.storage.StoragePathProvider) Form(org.odk.collect.forms.Form) UploadException(org.odk.collect.android.upload.UploadException) FormsRepositoryProvider(org.odk.collect.android.utilities.FormsRepositoryProvider) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) File(java.io.File) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement)

Example 5 with UploadException

use of org.odk.collect.android.upload.UploadException in project collect by opendatakit.

the class InstanceGoogleSheetsUploader method insertRow.

private void insertRow(Instance instance, TreeElement element, String parentKey, String key, File instanceFile, String sheetTitle) throws UploadException {
    try {
        List<List<Object>> sheetCells = getSheetCells(sheetTitle);
        boolean newSheet = sheetCells == null || sheetCells.isEmpty();
        List<Object> columnTitles = getColumnTitles(element, newSheet);
        ensureNumberOfColumnsIsValid(columnTitles.size());
        if (!newSheet) {
            // we are editing an existed sheet
            if (isAnyColumnHeaderEmpty(sheetCells.get(0))) {
                // Insert a header row again to fill empty headers
                sheetsHelper.updateRow(spreadsheet.getSpreadsheetId(), sheetTitle + "!A1", new ValueRange().setValues(Collections.singletonList(columnTitles)));
                // read sheet cells again to update
                sheetCells = getSheetCells(sheetTitle);
            }
            disallowMissingColumns(sheetCells.get(0), columnTitles);
            addAltitudeAndAccuracyTitles(sheetCells.get(0), columnTitles);
            // Call again to ensure valid number of columns
            ensureNumberOfColumnsIsValid(columnTitles.size());
        } else {
            // new sheet
            Integer sheetId = getSheetId(sheetTitle);
            if (sheetId != null) {
                sheetsHelper.resizeSpreadSheet(spreadsheet.getSpreadsheetId(), sheetId, columnTitles.size());
            }
            sheetsHelper.insertRow(spreadsheet.getSpreadsheetId(), sheetTitle, new ValueRange().setValues(Collections.singletonList(columnTitles)));
            // read sheet cells again to update
            sheetCells = getSheetCells(sheetTitle);
        }
        HashMap<String, String> answers = getAnswers(instance, element, columnTitles, instanceFile, parentKey, key);
        if (shouldRowBeInserted(answers)) {
            sheetsHelper.insertRow(spreadsheet.getSpreadsheetId(), sheetTitle, new ValueRange().setValues(Collections.singletonList(prepareListOfValues(sheetCells.get(0), columnTitles, answers))));
        }
    } catch (GoogleJsonResponseException e) {
        throw new UploadException(getErrorMessageFromGoogleJsonResponseException(e));
    } catch (IOException e) {
        throw new UploadException(e);
    }
}
Also used : ValueRange(com.google.api.services.sheets.v4.model.ValueRange) GoogleJsonResponseException(com.google.api.client.googleapis.json.GoogleJsonResponseException) UploadException(org.odk.collect.android.upload.UploadException) ArrayList(java.util.ArrayList) List(java.util.List) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) IOException(java.io.IOException)

Aggregations

UploadException (org.odk.collect.android.upload.UploadException)8 LocalizedApplicationKt.getLocalizedString (org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString)7 IOException (java.io.IOException)4 GoogleJsonResponseException (com.google.api.client.googleapis.json.GoogleJsonResponseException)3 File (java.io.File)3 FormsRepositoryProvider (org.odk.collect.android.utilities.FormsRepositoryProvider)3 Instance (org.odk.collect.forms.instances.Instance)3 PropertyManager (org.odk.collect.android.logic.PropertyManager)2 InstanceServerUploader (org.odk.collect.android.upload.InstanceServerUploader)2 Form (org.odk.collect.forms.Form)2 Pair (android.util.Pair)1 ValueRange (com.google.api.services.sheets.v4.model.ValueRange)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 List (java.util.List)1 FormDef (org.javarosa.core.model.FormDef)1 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)1 TreeElement (org.javarosa.core.model.instance.TreeElement)1 FormEntryController (org.javarosa.form.api.FormEntryController)1 FormEntryModel (org.javarosa.form.api.FormEntryModel)1