Search in sources :

Example 66 with TreeReference

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

the class LatestDagBase method doEvaluateTriggerables.

protected Set<QuickTriggerable> doEvaluateTriggerables(FormInstance mainInstance, EvaluationContext evalContext, Set<QuickTriggerable> tv, TreeReference anchorRef, Set<QuickTriggerable> alreadyEvaluated) {
    // tv should now contain all of the triggerable components which are
    // going
    // to need to be addressed
    // by this update.
    // 'triggerables' is topologically-ordered by dependencies, so evaluate
    // the triggerables in 'tv'
    // in the order they appear in 'triggerables'
    Set<QuickTriggerable> fired = new HashSet<QuickTriggerable>();
    Map<TreeReference, List<TreeReference>> firedAnchors = new LinkedHashMap<TreeReference, List<TreeReference>>();
    for (QuickTriggerable qt : triggerablesDAG) {
        if (tv.contains(qt) && !alreadyEvaluated.contains(qt)) {
            List<TreeReference> affectedTriggers = qt.t.findAffectedTriggers(firedAnchors);
            if (affectedTriggers.isEmpty()) {
                affectedTriggers.add(anchorRef);
            }
            List<EvaluationResult> evaluationResults = evaluateTriggerable(mainInstance, evalContext, qt, affectedTriggers);
            if (evaluationResults.size() > 0) {
                fired.add(qt);
                for (EvaluationResult evaluationResult : evaluationResults) {
                    TreeReference affectedRef = evaluationResult.getAffectedRef();
                    TreeReference key = affectedRef.genericize();
                    List<TreeReference> values = firedAnchors.get(key);
                    if (values == null) {
                        values = new ArrayList<TreeReference>();
                        firedAnchors.put(key, values);
                    }
                    values.add(affectedRef);
                }
            }
            fired.add(qt);
        }
    }
    return fired;
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) List(java.util.List) ArrayList(java.util.ArrayList) EvaluationResult(org.javarosa.debug.EvaluationResult) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap)

Example 67 with TreeReference

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

the class LatestDagBase method evaluateTriggerable.

/**
 * Step 3 in DAG cascade. evaluate the individual triggerable expressions
 * against the anchor (the value that changed which triggered recomputation)
 *
 * @param qt
 *            The triggerable to be updated
 * @param anchorRefs
 */
private List<EvaluationResult> evaluateTriggerable(FormInstance mainInstance, EvaluationContext evalContext, QuickTriggerable qt, List<TreeReference> anchorRefs) {
    List<EvaluationResult> evaluationResults = new ArrayList<EvaluationResult>(0);
    // Contextualize the reference used by the triggerable against the
    // anchor
    Set<TreeReference> updatedContextRef = new HashSet<TreeReference>();
    for (TreeReference anchorRef : anchorRefs) {
        TreeReference contextRef = qt.t.contextualizeContextRef(anchorRef);
        if (updatedContextRef.contains(contextRef)) {
            continue;
        }
        try {
            // Now identify all of the fully qualified nodes which this
            // triggerable
            // updates. (Multiple nodes can be updated by the same trigger)
            List<TreeReference> qualifiedList = evalContext.expandReference(contextRef);
            // Go through each one and evaluate the trigger expression
            for (TreeReference qualified : qualifiedList) {
                EvaluationContext ec = new EvaluationContext(evalContext, qualified);
                evaluationResults.addAll(qt.t.apply(mainInstance, ec, qualified));
            }
            boolean fired = evaluationResults.size() > 0;
            if (fired) {
                accessor.getEventNotifier().publishEvent(new Event(qt.t.getClass().getSimpleName(), evaluationResults));
            }
            updatedContextRef.add(contextRef);
        } catch (Exception e) {
            throw new RuntimeException("Error evaluating field '" + contextRef.getNameLast() + "': " + e.getMessage(), e);
        }
    }
    return evaluationResults;
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) ArrayList(java.util.ArrayList) Event(org.javarosa.debug.Event) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) EvaluationResult(org.javarosa.debug.EvaluationResult) HashSet(java.util.HashSet)

Example 68 with TreeReference

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

the class Safe2014DagImpl method evaluateChildrenTriggerables.

private void evaluateChildrenTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeElement newNode, boolean createdOrDeleted, 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, alreadyEvaluated);
        publishSummary((createdOrDeleted ? "Created" : "Deleted"), anchorRef, childTriggerables);
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference)

Example 69 with TreeReference

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

the class Safe2014DagImpl 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
    // 
    ArrayList<QuickTriggerable> vertices = new ArrayList<QuickTriggerable>(unorderedTriggerables);
    triggerablesDAG.clear();
    ArrayList<QuickTriggerable[]> partialOrdering = new ArrayList<QuickTriggerable[]>();
    HashSet<QuickTriggerable> newDestinationSet = new HashSet<QuickTriggerable>();
    for (QuickTriggerable qt : vertices) {
        HashSet<QuickTriggerable> deps = new HashSet<QuickTriggerable>();
        newDestinationSet.clear();
        fillTriggeredElements(mainInstance, evalContext, qt, deps, newDestinationSet);
        // remove any self-reference if we have one...
        deps.remove(qt);
        for (QuickTriggerable qu : deps) {
            QuickTriggerable[] edge = { qt, qu };
            partialOrdering.add(edge);
        }
        // save for aggressive 2014 behavior
        qt.t.setImmediateCascades(deps);
    }
    ArrayList<QuickTriggerable> orderedRoots = new ArrayList<QuickTriggerable>();
    HashSet<QuickTriggerable> roots = new HashSet<QuickTriggerable>(vertices.size());
    int waveCount = -1;
    while (vertices.size() > 0) {
        ++waveCount;
        // 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) {
            String hints = "";
            for (QuickTriggerable qt : vertices) {
                for (TreeReference r : qt.t.getTargets()) {
                    hints += "\n" + r.toString(true);
                }
            }
            String message = "Cycle detected in form's relevant and calculation logic!";
            if (!hints.equals("")) {
                message += "\nThe following nodes are likely involved in the loop:" + hints;
            }
            throw new IllegalStateException(message);
        }
        // order the root nodes - so the order is fixed
        orderedRoots.clear();
        orderedRoots.addAll(roots);
        Collections.sort(orderedRoots, QuickTriggerable.quickTriggerablesRootOrdering);
        // add them to the triggerablesDAG.
        for (int i = 0; i < orderedRoots.size(); i++) {
            QuickTriggerable root = orderedRoots.get(i);
            root.t.setWaveCount(waveCount);
            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) ArrayList(java.util.ArrayList) TreeReference(org.javarosa.core.model.instance.TreeReference) HashSet(java.util.HashSet)

Example 70 with TreeReference

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

the class Safe2014DagImpl method addChildrenOfReference.

/**
 * This is a utility method to get all of the references of a node. It can
 * be replaced when we support dependent XPath Steps (IE: /path/to//)
 */
private void addChildrenOfReference(FormInstance mainInstance, EvaluationContext evalContext, TreeReference original, Set<TreeReference> toAdd, boolean expandRepeatables) {
    // original has already been added to the 'toAdd' list.
    TreeElement repeatTemplate = expandRepeatables ? mainInstance.getTemplatePath(original) : null;
    if (repeatTemplate != null) {
        for (int i = 0; i < repeatTemplate.getNumChildren(); ++i) {
            TreeElement child = repeatTemplate.getChildAt(i);
            toAdd.add(child.getRef().genericize());
            addChildrenOfElement(mainInstance, evalContext, child, toAdd, expandRepeatables);
        }
    } else {
        List<TreeReference> refSet = evalContext.expandReference(original);
        for (TreeReference ref : refSet) {
            addChildrenOfElement(mainInstance, evalContext, evalContext.resolveReference(ref), toAdd, expandRepeatables);
        }
    }
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) TreeElement(org.javarosa.core.model.instance.TreeElement) AbstractTreeElement(org.javarosa.core.model.instance.AbstractTreeElement)

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