Search in sources :

Example 1 with XPathPathExpr

use of org.javarosa.xpath.expr.XPathPathExpr in project javarosa by opendatakit.

the class TreeElement method tryBatchChildFetch.

@Override
public List<TreeReference> tryBatchChildFetch(String name, int mult, List<XPathExpression> predicates, EvaluationContext evalContext) {
    // Only do for predicates
    if (mult != TreeReference.INDEX_UNBOUND || predicates == null) {
        return null;
    }
    List<Integer> toRemove = new ArrayList<Integer>();
    List<TreeReference> selectedChildren = null;
    // Lazy init these until we've determined that our predicate is hintable
    HashMap<XPathPathExpr, String> indices = null;
    List<TreeElement> kids = null;
    predicate: for (int i = 0; i < predicates.size(); ++i) {
        XPathExpression xpe = predicates.get(i);
        // something we index with something static.
        if (xpe instanceof XPathEqExpr) {
            XPathExpression left = ((XPathEqExpr) xpe).a;
            XPathExpression right = ((XPathEqExpr) xpe).b;
            // handling attribute based referencing with very reasonable timing, but it's complex otherwise)
            if (left instanceof XPathPathExpr && right instanceof XPathStringLiteral) {
                // don't want the overhead if our predicate is too complex anyway
                if (indices == null) {
                    indices = new HashMap<XPathPathExpr, String>();
                    kids = this.getChildrenWithName(name);
                    if (kids.size() == 0) {
                        return null;
                    }
                    // Anything that we're going to use across elements should be on all of them
                    TreeElement kid = kids.get(0);
                    for (int j = 0; j < kid.getAttributeCount(); ++j) {
                        String attribute = kid.getAttributeName(j);
                        indices.put(XPathReference.getPathExpr("@" + attribute), attribute);
                    }
                }
                for (XPathPathExpr expr : indices.keySet()) {
                    if (expr.equals(left)) {
                        String attributeName = indices.get(expr);
                        for (TreeElement kid : kids) {
                            if (kid.getAttributeValue(null, attributeName).equals(((XPathStringLiteral) right).s)) {
                                if (selectedChildren == null) {
                                    selectedChildren = new ArrayList<TreeReference>();
                                }
                                selectedChildren.add(kid.getRef());
                            }
                        }
                        // Note that this predicate is evaluated and doesn't need to be evaluated in the future.
                        toRemove.add(DataUtil.integer(i));
                        continue predicate;
                    }
                }
            }
        }
        // so otherwise, just get outta here.
        break;
    }
    // if we weren't able to evaluate any predicates, signal that.
    if (selectedChildren == null) {
        return null;
    }
    // otherwise, remove all of the predicates we've already evaluated
    for (int i = toRemove.size() - 1; i >= 0; i--) {
        predicates.remove(toRemove.get(i).intValue());
    }
    return selectedChildren;
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) HashMap(java.util.HashMap) XPathPathExpr(org.javarosa.xpath.expr.XPathPathExpr) ArrayList(java.util.ArrayList) Constraint(org.javarosa.core.model.condition.Constraint) XPathStringLiteral(org.javarosa.xpath.expr.XPathStringLiteral) XPathEqExpr(org.javarosa.xpath.expr.XPathEqExpr)

Example 2 with XPathPathExpr

use of org.javarosa.xpath.expr.XPathPathExpr in project javarosa by opendatakit.

the class XPathConditional method getTriggers.

private static void getTriggers(XPathExpression x, Set<TreeReference> v, TreeReference contextRef) {
    if (x instanceof XPathPathExpr) {
        TreeReference ref = ((XPathPathExpr) x).getReference();
        TreeReference contextualized = ref;
        if (contextRef != null) {
            contextualized = ref.contextualize(contextRef);
        }
        // TODO: It's possible we should just handle this the same way as "genericize". Not entirely clear.
        if (contextualized.hasPredicates()) {
            contextualized = contextualized.removePredicates();
        }
        v.add(contextualized);
        for (int i = 0; i < ref.size(); i++) {
            List<XPathExpression> predicates = ref.getPredicate(i);
            if (predicates == null) {
                continue;
            }
            // we can't generate this properly without an absolute reference
            if (!ref.isAbsolute()) {
                throw new IllegalArgumentException("can't get triggers for relative references");
            }
            TreeReference predicateContext = ref.getSubReference(i);
            for (XPathExpression predicate : predicates) {
                getTriggers(predicate, v, predicateContext);
            }
        }
    } else if (x instanceof XPathBinaryOpExpr) {
        getTriggers(((XPathBinaryOpExpr) x).a, v, contextRef);
        getTriggers(((XPathBinaryOpExpr) x).b, v, contextRef);
    } else if (x instanceof XPathUnaryOpExpr) {
        getTriggers(((XPathUnaryOpExpr) x).a, v, contextRef);
    } else if (x instanceof XPathFuncExpr) {
        XPathFuncExpr fx = (XPathFuncExpr) x;
        for (int i = 0; i < fx.args.length; i++) getTriggers(fx.args[i], v, contextRef);
    }
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) XPathPathExpr(org.javarosa.xpath.expr.XPathPathExpr) TreeReference(org.javarosa.core.model.instance.TreeReference) XPathFuncExpr(org.javarosa.xpath.expr.XPathFuncExpr) XPathBinaryOpExpr(org.javarosa.xpath.expr.XPathBinaryOpExpr) XPathUnaryOpExpr(org.javarosa.xpath.expr.XPathUnaryOpExpr)

Example 3 with XPathPathExpr

use of org.javarosa.xpath.expr.XPathPathExpr in project collect by opendatakit.

the class ExternalAppsUtils method getValueRepresentedBy.

public static Object getValueRepresentedBy(String text, TreeReference reference) throws XPathSyntaxException {
    if (text.startsWith("'")) {
        // treat this as a constant parameter but not require an ending quote
        return text.endsWith("'") ? text.substring(1, text.length() - 1) : text.substring(1);
    }
    FormDef formDef = Collect.getInstance().getFormController().getFormDef();
    FormInstance formInstance = formDef.getInstance();
    EvaluationContext evaluationContext = new EvaluationContext(formDef.getEvaluationContext(), reference);
    if (text.startsWith("/")) {
        // treat this is an xpath
        XPathPathExpr pathExpr = XPathReference.getPathExpr(text);
        XPathNodeset xpathNodeset = pathExpr.eval(formInstance, evaluationContext);
        return XPathFuncExpr.unpack(xpathNodeset);
    } else if (text.equals("instanceProviderID()")) {
        // instanceProviderID returns -1 if the current instance has not been saved to disk already
        String path = Collect.getInstance().getFormController().getInstanceFile().getAbsolutePath();
        String instanceProviderID = "-1";
        Instance instance = new InstancesRepositoryProvider(Collect.getInstance()).get().getOneByPath(path);
        if (instance != null) {
            instanceProviderID = instance.getDbId().toString();
        }
        return instanceProviderID;
    } else {
        // treat this as a function
        XPathExpression xpathExpression = XPathParseTool.parseXPath(text);
        return xpathExpression.eval(formInstance, evaluationContext);
    }
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) InstancesRepositoryProvider(org.odk.collect.android.utilities.InstancesRepositoryProvider) FormInstance(org.javarosa.core.model.instance.FormInstance) Instance(org.odk.collect.forms.instances.Instance) FormDef(org.javarosa.core.model.FormDef) XPathPathExpr(org.javarosa.xpath.expr.XPathPathExpr) XPathNodeset(org.javarosa.xpath.XPathNodeset) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) FormInstance(org.javarosa.core.model.instance.FormInstance)

Example 4 with XPathPathExpr

use of org.javarosa.xpath.expr.XPathPathExpr in project collect by opendatakit.

the class ExternalAppsUtils method populateParameters.

public static void populateParameters(Intent intent, Map<String, String> exParams, TreeReference reference) throws ExternalParamsException {
    FormDef formDef = Collect.getInstance().getFormController().getFormDef();
    FormInstance formInstance = formDef.getInstance();
    EvaluationContext evaluationContext = new EvaluationContext(formDef.getEvaluationContext(), reference);
    if (exParams != null) {
        for (Map.Entry<String, String> paramEntry : exParams.entrySet()) {
            String paramEntryValue = paramEntry.getValue();
            try {
                Object result;
                if (paramEntryValue.startsWith("'")) {
                    // but not require an ending quote
                    if (paramEntryValue.endsWith("'")) {
                        result = paramEntryValue.substring(1, paramEntryValue.length() - 1);
                    } else {
                        result = paramEntryValue.substring(1, paramEntryValue.length());
                    }
                } else if (paramEntryValue.startsWith("/")) {
                    // treat this is an xpath
                    XPathPathExpr pathExpr = XPathReference.getPathExpr(paramEntryValue);
                    XPathNodeset xpathNodeset = pathExpr.eval(formInstance, evaluationContext);
                    result = XPathFuncExpr.unpack(xpathNodeset);
                } else if (paramEntryValue.equals("instanceProviderID()")) {
                    // instanceProviderID returns -1 if the current instance has not been
                    // saved to disk already
                    String path = Collect.getInstance().getFormController().getInstanceFile().getAbsolutePath();
                    String instanceProviderID = "-1";
                    Cursor c = new InstancesDao().getInstancesCursorForFilePath(path);
                    if (c != null && c.getCount() > 0) {
                        // should only ever be one
                        c.moveToFirst();
                        instanceProviderID = c.getString(c.getColumnIndex(InstanceColumns._ID));
                    }
                    if (c != null) {
                        c.close();
                    }
                    result = instanceProviderID;
                } else {
                    // treat this is a function
                    XPathExpression xpathExpression = XPathParseTool.parseXPath(paramEntryValue);
                    result = xpathExpression.eval(formInstance, evaluationContext);
                }
                if (result != null && result instanceof Serializable) {
                    intent.putExtra(paramEntry.getKey(), (Serializable) result);
                }
            } catch (Exception e) {
                throw new ExternalParamsException("Could not evaluate '" + paramEntryValue + "'", e);
            }
        }
    }
}
Also used : XPathExpression(org.javarosa.xpath.expr.XPathExpression) Serializable(java.io.Serializable) XPathPathExpr(org.javarosa.xpath.expr.XPathPathExpr) Cursor(android.database.Cursor) ExternalParamsException(org.odk.collect.android.exception.ExternalParamsException) ExternalParamsException(org.odk.collect.android.exception.ExternalParamsException) InstancesDao(org.odk.collect.android.dao.InstancesDao) FormDef(org.javarosa.core.model.FormDef) XPathNodeset(org.javarosa.xpath.XPathNodeset) EvaluationContext(org.javarosa.core.model.condition.EvaluationContext) FormInstance(org.javarosa.core.model.instance.FormInstance) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 5 with XPathPathExpr

use of org.javarosa.xpath.expr.XPathPathExpr 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)

Aggregations

XPathPathExpr (org.javarosa.xpath.expr.XPathPathExpr)8 XPathExpression (org.javarosa.xpath.expr.XPathExpression)6 FormDef (org.javarosa.core.model.FormDef)3 EvaluationContext (org.javarosa.core.model.condition.EvaluationContext)3 ArrayList (java.util.ArrayList)2 AbstractTreeElement (org.javarosa.core.model.instance.AbstractTreeElement)2 FormInstance (org.javarosa.core.model.instance.FormInstance)2 TreeReference (org.javarosa.core.model.instance.TreeReference)2 XPathNodeset (org.javarosa.xpath.XPathNodeset)2 Cursor (android.database.Cursor)1 Serializable (java.io.Serializable)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 Vector (java.util.Vector)1 IFormElement (org.javarosa.core.model.IFormElement)1 ItemsetBinding (org.javarosa.core.model.ItemsetBinding)1 Constraint (org.javarosa.core.model.condition.Constraint)1 DataInstance (org.javarosa.core.model.instance.DataInstance)1 TreeElement (org.javarosa.core.model.instance.TreeElement)1