Search in sources :

Example 1 with ItemsetBinding

use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.

the class FormInstanceParser method verifyItemsetSrcDstCompatibility.

private void verifyItemsetSrcDstCompatibility(FormInstance instance) {
    for (ItemsetBinding itemset : itemsets) {
        boolean destRepeatable = (instance.getTemplate(itemset.getDestRef()) != null);
        if (itemset.copyMode) {
            if (!destRepeatable) {
                throw new XFormParseException("itemset copies to node(s) which are not repeatable");
            }
            // validate homogeneity between src and dst nodes
            TreeElement srcNode = instance.getTemplatePath(itemset.copyRef);
            TreeElement dstNode = instance.getTemplate(itemset.getDestRef());
            if (!FormInstance.isHomogeneous(srcNode, dstNode)) {
                reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Your itemset source [" + srcNode.getRef().toString() + "] and dest [" + dstNode.getRef().toString() + "] of appear to be incompatible!", null);
            }
        // TODO: i feel like, in theory, i should additionally check that the repeatable children of src and dst
        // match up (Achild is repeatable <--> Bchild is repeatable). isHomogeneous doesn't check this. but i'm
        // hard-pressed to think of scenarios where this would actually cause problems
        } else {
            if (destRepeatable) {
                throw new XFormParseException("itemset sets value on repeatable nodes");
            }
        }
    }
}
Also used : ItemsetBinding(org.javarosa.core.model.ItemsetBinding) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 2 with ItemsetBinding

use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.

the class FormEntryPrompt method expireDynamicChoices.

public void expireDynamicChoices() {
    dynamicChoicesPopulated = false;
    ItemsetBinding itemset = getQuestion().getDynamicChoices();
    if (itemset != null) {
        itemset.clearChoices();
    }
}
Also used : ItemsetBinding(org.javarosa.core.model.ItemsetBinding)

Example 3 with ItemsetBinding

use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.

the class FormEntryPrompt method getSelectChoices.

public List<SelectChoice> getSelectChoices() {
    QuestionDef q = getQuestion();
    ItemsetBinding itemset = q.getDynamicChoices();
    if (itemset != null) {
        if (!dynamicChoicesPopulated) {
            form.populateDynamicChoices(itemset, mTreeElement.getRef());
            dynamicChoicesPopulated = true;
        }
        return itemset.getChoices();
    } else {
        // static choices
        return q.getChoices();
    }
}
Also used : ItemsetBinding(org.javarosa.core.model.ItemsetBinding) QuestionDef(org.javarosa.core.model.QuestionDef)

Example 4 with ItemsetBinding

use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.

the class XFormParser method parseItemset.

private void parseItemset(QuestionDef q, Element e, IFormElement qparent) {
    ItemsetBinding itemset = new ItemsetBinding();
    // //////////////USED FOR PARSER WARNING OUTPUT ONLY
    // catalogue of used attributes in this method/element
    List<String> usedAtts = new ArrayList<>();
    // for child with name 'label'
    List<String> labelUA = new ArrayList<>();
    // for child with name 'value'
    List<String> valueUA = new ArrayList<>();
    // for child with name 'copy'
    List<String> copyUA = new ArrayList<>();
    usedAtts.add(NODESET_ATTR);
    labelUA.add(REF_ATTR);
    valueUA.add(REF_ATTR);
    valueUA.add(FORM_ATTR);
    copyUA.add(REF_ATTR);
    // //////////////////////////////////////////////////
    /*
         * At this point in time, we cannot construct a valid nodesetRef
         *
         * Leave all ...Ref entries as null and test the ...Expr entries for null / non-null values.
         *
         * We will patch this all up in the verifyItemsetBindings() method.
         */
    String nodesetStr = e.getAttributeValue("", NODESET_ATTR);
    if (nodesetStr == null)
        throw new RuntimeException("No nodeset attribute in element: [" + e.getName() + "]. This is required. (Element Printout:" + XFormSerializer.elementToString(e) + ")");
    XPathPathExpr path = XPathReference.getPathExpr(nodesetStr);
    itemset.nodesetExpr = new XPathConditional(path);
    itemset.contextRef = getFormElementRef(qparent);
    // this is not valid yet...
    itemset.nodesetRef = null;
    // itemset.nodesetRef = FormInstance.unpackReference(getAbsRef(new XPathReference(path.getReference(true)), itemset.contextRef));
    itemset.copyMode = false;
    for (int i = 0; i < e.getChildCount(); i++) {
        int type = e.getType(i);
        Element child = (type == Node.ELEMENT ? e.getElement(i) : null);
        String childName = (child != null ? child.getName() : null);
        if (LABEL_ELEMENT.equals(childName)) {
            String labelXpath = child.getAttributeValue("", REF_ATTR);
            boolean labelItext = false;
            // print unused attribute warning message for child element
            if (XFormUtils.showUnusedAttributeWarning(child, labelUA)) {
                reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(child, labelUA), getVagueLocation(child));
            }
            if (labelXpath != null) {
                if (labelXpath.startsWith(DYNAMIC_ITEXT_OPEN) && labelXpath.endsWith(DYNAMIC_ITEXT_CLOSE)) {
                    labelXpath = labelXpath.substring(DYNAMIC_ITEXT_OPEN.length(), labelXpath.lastIndexOf(DYNAMIC_ITEXT_CLOSE));
                    labelItext = true;
                }
            } else {
                throw new XFormParseException("<label> in <itemset> requires 'ref'");
            }
            XPathPathExpr labelPath = XPathReference.getPathExpr(labelXpath);
            itemset.labelRef = null;
            // itemset.labelRef = FormInstance.unpackReference(getAbsRef(new XPathReference(labelPath), itemset.nodesetRef));
            itemset.labelExpr = new XPathConditional(labelPath);
            itemset.labelIsItext = labelItext;
        } else if ("copy".equals(childName)) {
            String copyXpath = child.getAttributeValue("", REF_ATTR);
            // print unused attribute warning message for child element
            if (XFormUtils.showUnusedAttributeWarning(child, copyUA)) {
                reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(child, copyUA), getVagueLocation(child));
            }
            if (copyXpath == null) {
                throw new XFormParseException("<copy> in <itemset> requires 'ref'");
            }
            XPathPathExpr copyPath = XPathReference.getPathExpr(copyXpath);
            itemset.copyRef = null;
            // itemset.copyRef = FormInstance.unpackReference(getAbsRef(new XPathReference(copyPath), itemset.nodesetRef));
            itemset.copyExpr = new XPathConditional(copyPath);
            itemset.copyMode = true;
        } else if (VALUE.equals(childName)) {
            String valueXpath = child.getAttributeValue("", REF_ATTR);
            // print unused attribute warning message for child element
            if (XFormUtils.showUnusedAttributeWarning(child, valueUA)) {
                reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(child, valueUA), getVagueLocation(child));
            }
            if (valueXpath == null) {
                throw new XFormParseException("<value> in <itemset> requires 'ref'");
            }
            XPathPathExpr valuePath = XPathReference.getPathExpr(valueXpath);
            itemset.valueRef = null;
            // itemset.valueRef = FormInstance.unpackReference(getAbsRef(new XPathReference(valuePath), itemset.nodesetRef));
            itemset.valueExpr = new XPathConditional(valuePath);
        }
    }
    if (itemset.labelExpr == null) {
        throw new XFormParseException("<itemset> requires <label>");
    } else if (itemset.copyExpr == null && itemset.valueExpr == null) {
        throw new XFormParseException("<itemset> requires <copy> or <value>");
    }
    if (itemset.copyExpr != null) {
        if (itemset.valueExpr == null) {
            reporter.warning(XFormParserReporter.TYPE_TECHNICAL, "<itemset>s with <copy> are STRONGLY recommended to have <value> as well; pre-selecting, default answers, and display of answers will not work properly otherwise", getVagueLocation(e));
        }
    }
    itemsets.add(itemset);
    q.setDynamicChoices(itemset);
    // print unused attribute warning message for parent element
    if (XFormUtils.showUnusedAttributeWarning(e, usedAtts)) {
        reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(e, usedAtts), getVagueLocation(e));
    }
}
Also used : XPathPathExpr(org.javarosa.xpath.expr.XPathPathExpr) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement) Element(org.kxml2.kdom.Element) IFormElement(org.javarosa.core.model.IFormElement) ArrayList(java.util.ArrayList) ItemsetBinding(org.javarosa.core.model.ItemsetBinding) XPathConditional(org.javarosa.xpath.XPathConditional)

Example 5 with ItemsetBinding

use of org.javarosa.core.model.ItemsetBinding 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)

Aggregations

ItemsetBinding (org.javarosa.core.model.ItemsetBinding)5 TreeElement (org.javarosa.core.model.instance.TreeElement)3 ArrayList (java.util.ArrayList)2 QuestionDef (org.javarosa.core.model.QuestionDef)2 IFormElement (org.javarosa.core.model.IFormElement)1 SelectChoice (org.javarosa.core.model.SelectChoice)1 Constraint (org.javarosa.core.model.condition.Constraint)1 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)1 ConstraintHint (org.javarosa.core.model.condition.pivot.ConstraintHint)1 IAnswerData (org.javarosa.core.model.data.IAnswerData)1 SelectMultiData (org.javarosa.core.model.data.SelectMultiData)1 SelectOneData (org.javarosa.core.model.data.SelectOneData)1 Selection (org.javarosa.core.model.data.helper.Selection)1 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)1 TreeReference (org.javarosa.core.model.instance.TreeReference)1 XPathConditional (org.javarosa.xpath.XPathConditional)1 XPathPathExpr (org.javarosa.xpath.expr.XPathPathExpr)1 Element (org.kxml2.kdom.Element)1