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;
}
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);
}
}
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);
}
}
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);
}
}
}
}
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));
}
}
Aggregations