Search in sources :

Example 61 with TreeReference

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

the class IDag method getConditionExpressionForTrueAction.

/**
 * Pull this in from FormOverview so that we can make fields private.
 *
 * @param instanceNode
 * @param action
 * @return
 */
public final IConditionExpr getConditionExpressionForTrueAction(FormInstance mainInstance, TreeElement instanceNode, int action) {
    IConditionExpr expr = null;
    for (int i = 0; i < triggerablesDAG.size() && expr == null; i++) {
        // Clayton Sims - Jun 1, 2009 : Not sure how legitimate this
        // cast is. It might work now, but break later.
        // Clayton Sims - Jun 24, 2009 : Yeah, that change broke things.
        // For now, we won't bother to print out anything that isn't
        // a condition.
        QuickTriggerable qt = triggerablesDAG.get(i);
        if (qt.t instanceof Condition) {
            Condition c = (Condition) qt.t;
            if (c.trueAction == action) {
                List<TreeReference> targets = c.getTargets();
                for (int j = 0; j < targets.size() && expr == null; j++) {
                    TreeReference target = targets.get(j);
                    TreeReference tr = (TreeReference) (new XPathReference(target)).getReference();
                    TreeElement element = mainInstance.getTemplatePath(tr);
                    if (instanceNode == element) {
                        expr = c.getExpr();
                    }
                }
            }
        }
    }
    return expr;
}
Also used : Condition(org.javarosa.core.model.condition.Condition) IConditionExpr(org.javarosa.core.model.condition.IConditionExpr) TreeReference(org.javarosa.core.model.instance.TreeReference) XPathReference(org.javarosa.model.xform.XPathReference) TreeElement(org.javarosa.core.model.instance.TreeElement)

Example 62 with TreeReference

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

the class IDag method addTriggerable.

/**
 * Add the triggerables to the dataset prior to finalizing.
 *
 * @param t
 */
public final Triggerable addTriggerable(Triggerable t) {
    QuickTriggerable qt = findTriggerable(t);
    if (qt != null) {
        // one node may control access to many nodes; this means many nodes
        // effectively have the same condition
        // let's identify when conditions are the same, and store and calculate
        // it only once
        // nov-2-2011: ctsims - We need to merge the context nodes together
        // whenever we do this (finding the highest
        // common ground between the two), otherwise we can end up failing to
        // trigger when the ignored context
        // exists and the used one doesn't
        Triggerable existingTriggerable = qt.t;
        existingTriggerable.changeContextRefToIntersectWithTriggerable(t);
        return existingTriggerable;
    // note, if the contextRef is unnecessarily deep, the condition will be
    // evaluated more times than needed
    // perhaps detect when 'identical' condition has a shorter contextRef,
    // and use that one instead?
    } else {
        qt = new QuickTriggerable(t);
        unorderedTriggerables.add(qt);
        Set<TreeReference> triggers = t.getTriggers();
        for (TreeReference trigger : triggers) {
            ArrayList<QuickTriggerable> triggered = triggerIndex.get(trigger);
            if (triggered == null) {
                triggered = new ArrayList<QuickTriggerable>();
                triggerIndex.put(trigger.clone(), triggered);
            }
            if (!triggered.contains(qt)) {
                triggered.add(qt);
            }
        }
        return t;
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) Triggerable(org.javarosa.core.model.condition.Triggerable)

Example 63 with TreeReference

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

the class LegacyDagImpl method initializeTriggerables.

/**
 * Walks the current set of conditions, and evaluates each of them with the
 * current context.
 */
@Override
public Collection<QuickTriggerable> initializeTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeReference rootRef, boolean midSurvey) {
    TreeReference genericRoot = rootRef.genericize();
    ArrayList<QuickTriggerable> applicable = new ArrayList<QuickTriggerable>();
    for (int i = 0; i < triggerablesDAG.size(); i++) {
        QuickTriggerable qt = triggerablesDAG.get(i);
        for (int j = 0; j < qt.t.getTargets().size(); j++) {
            TreeReference target = qt.t.getTargets().get(j);
            if (genericRoot.isParentOf(target, false)) {
                applicable.add(qt);
                break;
            }
        }
    }
    return evaluateTriggerables(mainInstance, evalContext, applicable, rootRef);
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) ArrayList(java.util.ArrayList)

Example 64 with TreeReference

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

the class LegacyDagImpl method evaluateTriggerables.

/**
 * Step 2 in evaluating DAG computation updates from a value being changed
 * in the instance. This step is responsible for taking the root set of
 * directly triggered conditions, identifying which conditions should
 * further be triggered due to their update, and then dispatching all of the
 * evaluations.
 *  @param tv
 *            A list of all of the trigerrables directly triggered by the
 *            value changed
 * @param anchorRef
 */
private List<QuickTriggerable> evaluateTriggerables(FormInstance mainInstance, EvaluationContext evalContext, ArrayList<QuickTriggerable> tv, TreeReference anchorRef) {
    // add all cascaded triggerables to queue
    for (int i = 0; i < tv.size(); i++) {
        QuickTriggerable qt = tv.get(i);
        if (qt.t.canCascade()) {
            for (int j = 0; j < qt.t.getTargets().size(); j++) {
                TreeReference target = qt.t.getTargets().get(j);
                ArrayList<QuickTriggerable> triggered = triggerIndex.get(target);
                if (triggered != null) {
                    for (int k = 0; k < triggered.size(); k++) {
                        QuickTriggerable qu = triggered.get(k);
                        if (!tv.contains(qu))
                            tv.add(qu);
                    }
                }
            }
        }
    }
    // in the order they appear in 'triggerables'
    for (int i = 0; i < triggerablesDAG.size(); i++) {
        QuickTriggerable qt = triggerablesDAG.get(i);
        if (tv.contains(qt)) {
            evaluateTriggerable(mainInstance, evalContext, qt, anchorRef);
        }
    }
    return tv;
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference)

Example 65 with TreeReference

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

the class LegacyDagImpl method finalizeTriggerables.

/**
 * Finalize the DAG associated with the form's triggered conditions. This
 * will create the appropriate ordering and dependencies to ensure the
 * conditions will be evaluated in the appropriate orders.
 *
 * @throws IllegalStateException
 *             - If the trigger ordering contains an illegal cycle and the
 *             triggers can't be laid out appropriately
 */
@Override
public void finalizeTriggerables(FormInstance mainInstance, EvaluationContext evalContext) throws IllegalStateException {
    // 
    // DAGify the triggerables based on dependencies and sort them so that
    // triggerables come only after the triggerables they depend on
    // 
    triggerablesDAG.clear();
    // 
    // DAGify the triggerables based on dependencies and sort them so that
    // trigbles come only after the trigbles they depend on
    // 
    ArrayList<QuickTriggerable[]> partialOrdering = new ArrayList<QuickTriggerable[]>();
    for (int i = 0; i < unorderedTriggerables.size(); i++) {
        QuickTriggerable qt = unorderedTriggerables.get(i);
        Triggerable t = qt.t;
        ArrayList<QuickTriggerable> deps = new ArrayList<QuickTriggerable>();
        if (t.canCascade()) {
            for (int j = 0; j < t.getTargets().size(); j++) {
                TreeReference target = t.getTargets().get(j);
                ArrayList<QuickTriggerable> triggered = triggerIndex.get(target);
                if (triggered != null) {
                    for (int k = 0; k < triggered.size(); k++) {
                        QuickTriggerable qu = triggered.get(k);
                        if (!deps.contains(qu))
                            deps.add(qu);
                    }
                }
            }
        }
        for (int j = 0; j < deps.size(); j++) {
            QuickTriggerable qu = deps.get(j);
            QuickTriggerable[] edge = { qt, qu };
            partialOrdering.add(edge);
        }
    }
    ArrayList<QuickTriggerable> vertices = new ArrayList<QuickTriggerable>(unorderedTriggerables);
    ArrayList<QuickTriggerable> roots = new ArrayList<QuickTriggerable>(unorderedTriggerables.size());
    while (vertices.size() > 0) {
        // determine root nodes
        roots.clear();
        roots.addAll(vertices);
        for (int i = 0; i < partialOrdering.size(); i++) {
            QuickTriggerable[] edge = partialOrdering.get(i);
            roots.remove(edge[1]);
        }
        // if no root nodes while graph still has nodes, graph has cycles
        if (roots.size() == 0) {
            throw new RuntimeException("Cannot create partial ordering of triggerables due to dependency cycle. Why wasn't this caught during parsing?");
        }
        // remove root nodes and edges originating from them
        for (int i = 0; i < roots.size(); i++) {
            QuickTriggerable root = roots.get(i);
            triggerablesDAG.add(root);
            vertices.remove(root);
        }
        for (int i = partialOrdering.size() - 1; i >= 0; i--) {
            QuickTriggerable[] edge = partialOrdering.get(i);
            if (roots.contains(edge[0]))
                partialOrdering.remove(i);
        }
    }
    // 
    // build the condition index for repeatable nodes
    // 
    conditionRepeatTargetIndex.clear();
    for (QuickTriggerable qt : triggerablesDAG) {
        if (qt.t instanceof Condition) {
            List<TreeReference> targets = qt.t.getTargets();
            for (TreeReference target : targets) {
                if (mainInstance.getTemplate(target) != null) {
                    conditionRepeatTargetIndex.put(target, qt);
                }
            }
        }
    }
// printTriggerables();
}
Also used : Condition(org.javarosa.core.model.condition.Condition) TreeReference(org.javarosa.core.model.instance.TreeReference) ArrayList(java.util.ArrayList) Triggerable(org.javarosa.core.model.condition.Triggerable)

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