use of org.odk.collect.android.dao.FormsDao in project collect by opendatakit.
the class NetworkReceiver method isFormAutoSendEnabled.
/**
* @param isFormAutoSendOptionEnabled represents whether the auto-send option is enabled at the app level
*
* If the form explicitly sets the auto-send property, then it overrides the preferences.
*/
private boolean isFormAutoSendEnabled(String jrFormId, boolean isFormAutoSendOptionEnabled) {
Cursor cursor = new FormsDao().getFormsCursorForFormId(jrFormId);
String autoSend = null;
if (cursor != null && cursor.moveToFirst()) {
try {
int autoSendColumnIndex = cursor.getColumnIndex(AUTO_SEND);
autoSend = cursor.getString(autoSendColumnIndex);
} finally {
cursor.close();
}
}
return autoSend == null ? isFormAutoSendOptionEnabled : Boolean.valueOf(autoSend);
}
use of org.odk.collect.android.dao.FormsDao in project collect by opendatakit.
the class DiskSyncTask method doInBackground.
@Override
protected String doInBackground(Void... params) {
formsDao = new FormsDao();
int instance = ++counter;
Timber.i("[%d] doInBackground begins!", instance);
List<String> idsToDelete = new ArrayList<>();
try {
// Process everything then report what didn't work.
StringBuilder errors = new StringBuilder();
File formDir = new File(Collect.FORMS_PATH);
if (formDir.exists() && formDir.isDirectory()) {
// Get all the files in the /odk/foms directory
List<File> formsToAdd = new LinkedList<File>();
// Step 1: assemble the candidate form files
// discard files beginning with "."
// discard files not ending with ".xml" or ".xhtml"
{
File[] formDefs = formDir.listFiles();
for (File addMe : formDefs) {
// Ignore invisible files that start with periods.
if (!addMe.getName().startsWith(".") && (addMe.getName().endsWith(".xml") || addMe.getName().endsWith(".xhtml"))) {
formsToAdd.add(addMe);
} else {
Timber.i("[%d] Ignoring: %s", instance, addMe.getAbsolutePath());
}
}
}
// Step 2: quickly run through and figure out what files we need to
// parse and update; this is quick, as we only calculate the md5
// and see if it has changed.
List<UriFile> uriToUpdate = new ArrayList<UriFile>();
Cursor cursor = null;
// open the cursor within a try-catch block so it can always be closed.
try {
cursor = formsDao.getFormsCursor();
if (cursor == null) {
Timber.e("[%d] Forms Content Provider returned NULL", instance);
errors.append("Internal Error: Unable to access Forms content provider\r\n");
return errors.toString();
}
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
// For each element in the provider, see if the file already exists
String sqlFilename = cursor.getString(cursor.getColumnIndex(FormsColumns.FORM_FILE_PATH));
String md5 = cursor.getString(cursor.getColumnIndex(FormsColumns.MD5_HASH));
File sqlFile = new File(sqlFilename);
if (sqlFile.exists()) {
// remove it from the list of forms (we only want forms
// we haven't added at the end)
formsToAdd.remove(sqlFile);
String md5Computed = FileUtils.getMd5Hash(sqlFile);
if (md5Computed == null || md5 == null || !md5Computed.equals(md5)) {
// Probably someone overwrite the file on the sdcard
// So re-parse it and update it's information
String id = cursor.getString(cursor.getColumnIndex(FormsColumns._ID));
Uri updateUri = Uri.withAppendedPath(FormsColumns.CONTENT_URI, id);
uriToUpdate.add(new UriFile(updateUri, sqlFile));
}
} else {
// File not found in sdcard but file path found in database
// probably because the file has been deleted or filename was changed in sdcard
// Add the ID to list so that they could be deleted all together
String id = cursor.getString(cursor.getColumnIndex(FormsColumns._ID));
idsToDelete.add(id);
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
if (!idsToDelete.isEmpty()) {
// Delete the forms not found in sdcard from the database
formsDao.deleteFormsFromIDs(idsToDelete.toArray(new String[idsToDelete.size()]));
}
// Step3: go through uriToUpdate to parse and update each in turn.
// This is slow because buildContentValues(...) is slow.
// Big win if multiple DiskSyncTasks running
Collections.shuffle(uriToUpdate);
for (UriFile entry : uriToUpdate) {
Uri updateUri = entry.uri;
File formDefFile = entry.file;
// Probably someone overwrite the file on the sdcard
// So re-parse it and update it's information
ContentValues values;
try {
values = buildContentValues(formDefFile);
} catch (IllegalArgumentException e) {
errors.append(e.getMessage()).append("\r\n");
File badFile = new File(formDefFile.getParentFile(), formDefFile.getName() + ".bad");
badFile.delete();
formDefFile.renameTo(badFile);
continue;
}
// update in content provider
int count = Collect.getInstance().getContentResolver().update(updateUri, values, null, null);
Timber.i("[%d] %d records successfully updated", instance, count);
}
uriToUpdate.clear();
// Step 4: go through the newly-discovered files in xFormsToAdd and add them.
// This is slow because buildContentValues(...) is slow.
//
// Big win if multiple DiskSyncTasks running
Collections.shuffle(formsToAdd);
while (!formsToAdd.isEmpty()) {
File formDefFile = formsToAdd.remove(0);
// Skip this file if that is the case.
if (isAlreadyDefined(formDefFile)) {
Timber.i("[%d] skipping -- definition already recorded: %s", instance, formDefFile.getAbsolutePath());
continue;
}
// Parse it for the first time...
ContentValues values;
try {
values = buildContentValues(formDefFile);
} catch (IllegalArgumentException e) {
errors.append(e.getMessage()).append("\r\n");
File badFile = new File(formDefFile.getParentFile(), formDefFile.getName() + ".bad");
badFile.delete();
formDefFile.renameTo(badFile);
continue;
}
// insert into content provider
try {
// insert failures are OK and expected if multiple
// DiskSync scanners are active.
formsDao.saveForm(values);
} catch (SQLException e) {
Timber.i("[%d] %s", instance, e.toString());
}
}
}
if (errors.length() != 0) {
statusMessage = errors.toString();
} else {
statusMessage = Collect.getInstance().getString(R.string.finished_disk_scan);
}
return statusMessage;
} finally {
Timber.i("[%d] doInBackground ends!", instance);
}
}
use of org.odk.collect.android.dao.FormsDao in project collect by opendatakit.
the class InstanceGoogleSheetsUploader method uploadInstances.
private Map<String, String> uploadInstances(String selection, String[] selectionArgs, int low, int instanceCount) {
final Map<String, String> messagesByInstanceId = new HashMap<>();
try (Cursor cursor = new InstancesDao().getInstancesCursor(selection, selectionArgs)) {
if (cursor.getCount() > 0) {
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
if (isCancelled()) {
return messagesByInstanceId;
}
final String id = cursor.getString(cursor.getColumnIndex(InstanceColumns._ID));
jrFormId = cursor.getString(cursor.getColumnIndex(InstanceColumns.JR_FORM_ID));
Uri toUpdate = Uri.withAppendedPath(InstanceColumns.CONTENT_URI, id);
ContentValues cv = new ContentValues();
Cursor formCursor = new FormsDao().getFormsCursorForFormId(jrFormId);
String md5 = null;
String formFilePath = null;
if (formCursor.getCount() > 0) {
formCursor.moveToFirst();
md5 = formCursor.getString(formCursor.getColumnIndex(FormsColumns.MD5_HASH));
formFilePath = formCursor.getString(formCursor.getColumnIndex(FormsColumns.FORM_FILE_PATH));
}
if (md5 == null) {
// fail and exit
Timber.e("no md5");
return messagesByInstanceId;
}
publishProgress(cursor.getPosition() + 1 + low, instanceCount);
String instance = cursor.getString(cursor.getColumnIndex(InstanceColumns.INSTANCE_FILE_PATH));
try {
uploadOneInstance(new File(instance), formFilePath, getGoogleSheetsUrl(cursor));
cv.put(InstanceColumns.STATUS, InstanceProviderAPI.STATUS_SUBMITTED);
Collect.getInstance().getContentResolver().update(toUpdate, cv, null, null);
messagesByInstanceId.put(id, Collect.getInstance().getString(R.string.success));
} catch (UploadException e) {
Timber.e(e);
messagesByInstanceId.put(id, e.getMessage() != null ? e.getMessage() : e.getCause().getMessage());
cv.put(InstanceColumns.STATUS, InstanceProviderAPI.STATUS_SUBMISSION_FAILED);
Collect.getInstance().getContentResolver().update(toUpdate, cv, null, null);
}
}
}
}
return messagesByInstanceId;
}
use of org.odk.collect.android.dao.FormsDao in project collect by opendatakit.
the class AndroidShortcuts method buildMenuList.
/**
* Builds a list of shortcuts
*/
private void buildMenuList() {
ArrayList<String> names = new ArrayList<String>();
ArrayList<Uri> commands = new ArrayList<Uri>();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.select_odk_shortcut);
Cursor c = null;
try {
c = new FormsDao().getFormsCursor();
if (c.getCount() > 0) {
c.moveToPosition(-1);
while (c.moveToNext()) {
String formName = c.getString(c.getColumnIndex(FormsColumns.DISPLAY_NAME));
names.add(formName);
Uri uri = Uri.withAppendedPath(FormsColumns.CONTENT_URI, c.getString(c.getColumnIndex(FormsColumns._ID)));
commands.add(uri);
}
}
} finally {
if (c != null) {
c.close();
}
}
this.names = names.toArray(new String[0]);
this.commands = commands.toArray(new Uri[0]);
builder.setItems(this.names, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
returnShortcut(AndroidShortcuts.this.names[item], AndroidShortcuts.this.commands[item]);
}
});
builder.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
AndroidShortcuts sc = AndroidShortcuts.this;
sc.setResult(RESULT_CANCELED);
sc.finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
use of org.odk.collect.android.dao.FormsDao in project collect by opendatakit.
the class FormEntryActivity method createLanguageDialog.
/**
* Creates and displays a dialog allowing the user to set the language for
* the form.
*/
private void createLanguageDialog() {
Collect.getInstance().getActivityLogger().logInstanceAction(this, "createLanguageDialog", "show");
FormController formController = getFormController();
final String[] languages = formController.getLanguages();
int selected = -1;
if (languages != null) {
String language = formController.getLanguage();
for (int i = 0; i < languages.length; i++) {
if (language.equals(languages[i])) {
selected = i;
}
}
}
alertDialog = new AlertDialog.Builder(this).setSingleChoiceItems(languages, selected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
// Update the language in the content provider
// when selecting a new
// language
ContentValues values = new ContentValues();
values.put(FormsColumns.LANGUAGE, languages[whichButton]);
String selection = FormsColumns.FORM_FILE_PATH + "=?";
String[] selectArgs = { formPath };
int updated = new FormsDao().updateForm(values, selection, selectArgs);
Timber.i("Updated language to: %s in %d rows", languages[whichButton], updated);
Collect.getInstance().getActivityLogger().logInstanceAction(this, "createLanguageDialog", "changeLanguage." + languages[whichButton]);
FormController formController = getFormController();
formController.setLanguage(languages[whichButton]);
dialog.dismiss();
if (formController.currentPromptIsQuestion()) {
saveAnswersForCurrentScreen(DO_NOT_EVALUATE_CONSTRAINTS);
}
refreshCurrentView();
}
}).setTitle(getString(R.string.change_language)).setNegativeButton(getString(R.string.do_not_change), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
Collect.getInstance().getActivityLogger().logInstanceAction(this, "createLanguageDialog", "cancel");
}
}).create();
alertDialog.show();
}
Aggregations