Search in sources :

Example 51 with TreeReference

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

the class XPathFuncExpr method indexedRepeat.

/**
 * This provides a method of indexing fields stored in prior repeat groups.
 *
 * args[0] = generic XPath expression to index
 * args[1] = generic XPath expression for group to index
 * args[2] = index number for group
 * args[3] = generic XPath expression for add'l group to index (if 5 or 7 parameters passed)
 * args[4] = index number for group (if 5 or 7 parameters passed)
 * args[5] = generic XPath expression for add'l group to index (if 7 parameters passed)
 * args[6] = index number for group (if 7 parameters passed)
 *
 * @param model
 * @param ec
 * @param args
 * @param argVals
 * @return
 */
public static Object indexedRepeat(DataInstance model, EvaluationContext ec, XPathExpression[] args, Object[] argVals) throws XPathTypeMismatchException {
    // initialize target and context references
    if (!(args[0] instanceof XPathPathExpr)) {
        throw new XPathTypeMismatchException("indexed-repeat(): first parameter must be XPath field reference");
    }
    XPathPathExpr targetPath = (XPathPathExpr) args[0];
    TreeReference targetRef = targetPath.getReference();
    TreeReference contextRef = targetRef.clone();
    // process passed index(es)
    for (int pathargi = 1, idxargi = 2; idxargi < args.length; pathargi += 2, idxargi += 2) {
        // confirm that we were passed an XPath
        if (!(args[pathargi] instanceof XPathPathExpr)) {
            throw new XPathTypeMismatchException("indexed-repeat(): parameter " + (pathargi + 1) + " must be XPath repeat-group reference");
        }
        // confirm that the passed XPath is a parent of our overall target path
        TreeReference groupRef = ((XPathPathExpr) args[pathargi]).getReference();
        if (!groupRef.isParentOf(targetRef, true)) {
            throw new XPathTypeMismatchException("indexed-repeat(): parameter " + (pathargi + 1) + " must be a parent of the field in parameter 1");
        }
        // process index (if valid)
        int groupIdx = toInt(args[idxargi].eval(model, ec)).intValue();
        if (groupIdx <= 0) {
            /*
                   Don't allow invalid index otherwise an exception will be thrown later by XPathNodeset#unpack().
                   This may happen if referenced node hadn't gotten a value yet but the calculation was fired. For example when adding a new repeat.
                 */
            groupIdx = 1;
        }
        contextRef.setMultiplicity(groupRef.size() - 1, groupIdx - 1);
    }
    // evaluate and return the XPath expression, in context
    EvaluationContext revisedec = new EvaluationContext(ec, contextRef);
    return (targetPath.eval(model, revisedec));
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) XPathTypeMismatchException(org.javarosa.xpath.XPathTypeMismatchException) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext)

Example 52 with TreeReference

use of org.javarosa.core.model.instance.TreeReference 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 53 with TreeReference

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

the class Fast2014DagImpl method evaluateChildrenTriggerables.

private void evaluateChildrenTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeElement newNode, boolean createdOrDeleted, boolean midSurvey, Set<QuickTriggerable> alreadyEvaluated) {
    // iterate into the group children and evaluate any triggerables that
    // depend one them, if they are not already calculated.
    int numChildren = newNode.getNumChildren();
    for (int i = 0; i < numChildren; i++) {
        TreeReference anchorRef = newNode.getChildAt(i).getRef();
        Set<QuickTriggerable> childTriggerables = triggerTriggerables(mainInstance, evalContext, anchorRef, midSurvey, alreadyEvaluated);
        publishSummary((createdOrDeleted ? "Created" : "Deleted"), anchorRef, childTriggerables);
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference)

Example 54 with TreeReference

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

the class Fast2014DagImpl method fillTriggeredElements.

/**
 * Get all of the elements which will need to be evaluated (in order) when
 * the triggerable is fired.
 *
 * @param qt
 * @param destinationSet
 *            where to store the triggerables
 * @param midSurvey
 *            if true, then the slow code will execute, if false, then
 *            old/fast code will execute that suffers from
 *            https://code.google.com/p/opendatakit/issues/detail?id=888
 */
public void fillTriggeredElements(FormInstance mainInstance, EvaluationContext evalContext, QuickTriggerable qt, Set<QuickTriggerable> destinationSet, Set<QuickTriggerable> newDestinationSet, boolean midSurvey) {
    if (qt.t.canCascade()) {
        List<TreeReference> targets = qt.t.getTargets();
        if (!midSurvey) {
            for (TreeReference target : targets) {
                ArrayList<QuickTriggerable> triggered = triggerIndex.get(target);
                if (triggered != null) {
                    for (QuickTriggerable qu : triggered) {
                        if (!destinationSet.contains(qu)) {
                            destinationSet.add(qu);
                            newDestinationSet.add(qu);
                        }
                    }
                }
            }
        } else {
            boolean expandRepeatables = true;
            for (TreeReference target : targets) {
                Set<TreeReference> updatedNodes = new HashSet<TreeReference>();
                updatedNodes.add(target);
                // to the list of updated elements as well.
                if (qt.t.isCascadingToChildren()) {
                    addChildrenOfReference(mainInstance, evalContext, target, updatedNodes, expandRepeatables);
                }
                // multiple nodes if there's a relevance cascade.
                for (TreeReference ref : updatedNodes) {
                    // Check our index to see if that target is a Trigger
                    // for
                    // other
                    // conditions
                    // IE: if they are an element of a different calculation
                    // or
                    // relevancy calc
                    // We can't make this reference generic before now or
                    // we'll
                    // lose the
                    // target information,
                    // so we'll be more inclusive than needed and see if any
                    // of
                    // our
                    // triggers are keyed on
                    // the predicate-less path of this ref
                    ArrayList<QuickTriggerable> triggered = triggerIndex.get(ref.hasPredicates() ? ref.removePredicates() : ref);
                    if (triggered != null) {
                        // found
                        for (QuickTriggerable qu : triggered) {
                            // already
                            if (!destinationSet.contains(qu)) {
                                destinationSet.add(qu);
                                newDestinationSet.add(qu);
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) HashSet(java.util.HashSet)

Example 55 with TreeReference

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

the class Fast2014DagImpl method triggerTriggerables.

private Set<QuickTriggerable> triggerTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeReference ref, boolean midSurvey, Set<QuickTriggerable> alreadyEvaluated) {
    // turn unambiguous ref into a generic ref
    // to identify what nodes should be triggered by this
    // reference changing
    TreeReference genericRef = ref.genericize();
    // get triggerables which are activated by the generic reference
    ArrayList<QuickTriggerable> triggered = triggerIndex.get(genericRef);
    if (triggered == null) {
        return alreadyEvaluated;
    }
    Set<QuickTriggerable> triggeredCopy = new HashSet<QuickTriggerable>(triggered);
    // Evaluate all of the triggerables in our new set
    return evaluateTriggerables(mainInstance, evalContext, triggeredCopy, ref, midSurvey, alreadyEvaluated);
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) HashSet(java.util.HashSet)

Aggregations

TreeReference (org.javarosa.core.model.instance.TreeReference)85 ArrayList (java.util.ArrayList)30 TreeElement (org.javarosa.core.model.instance.TreeElement)29 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)16 Constraint (org.javarosa.core.model.condition.Constraint)12 HashSet (java.util.HashSet)11 Test (org.junit.Test)9 FormInstance (org.javarosa.core.model.instance.FormInstance)8 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)7 IFormElement (org.javarosa.core.model.IFormElement)6 Condition (org.javarosa.core.model.condition.Condition)6 IAnswerData (org.javarosa.core.model.data.IAnswerData)6 InstanceInitializationFactory (org.javarosa.core.model.instance.InstanceInitializationFactory)6 GroupDef (org.javarosa.core.model.GroupDef)5 XPathReference (org.javarosa.model.xform.XPathReference)5 DataBinding (org.javarosa.core.model.DataBinding)4 IDataReference (org.javarosa.core.model.IDataReference)4 DataInstance (org.javarosa.core.model.instance.DataInstance)4 EvaluationResult (org.javarosa.debug.EvaluationResult)4 XPathException (org.javarosa.xpath.XPathException)4