Search in sources :

Example 36 with FormController

use of org.odk.collect.android.logic.FormController in project collect by opendatakit.

the class SaveToDiskTask method exportData.

/**
 * Write's the data to the sdcard, and updates the instances content provider.
 * In theory we don't have to write to disk, and this is where you'd add
 * other methods.
 */
private void exportData(boolean markCompleted) throws IOException, EncryptionException {
    FormController formController = Collect.getInstance().getFormController();
    publishProgress(Collect.getInstance().getString(R.string.survey_saving_collecting_message));
    ByteArrayPayload payload = formController.getFilledInFormXml();
    // write out xml
    String instancePath = formController.getInstanceFile().getAbsolutePath();
    publishProgress(Collect.getInstance().getString(R.string.survey_saving_saving_message));
    exportXmlFile(payload, instancePath);
    // update the uri. We have exported the reloadable instance, so update status...
    // Since we saved a reloadable instance, it is flagged as re-openable so that if any error
    // occurs during the packaging of the data for the server fails (e.g., encryption),
    // we can still reopen the filled-out form and re-save it at a later time.
    updateInstanceDatabase(true, true);
    if (markCompleted) {
        // now see if the packaging of the data for the server would make it
        // non-reopenable (e.g., encryption or send an SMS or other fraction of the form).
        boolean canEditAfterCompleted = formController.isSubmissionEntireForm();
        boolean isEncrypted = false;
        // build a submission.xml to hold the data being submitted
        // and (if appropriate) encrypt the files on the side
        // pay attention to the ref attribute of the submission profile...
        File instanceXml = formController.getInstanceFile();
        File submissionXml = new File(instanceXml.getParentFile(), "submission.xml");
        payload = formController.getSubmissionXml();
        // write out submission.xml -- the data to actually submit to aggregate
        publishProgress(Collect.getInstance().getString(R.string.survey_saving_finalizing_message));
        exportXmlFile(payload, submissionXml.getAbsolutePath());
        // see if the form is encrypted and we can encrypt it...
        EncryptedFormInformation formInfo = EncryptionUtils.getEncryptedFormInformation(uri, formController.getSubmissionMetadata());
        if (formInfo != null) {
            // if we are encrypting, the form cannot be reopened afterward
            canEditAfterCompleted = false;
            // and encrypt the submission (this is a one-way operation)...
            publishProgress(Collect.getInstance().getString(R.string.survey_saving_encrypting_message));
            EncryptionUtils.generateEncryptedSubmission(instanceXml, submissionXml, formInfo);
            isEncrypted = true;
        }
        // At this point, we have:
        // 1. the saved original instanceXml,
        // 2. all the plaintext attachments
        // 2. the submission.xml that is the completed xml (whether encrypting or not)
        // 3. all the encrypted attachments if encrypting (isEncrypted = true).
        // 
        // NEXT:
        // 1. Update the instance database (with status complete).
        // 2. Overwrite the instanceXml with the submission.xml
        // and remove the plaintext attachments if encrypting
        updateInstanceDatabase(false, canEditAfterCompleted);
        if (!canEditAfterCompleted) {
            // delete the restore Xml file.
            if (!instanceXml.delete()) {
                String msg = "Error deleting " + instanceXml.getAbsolutePath() + " prior to renaming submission.xml";
                Timber.e(msg);
                throw new IOException(msg);
            }
            // rename the submission.xml to be the instanceXml
            if (!submissionXml.renameTo(instanceXml)) {
                String msg = "Error renaming submission.xml to " + instanceXml.getAbsolutePath();
                Timber.e(msg);
                throw new IOException(msg);
            }
        } else {
            // (we don't need to delete and rename anything).
            if (!submissionXml.delete()) {
                String msg = "Error deleting " + submissionXml.getAbsolutePath() + " (instance is re-openable)";
                Timber.w(msg);
            }
        }
        // (anything not named instanceXml or anything not ending in .enc)
        if (isEncrypted) {
            if (!EncryptionUtils.deletePlaintextFiles(instanceXml)) {
                Timber.e("Error deleting plaintext files for %s", instanceXml.getAbsolutePath());
            }
        }
    }
}
Also used : FormController(org.odk.collect.android.logic.FormController) ByteArrayPayload(org.javarosa.core.services.transport.payload.ByteArrayPayload) IOException(java.io.IOException) EncryptedFormInformation(org.odk.collect.android.utilities.EncryptionUtils.EncryptedFormInformation) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File)

Example 37 with FormController

use of org.odk.collect.android.logic.FormController in project collect by opendatakit.

the class ODKView method setDataForFields.

public void setDataForFields(Bundle bundle) throws JavaRosaException {
    if (bundle == null) {
        return;
    }
    FormController formController = Collect.getInstance().getFormController();
    Set<String> keys = bundle.keySet();
    for (String key : keys) {
        for (QuestionWidget questionWidget : widgets) {
            FormEntryPrompt prompt = questionWidget.getFormEntryPrompt();
            TreeReference treeReference = (TreeReference) prompt.getFormElement().getBind().getReference();
            if (treeReference.getNameLast().equals(key)) {
                switch(prompt.getDataType()) {
                    case Constants.DATATYPE_TEXT:
                        formController.saveAnswer(prompt.getIndex(), ExternalAppsUtils.asStringData(bundle.get(key)));
                        break;
                    case Constants.DATATYPE_INTEGER:
                        formController.saveAnswer(prompt.getIndex(), ExternalAppsUtils.asIntegerData(bundle.get(key)));
                        break;
                    case Constants.DATATYPE_DECIMAL:
                        formController.saveAnswer(prompt.getIndex(), ExternalAppsUtils.asDecimalData(bundle.get(key)));
                        break;
                    default:
                        throw new RuntimeException(getContext().getString(R.string.ext_assign_value_error, treeReference.toString(false)));
                }
                break;
            }
        }
    }
}
Also used : FormController(org.odk.collect.android.logic.FormController) FormEntryPrompt(org.javarosa.form.api.FormEntryPrompt) TreeReference(org.javarosa.core.model.instance.TreeReference) QuestionWidget(org.odk.collect.android.widgets.QuestionWidget)

Example 38 with FormController

use of org.odk.collect.android.logic.FormController in project collect by opendatakit.

the class ItemsetWidget method getItems.

private List<SelectChoice> getItems() {
    String nodesetString = getNodesetString();
    List<String> arguments = new ArrayList<>();
    String selectionString = getSelectionStringAndPopulateArguments(getQueryString(nodesetString), arguments);
    FormController formController = Collect.getInstance().getFormController();
    String[] selectionArgs = getSelectionArgs(arguments, nodesetString, formController);
    return selectionArgs == null ? null : getItemsFromDatabase(selectionString, selectionArgs, formController);
}
Also used : FormController(org.odk.collect.android.logic.FormController) ArrayList(java.util.ArrayList)

Example 39 with FormController

use of org.odk.collect.android.logic.FormController in project collect by opendatakit.

the class QuestionWidget method clearNextLevelsOfCascadingSelect.

/**
 * It's needed only for external choices. Everything works well and
 * out of the box when we use internal choices instead
 */
protected void clearNextLevelsOfCascadingSelect() {
    FormController formController = Collect.getInstance().getFormController();
    if (formController == null) {
        return;
    }
    if (formController.currentCaptionPromptIsQuestion()) {
        try {
            FormIndex startFormIndex = formController.getQuestionPrompt().getIndex();
            formController.stepToNextScreenEvent();
            while (formController.currentCaptionPromptIsQuestion() && formController.getQuestionPrompt().getFormElement().getAdditionalAttribute(null, "query") != null) {
                formController.saveAnswer(formController.getQuestionPrompt().getIndex(), null);
                formController.stepToNextScreenEvent();
            }
            formController.jumpToIndex(startFormIndex);
        } catch (JavaRosaException e) {
            Timber.d(e);
        }
    }
}
Also used : FormController(org.odk.collect.android.logic.FormController) FormIndex(org.javarosa.core.model.FormIndex) JavaRosaException(org.odk.collect.android.exception.JavaRosaException)

Example 40 with FormController

use of org.odk.collect.android.logic.FormController in project collect by opendatakit.

the class InstancesDaoHelper method isInstanceComplete.

/**
 * Checks the database to determine if the current instance being edited has
 * already been 'marked completed'. A form can be 'unmarked' complete and
 * then resaved.
 *
 * @return true if form has been marked completed, false otherwise.
 */
public static boolean isInstanceComplete(boolean end) {
    // default to false if we're mid form
    boolean complete = false;
    FormController formController = Collect.getInstance().getFormController();
    if (formController != null && formController.getInstanceFile() != null) {
        // First check if we're at the end of the form, then check the preferences
        complete = end && (boolean) GeneralSharedPreferences.getInstance().get(PreferenceKeys.KEY_COMPLETED_DEFAULT);
        // Then see if we've already marked this form as complete before
        String path = formController.getInstanceFile().getAbsolutePath();
        try (Cursor c = new InstancesDao().getInstancesCursorForFilePath(path)) {
            if (c != null && c.getCount() > 0) {
                c.moveToFirst();
                int columnIndex = c.getColumnIndex(InstanceProviderAPI.InstanceColumns.STATUS);
                String status = c.getString(columnIndex);
                if (InstanceProviderAPI.STATUS_COMPLETE.equals(status)) {
                    complete = true;
                }
            }
        }
    } else {
        Timber.w("FormController or its instanceFile field has a null value");
    }
    return complete;
}
Also used : FormController(org.odk.collect.android.logic.FormController) InstancesDao(org.odk.collect.android.dao.InstancesDao) Cursor(android.database.Cursor)

Aggregations

FormController (org.odk.collect.android.logic.FormController)42 FailedConstraint (org.odk.collect.android.logic.FormController.FailedConstraint)10 FormIndex (org.javarosa.core.model.FormIndex)8 JavaRosaException (org.odk.collect.android.exception.JavaRosaException)8 File (java.io.File)7 OnClickListener (android.view.View.OnClickListener)6 ODKView (org.odk.collect.android.views.ODKView)6 DialogInterface (android.content.DialogInterface)5 View (android.view.View)5 AdapterView (android.widget.AdapterView)5 ListView (android.widget.ListView)5 TextView (android.widget.TextView)5 IOException (java.io.IOException)4 FormEntryPrompt (org.javarosa.form.api.FormEntryPrompt)4 Collect (org.odk.collect.android.application.Collect)4 GDriveConnectionException (org.odk.collect.android.exception.GDriveConnectionException)4 ContentValues (android.content.ContentValues)3 Intent (android.content.Intent)3 Cursor (android.database.Cursor)3 FormEntryCaption (org.javarosa.form.api.FormEntryCaption)3