Search in sources :

Example 1 with FormsDao

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);
}
Also used : FormsDao(org.odk.collect.android.dao.FormsDao) Cursor(android.database.Cursor)

Example 2 with FormsDao

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);
    }
}
Also used : FormsDao(org.odk.collect.android.dao.FormsDao) ContentValues(android.content.ContentValues) SQLException(android.database.SQLException) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) Uri(android.net.Uri) LinkedList(java.util.LinkedList) File(java.io.File)

Example 3 with FormsDao

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;
}
Also used : ContentValues(android.content.ContentValues) FormsDao(org.odk.collect.android.dao.FormsDao) InstancesDao(org.odk.collect.android.dao.InstancesDao) HashMap(java.util.HashMap) Cursor(android.database.Cursor) Uri(android.net.Uri) File(java.io.File)

Example 4 with FormsDao

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();
}
Also used : AlertDialog(android.app.AlertDialog) FormsDao(org.odk.collect.android.dao.FormsDao) DialogInterface(android.content.DialogInterface) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) Uri(android.net.Uri) OnCancelListener(android.content.DialogInterface.OnCancelListener)

Example 5 with FormsDao

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();
}
Also used : FormController(org.odk.collect.android.logic.FormController) AlertDialog(android.support.v7.app.AlertDialog) ContentValues(android.content.ContentValues) FormsDao(org.odk.collect.android.dao.FormsDao) DialogInterface(android.content.DialogInterface) FailedConstraint(org.odk.collect.android.logic.FormController.FailedConstraint)

Aggregations

FormsDao (org.odk.collect.android.dao.FormsDao)12 Cursor (android.database.Cursor)9 ContentValues (android.content.ContentValues)3 Uri (android.net.Uri)3 File (java.io.File)3 DialogInterface (android.content.DialogInterface)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 AlertDialog (android.app.AlertDialog)1 ContentResolver (android.content.ContentResolver)1 OnCancelListener (android.content.DialogInterface.OnCancelListener)1 SQLException (android.database.SQLException)1 AlertDialog (android.support.v7.app.AlertDialog)1 View (android.view.View)1 ImageView (android.widget.ImageView)1 TextView (android.widget.TextView)1 KeyFactory (java.security.KeyFactory)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 NoSuchProviderException (java.security.NoSuchProviderException)1 PublicKey (java.security.PublicKey)1