Search in sources :

Example 16 with TreeReference

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

the class XPathPathExpr method getReference.

/**
 * translate an xpath path reference into a TreeReference
 * TreeReferences only support a subset of true xpath paths; restrictions are:
 *   simple child name tests 'child::name', '.', and '..' allowed only
 *   no predicates
 *   all '..' steps must come before anything else
 */
public TreeReference getReference(boolean allowPredicates) throws XPathUnsupportedException {
    TreeReference ref = new TreeReference();
    boolean parentsAllowed;
    switch(init_context) {
        case XPathPathExpr.INIT_CONTEXT_ROOT:
            ref.setRefLevel(TreeReference.REF_ABSOLUTE);
            parentsAllowed = false;
            break;
        case XPathPathExpr.INIT_CONTEXT_RELATIVE:
            ref.setRefLevel(0);
            parentsAllowed = true;
            break;
        case XPathPathExpr.INIT_CONTEXT_EXPR:
            if (this.filtExpr.x != null && this.filtExpr.x instanceof XPathFuncExpr) {
                XPathFuncExpr func = (XPathFuncExpr) (this.filtExpr.x);
                if (func.id.toString().equals("instance")) {
                    // i assume when refering the non main instance you have to be absolute
                    ref.setRefLevel(TreeReference.REF_ABSOLUTE);
                    parentsAllowed = false;
                    if (func.args.length != 1) {
                        throw new XPathUnsupportedException("instance() function used with " + func.args.length + " arguements. Expecting 1 arguement");
                    }
                    if (!(func.args[0] instanceof XPathStringLiteral)) {
                        throw new XPathUnsupportedException("instance() function expecting 1 string literal arguement arguement");
                    }
                    XPathStringLiteral strLit = (XPathStringLiteral) (func.args[0]);
                    // we've got a non-standard instance in play, watch out
                    if (strLit.s == null) {
                        // absolute reference to the main instance
                        ref.setContext(TreeReference.CONTEXT_ABSOLUTE);
                        ref.setInstanceName(null);
                    } else {
                        ref.setContext(TreeReference.CONTEXT_INSTANCE);
                        ref.setInstanceName(strLit.s);
                    }
                } else if (func.id.toString().equals("current")) {
                    parentsAllowed = true;
                    ref.setContext(TreeReference.CONTEXT_ORIGINAL);
                } else {
                    // We only support expression root contexts for instance refs, everything else is an illegal filter
                    throw new XPathUnsupportedException("filter expression");
                }
            } else {
                // We only support expression root contexts for instance refs, everything else is an illegal filter
                throw new XPathUnsupportedException("filter expression");
            }
            break;
        default:
            throw new XPathUnsupportedException("filter expression");
    }
    for (int i = 0; i < steps.length; i++) {
        XPathStep step = steps[i];
        if (step.axis == XPathStep.AXIS_SELF) {
            if (step.test != XPathStep.TEST_TYPE_NODE) {
                throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
            }
        } else if (step.axis == XPathStep.AXIS_PARENT) {
            if (!parentsAllowed || step.test != XPathStep.TEST_TYPE_NODE) {
                throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
            } else {
                ref.incrementRefLevel();
            }
        } else if (step.axis == XPathStep.AXIS_ATTRIBUTE) {
            if (step.test == XPathStep.TEST_NAME) {
                ref.add(step.name.toString(), TreeReference.INDEX_ATTRIBUTE);
                parentsAllowed = false;
            // TODO: Can you step back from an attribute, or should this always be
            // the last step?
            } else {
                throw new XPathUnsupportedException("attribute step other than 'attribute::name");
            }
        } else if (step.axis == XPathStep.AXIS_CHILD) {
            if (step.test == XPathStep.TEST_NAME) {
                ref.add(step.name.toString(), TreeReference.INDEX_UNBOUND);
                parentsAllowed = true;
            } else if (step.test == XPathStep.TEST_NAME_WILDCARD) {
                ref.add(TreeReference.NAME_WILDCARD, TreeReference.INDEX_UNBOUND);
                parentsAllowed = true;
            } else {
                throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
            }
        } else {
            throw new XPathUnsupportedException("step other than 'child::name', '.', '..'");
        }
        if (step.predicates.length > 0) {
            int refLevel = ref.getRefLevel();
            List<XPathExpression> v = new ArrayList<XPathExpression>(step.predicates.length);
            for (int j = 0; j < step.predicates.length; j++) {
                v.add(step.predicates[j]);
            }
            ref.addPredicate(i, v);
        }
    }
    return ref;
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) ArrayList(java.util.ArrayList) XPathUnsupportedException(org.javarosa.xpath.XPathUnsupportedException)

Example 17 with TreeReference

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

the class Fast2014DagImpl method copyItemsetAnswer.

@Override
public void copyItemsetAnswer(FormInstance mainInstance, EvaluationContext evalContext, TreeReference copyRef, TreeElement copyToElement, boolean midSurvey) {
    TreeReference targetRef = copyToElement.getRef();
    Set<QuickTriggerable> qtSet1 = triggerTriggerables(mainInstance, evalContext, copyRef, midSurvey, // trigger conditions that
    new HashSet<QuickTriggerable>(0));
    // depend on the creation of
    // these new nodes
    publishSummary("Copied itemset answer (phase 1)", targetRef, qtSet1);
    Set<QuickTriggerable> qtSet2 = initializeTriggerables(mainInstance, evalContext, copyRef, midSurvey, // initialize conditions for
    new HashSet<QuickTriggerable>(0));
    // the node (and sub-nodes)
    publishSummary("Copied itemset answer (phase 2)", targetRef, qtSet2);
// not 100% sure this will work since destRef is ambiguous as the last
// step, but i think it's supposed to work
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference)

Example 18 with TreeReference

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

the class Fast2014DagImpl 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> deps = new HashSet<QuickTriggerable>();
    HashSet<QuickTriggerable> newDestinationSet = new HashSet<QuickTriggerable>();
    for (QuickTriggerable qt : vertices) {
        deps.clear();
        newDestinationSet.clear();
        fillTriggeredElements(mainInstance, evalContext, qt, deps, newDestinationSet, true);
        // 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 - mainly for clean textual diffs when
        // printing
        // When this code is rewritten to use HashSet, this will become
        // important.
        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 19 with TreeReference

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

the class Fast2014DagImpl method initializeTriggerables.

private Set<QuickTriggerable> initializeTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeReference rootRef, boolean midSurvey, Set<QuickTriggerable> alreadyEvaluated) {
    TreeReference genericRoot = rootRef.genericize();
    Set<QuickTriggerable> applicable = new HashSet<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, midSurvey, alreadyEvaluated);
}
Also used : TreeReference(org.javarosa.core.model.instance.TreeReference) HashSet(java.util.HashSet)

Example 20 with TreeReference

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

the class Fast2014DagImpl 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//)
 */
public 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