Search in sources :

Example 26 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method getIndicesForGroup.

private List<FormIndex> getIndicesForGroup(GroupDef gd, FormIndex currentChildIndex, boolean jumpIntoRepeatGroups) {
    List<FormIndex> indices = new ArrayList<>();
    for (int i = 0; i < gd.getChildren().size(); i++) {
        final FormEntryModel formEntryModel = formEntryController.getModel();
        if (getEvent(currentChildIndex) == FormEntryController.EVENT_GROUP || (jumpIntoRepeatGroups && getEvent(currentChildIndex) == FormEntryController.EVENT_REPEAT)) {
            IFormElement nestedElement = formEntryModel.getForm().getChild(currentChildIndex);
            if (nestedElement instanceof GroupDef) {
                indices.addAll(getIndicesForGroup((GroupDef) nestedElement, formEntryModel.incrementIndex(currentChildIndex, true), jumpIntoRepeatGroups));
                currentChildIndex = formEntryModel.incrementIndex(currentChildIndex, false);
            }
        } else if (!jumpIntoRepeatGroups || getEvent(currentChildIndex) != FormEntryController.EVENT_PROMPT_NEW_REPEAT) {
            indices.add(currentChildIndex);
            currentChildIndex = formEntryModel.incrementIndex(currentChildIndex, false);
        }
    }
    return indices;
}
Also used : IFormElement(org.javarosa.core.model.IFormElement) FormEntryModel(org.javarosa.form.api.FormEntryModel) ArrayList(java.util.ArrayList) FormIndex(org.javarosa.core.model.FormIndex) GroupDef(org.javarosa.core.model.GroupDef)

Example 27 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method stepOverGroup.

/**
 * If using a view like HierarchyView that doesn't support multi-question per screen, step over
 * the group represented by the FormIndex.
 */
public int stepOverGroup() {
    GroupDef gd = (GroupDef) formEntryController.getModel().getForm().getChild(getFormIndex());
    List<FormIndex> indices = getIndicesForGroup(gd);
    // jump to the end of the group
    formEntryController.jumpToIndex(indices.get(indices.size() - 1));
    return stepToNextEvent(STEP_OVER_GROUP);
}
Also used : FormIndex(org.javarosa.core.model.FormIndex) GroupDef(org.javarosa.core.model.GroupDef)

Example 28 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormController method getIndexFromXPath.

@Nullable
public FormIndex getIndexFromXPath(String xpath) {
    switch(xpath) {
        case "beginningOfForm":
            return FormIndex.createBeginningOfFormIndex();
        case "endOfForm":
            return FormIndex.createEndOfFormIndex();
        case "unexpected":
            Timber.e("Unexpected string from XPath");
            return null;
        default:
            FormIndex returned = null;
            FormIndex saved = getFormIndex();
            // until the XPath of a form entry matches that of the supplied XPath
            try {
                jumpToIndex(FormIndex.createBeginningOfFormIndex());
                int event = stepToNextEvent(true);
                while (event != FormEntryController.EVENT_END_OF_FORM) {
                    String candidateXPath = getXPath(getFormIndex());
                    if (candidateXPath.equals(xpath)) {
                        returned = getFormIndex();
                        break;
                    }
                    event = stepToNextEvent(true);
                }
            } finally {
                jumpToIndex(saved);
            }
            return returned;
    }
}
Also used : FormIndex(org.javarosa.core.model.FormIndex) Nullable(androidx.annotation.Nullable)

Example 29 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class FormLoaderTask method doInBackground.

/**
 * Initialize {@link FormEntryController} with {@link FormDef} from binary or
 * from XML. If given an instance, it will be used to fill the {@link FormDef}.
 */
@Override
protected FECWrapper doInBackground(String... path) {
    errorMsg = null;
    final String formPath = path[0];
    if (formPath == null) {
        Timber.e("formPath is null");
        errorMsg = "formPath is null, please email support@getodk.org with a description of what you were doing when this happened.";
        return null;
    }
    final File formXml = new File(formPath);
    final File formMediaDir = FileUtils.getFormMediaDir(formXml);
    setupReferenceManagerForForm(ReferenceManager.instance(), formMediaDir);
    FormDef formDef = null;
    try {
        formDef = createFormDefFromCacheOrXml(formPath, formXml);
    } catch (StackOverflowError e) {
        Timber.e(e);
        errorMsg = getLocalizedString(Collect.getInstance(), R.string.too_complex_form);
    } catch (Exception | Error e) {
        Timber.w(e);
        errorMsg = "An unknown error has occurred. Please ask your project leadership to email support@getodk.org with information about this form.";
        errorMsg += "\n\n" + e.getMessage();
    }
    if (errorMsg != null || formDef == null) {
        Timber.w("No exception loading form but errorMsg set");
        return null;
    }
    externalDataManager = new ExternalDataManagerImpl(formMediaDir);
    // add external data function handlers
    ExternalDataHandler externalDataHandlerPull = new ExternalDataHandlerPull(externalDataManager);
    formDef.getEvaluationContext().addFunctionHandler(externalDataHandlerPull);
    try {
        loadExternalData(formMediaDir);
    } catch (Exception e) {
        Timber.e(e, "Exception thrown while loading external data");
        errorMsg = e.getMessage();
        return null;
    }
    if (isCancelled()) {
        // that means that the user has cancelled, so no need to go further
        return null;
    }
    // create FormEntryController from formdef
    final FormEntryModel fem = new FormEntryModel(formDef);
    final FormEntryController fec = new FormEntryController(fem);
    boolean usedSavepoint = false;
    try {
        Timber.i("Initializing form.");
        final long start = System.currentTimeMillis();
        usedSavepoint = initializeForm(formDef, fec);
        Timber.i("Form initialized in %.3f seconds.", (System.currentTimeMillis() - start) / 1000F);
    } catch (IOException | RuntimeException e) {
        Timber.e(e);
        if (e.getCause() instanceof XPathTypeMismatchException) {
            // this is a case of
            // https://bitbucket.org/m
            // .sundt/javarosa/commits/e5d344783e7968877402bcee11828fa55fac69de
            // the data are imported, the survey will be unusable
            // but we should give the option to the user to edit the form
            // otherwise the survey will be TOTALLY inaccessible.
            Timber.w("We have a syntactically correct instance, but the data threw an exception inside JR. We should allow editing.");
        } else {
            errorMsg = e.getMessage();
            return null;
        }
    }
    processItemSets(formMediaDir);
    final FormController fc = new FormController(formMediaDir, fec, instancePath == null ? null : new File(instancePath));
    if (xpath != null) {
        // we are resuming after having terminated -- set index to this
        // position...
        FormIndex idx = fc.getIndexFromXPath(xpath);
        if (idx != null) {
            fc.jumpToIndex(idx);
        }
    }
    if (waitingXPath != null) {
        FormIndex idx = fc.getIndexFromXPath(waitingXPath);
        if (idx != null) {
            fc.setIndexWaitingForData(idx);
        }
    }
    data = new FECWrapper(fc, usedSavepoint);
    return data;
}
Also used : FormController(org.odk.collect.android.javarosawrapper.FormController) FormEntryController(org.javarosa.form.api.FormEntryController) FormEntryModel(org.javarosa.form.api.FormEntryModel) LocalizedApplicationKt.getLocalizedString(org.odk.collect.strings.localization.LocalizedApplicationKt.getLocalizedString) IOException(java.io.IOException) ExternalDataHandlerPull(org.odk.collect.android.externaldata.handler.ExternalDataHandlerPull) ExternalDataHandler(org.odk.collect.android.externaldata.ExternalDataHandler) CsvValidationException(com.opencsv.exceptions.CsvValidationException) IOException(java.io.IOException) SQLException(android.database.SQLException) XPathTypeMismatchException(org.javarosa.xpath.XPathTypeMismatchException) ExternalDataManagerImpl(org.odk.collect.android.externaldata.ExternalDataManagerImpl) FormDef(org.javarosa.core.model.FormDef) FormIndex(org.javarosa.core.model.FormIndex) XPathTypeMismatchException(org.javarosa.xpath.XPathTypeMismatchException) File(java.io.File)

Example 30 with FormIndex

use of org.javarosa.core.model.FormIndex in project collect by opendatakit.

the class SelectOneWidget method clearFollowingItemsetWidgets.

/**
 * If there are "fast external itemset" selects right after this select, assume that they are linked to the current question and clear them.
 */
private void clearFollowingItemsetWidgets() {
    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.javarosawrapper.FormController) FormIndex(org.javarosa.core.model.FormIndex) JavaRosaException(org.odk.collect.android.exception.JavaRosaException)

Aggregations

FormIndex (org.javarosa.core.model.FormIndex)63 GroupDef (org.javarosa.core.model.GroupDef)11 JavaRosaException (org.odk.collect.android.exception.JavaRosaException)11 FormController (org.odk.collect.android.javarosawrapper.FormController)11 ArrayList (java.util.ArrayList)10 FormEntryPrompt (org.javarosa.form.api.FormEntryPrompt)10 Test (org.junit.Test)10 IFormElement (org.javarosa.core.model.IFormElement)6 TreeReference (org.javarosa.core.model.instance.TreeReference)6 FormEntryCaption (org.javarosa.form.api.FormEntryCaption)6 File (java.io.File)5 FormController (org.odk.collect.android.logic.FormController)5 HierarchyElement (org.odk.collect.android.logic.HierarchyElement)5 IAnswerData (org.javarosa.core.model.data.IAnswerData)4 HierarchyListAdapter (org.odk.collect.android.adapters.HierarchyListAdapter)4 FormDef (org.javarosa.core.model.FormDef)3 FormEntryModel (org.javarosa.form.api.FormEntryModel)3 Intent (android.content.Intent)2 ObjectInputStream (java.io.ObjectInputStream)2 HashMap (java.util.HashMap)2