Search in sources :

Example 61 with TreeElement

use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.

the class FormEntryModel method createModelIfNecessary.

/**
 * For the current index: Checks whether the index represents a node which
 * should exist given a non-interactive repeat, along with a count for that
 * repeat which is beneath the dynamic level specified.
 *
 * If this index does represent such a node, the new model for the repeat is
 * created behind the scenes and the index for the initial question is
 * returned.
 *
 * Note: This method will not prevent the addition of new repeat elements in
 * the interface, it will merely use the xforms repeat hint to create new
 * nodes that are assumed to exist
 *
 * @param index The index to be evaluated as to whether the underlying model is
 *        hinted to exist
 */
private void createModelIfNecessary(FormIndex index) {
    if (index.isInForm()) {
        IFormElement e = getForm().getChild(index);
        if (e instanceof GroupDef) {
            GroupDef g = (GroupDef) e;
            if (g.getRepeat() && g.getCountReference() != null) {
                // Lu Gram: repeat count XPath needs to be contextualized for nested repeat groups
                TreeReference countRef = FormInstance.unpackReference(g.getCountReference());
                TreeReference contextualized = countRef.contextualize(index.getReference());
                IAnswerData count = getForm().getMainInstance().resolveReference(contextualized).getValue();
                if (count != null) {
                    long fullcount = ((Integer) count.getValue()).intValue();
                    TreeReference ref = getForm().getChildInstanceRef(index);
                    TreeElement element = getForm().getMainInstance().resolveReference(ref);
                    if (element == null) {
                        if (index.getTerminal().getInstanceIndex() < fullcount) {
                            try {
                                getForm().createNewRepeat(index);
                            } catch (InvalidReferenceException ire) {
                                Std.printStack(ire);
                                throw new RuntimeException("Invalid Reference while creting new repeat!" + ire.getMessage());
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : IAnswerData(org.javarosa.core.model.data.IAnswerData) IFormElement(org.javarosa.core.model.IFormElement) TreeReference(org.javarosa.core.model.instance.TreeReference) GroupDef(org.javarosa.core.model.GroupDef) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 62 with TreeElement

use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.

the class FormEntryModel method setRepeatNextMultiplicity.

private boolean setRepeatNextMultiplicity(List<IFormElement> elements, List<Integer> multiplicities) {
    // find out if node is repeatable
    TreeReference nodeRef = form.getChildInstanceRef(elements, multiplicities);
    TreeElement node = form.getMainInstance().resolveReference(nodeRef);
    if (node == null || node.isRepeatable()) {
        // node == null if there are no instances of the repeat
        IFormElement lastElement = elements.get(elements.size() - 1);
        if (lastElement instanceof GroupDef && !((GroupDef) lastElement).getRepeat()) {
            // it's a regular group inside a repeatable group
            return false;
        }
        int mult;
        if (node == null) {
            // no repeats; next is 0
            mult = 0;
        } else {
            String name = node.getName();
            TreeElement parentNode = form.getMainInstance().resolveReference(nodeRef.getParentRef());
            mult = parentNode.getChildMultiplicity(name);
        }
        multiplicities.set(multiplicities.size() - 1, repeatStructure == REPEAT_STRUCTURE_NON_LINEAR ? TreeReference.INDEX_REPEAT_JUNCTURE : mult);
        return true;
    } else {
        return false;
    }
}
Also used : IFormElement(org.javarosa.core.model.IFormElement) TreeReference(org.javarosa.core.model.instance.TreeReference) GroupDef(org.javarosa.core.model.GroupDef) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 63 with TreeElement

use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.

the class FormEntryController method answerQuestion.

/**
 * Attempts to save the answer at the specified FormIndex into the
 * datamodel.
 *
 * @param index
 * @param data
 * @return OK if save was successful, error if a constraint was violated.
 */
public int answerQuestion(FormIndex index, IAnswerData data, boolean midSurvey) {
    QuestionDef q = model.getQuestionPrompt(index).getQuestion();
    if (model.getEvent(index) != FormEntryController.EVENT_QUESTION) {
        throw new RuntimeException("Non-Question object at the form index.");
    }
    TreeElement element = model.getTreeElement(index);
    boolean complexQuestion = q.isComplex();
    boolean hasConstraints = false;
    if (element.isRequired() && data == null) {
        return ANSWER_REQUIRED_BUT_EMPTY;
    } else if (!complexQuestion && !model.getForm().evaluateConstraint(index.getReference(), data)) {
        return ANSWER_CONSTRAINT_VIOLATED;
    } else if (!complexQuestion) {
        commitAnswer(element, index, data, midSurvey);
        return ANSWER_OK;
    } else if (complexQuestion && hasConstraints) {
        // TODO: itemsets: don't currently evaluate constraints for itemset/copy -- haven't figured out how handle it yet
        throw new RuntimeException("Itemsets do not currently evaluate constraints. Your constraint will not work, please remove it before proceeding.");
    } else {
        try {
            model.getForm().copyItemsetAnswer(q, element, data, midSurvey);
        } catch (InvalidReferenceException ire) {
            Std.printStack(ire);
            throw new RuntimeException("Invalid reference while copying itemset answer: " + ire.getMessage());
        }
        return ANSWER_OK;
    }
}
Also used : QuestionDef(org.javarosa.core.model.QuestionDef) InvalidReferenceException(org.javarosa.core.model.instance.InvalidReferenceException) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 64 with TreeElement

use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.

the class FormEntryPrompt method getAnswerValue.

// note: code overlap with FormDef.copyItemsetAnswer
public IAnswerData getAnswerValue() {
    QuestionDef q = getQuestion();
    ItemsetBinding itemset = q.getDynamicChoices();
    if (itemset != null) {
        if (itemset.valueRef != null) {
            List<SelectChoice> choices = getSelectChoices();
            List<String> preselectedValues = new ArrayList<String>();
            // determine which selections are already present in the answer
            if (itemset.copyMode) {
                TreeReference destRef = itemset.getDestRef().contextualize(mTreeElement.getRef());
                List<TreeReference> subNodes = form.getEvaluationContext().expandReference(destRef);
                for (int i = 0; i < subNodes.size(); i++) {
                    TreeElement node = form.getMainInstance().resolveReference(subNodes.get(i));
                    String value = itemset.getRelativeValue().evalReadable(form.getMainInstance(), new EvaluationContext(form.getEvaluationContext(), node.getRef()));
                    preselectedValues.add(value);
                }
            } else {
                List<Selection> sels;
                IAnswerData data = mTreeElement.getValue();
                if (data instanceof SelectMultiData) {
                    sels = (List<Selection>) data.getValue();
                } else if (data instanceof SelectOneData) {
                    sels = new ArrayList<Selection>(1);
                    sels.add((Selection) data.getValue());
                } else {
                    sels = new ArrayList<Selection>(0);
                }
                for (int i = 0; i < sels.size(); i++) {
                    preselectedValues.add(sels.get(i).xmlValue);
                }
            }
            // populate 'selection' with the corresponding choices (matching 'value') from the dynamic choiceset
            List<Selection> selection = new ArrayList<Selection>();
            for (int i = 0; i < preselectedValues.size(); i++) {
                String value = preselectedValues.get(i);
                SelectChoice choice = null;
                for (int j = 0; j < choices.size(); j++) {
                    SelectChoice ch = choices.get(j);
                    if (value.equals(ch.getValue())) {
                        choice = ch;
                        break;
                    }
                }
                // will no longer be an option this go around
                if (choice != null) {
                    selection.add(choice.selection());
                }
            }
            // convert to IAnswerData
            if (selection.size() == 0) {
                return null;
            } else if (q.getControlType() == Constants.CONTROL_SELECT_MULTI) {
                return new SelectMultiData(selection);
            } else if (q.getControlType() == Constants.CONTROL_SELECT_ONE) {
                // do something if more than one selected?
                return new SelectOneData(selection.get(0));
            } else {
                throw new RuntimeException("can't happen");
            }
        } else {
            // cannot map up selections without <value>
            return null;
        }
    } else {
        // static choices
        return mTreeElement.getValue();
    }
}
Also used : IAnswerData(org.javarosa.core.model.data.IAnswerData) SelectOneData(org.javarosa.core.model.data.SelectOneData) SelectChoice(org.javarosa.core.model.SelectChoice) Selection(org.javarosa.core.model.data.helper.Selection) ArrayList(java.util.ArrayList) ItemsetBinding(org.javarosa.core.model.ItemsetBinding) ConstraintHint(org.javarosa.core.model.condition.pivot.ConstraintHint) Constraint(org.javarosa.core.model.condition.Constraint) TreeElement(org.javarosa.core.model.instance.TreeElement) SelectMultiData(org.javarosa.core.model.data.SelectMultiData) TreeReference(org.javarosa.core.model.instance.TreeReference) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) QuestionDef(org.javarosa.core.model.QuestionDef)

Example 65 with TreeElement

use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.

the class TreeElementParser method parse.

@Override
public TreeElement parse() throws InvalidStructureException, IOException, XmlPullParserException, UnfullfilledRequirementsException {
    final int depth = parser.getDepth();
    final TreeElement element = new TreeElement(parser.getName(), multiplicity);
    element.setInstanceName(instanceId);
    for (int i = 0; i < parser.getAttributeCount(); ++i) {
        element.setAttribute(parser.getAttributeNamespace(i), parser.getAttributeName(i), parser.getAttributeValue(i));
    }
    final Map<String, Integer> multiplicitiesByName = new HashMap<>();
    // loop parses all siblings at a given depth
    while (parser.getDepth() >= depth) {
        switch(nextNonWhitespace()) {
            case KXmlParser.START_TAG:
                String name = parser.getName();
                final Integer multiplicity = multiplicitiesByName.get(name);
                int newMultiplicity = (multiplicity != null) ? multiplicity + 1 : 0;
                multiplicitiesByName.put(name, newMultiplicity);
                TreeElement childTreeElement = new TreeElementParser(parser, newMultiplicity, instanceId).parse();
                element.addChild(childTreeElement);
                break;
            case KXmlParser.END_TAG:
                return element;
            case KXmlParser.TEXT:
                element.setValue(new UncastData(parser.getText().trim()));
                break;
            default:
                throw new InvalidStructureException("Exception while trying to parse an XML Tree, got something other than tags and text", parser);
        }
    }
    return element;
}
Also used : HashMap(java.util.HashMap) UncastData(org.javarosa.core.model.data.UncastData) InvalidStructureException(org.javarosa.xml.util.InvalidStructureException) TreeElement(org.javarosa.core.model.instance.TreeElement)

Aggregations

TreeElement (org.javarosa.core.model.instance.TreeElement)86 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)33 TreeReference (org.javarosa.core.model.instance.TreeReference)28 FormInstance (org.javarosa.core.model.instance.FormInstance)16 ArrayList (java.util.ArrayList)15 Constraint (org.javarosa.core.model.condition.Constraint)11 Test (org.junit.Test)10 Element (org.kxml2.kdom.Element)9 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)8 FormDef (org.javarosa.core.model.FormDef)7 InstanceInitializationFactory (org.javarosa.core.model.instance.InstanceInitializationFactory)7 IOException (java.io.IOException)6 IFormElement (org.javarosa.core.model.IFormElement)6 StringData (org.javarosa.core.model.data.StringData)6 HashMap (java.util.HashMap)5 IAnswerData (org.javarosa.core.model.data.IAnswerData)4 File (java.io.File)3 GroupDef (org.javarosa.core.model.GroupDef)3 IDataReference (org.javarosa.core.model.IDataReference)3 QuestionDef (org.javarosa.core.model.QuestionDef)3