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;
}
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));
}
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();
}
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;
}
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);
}
}
Aggregations