use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class XPathEvalTest method testEval.
private void testEval(String expr, FormInstance model, EvaluationContext ec, Object expected) {
XPathExpression xpe = null;
boolean exceptionExpected = (expected instanceof XPathException);
if (ec == null) {
ec = new EvaluationContext(model);
}
try {
xpe = XPathParseTool.parseXPath(expr);
} catch (XPathSyntaxException xpse) {
System.out.println("Parsing " + expr + " failed with " + xpse.toString());
}
if (xpe == null) {
fail("Null expression or syntax error");
}
try {
Object result = xpe.eval(model, ec);
if (exceptionExpected) {
fail("Expected exception, expression : " + expr);
} else if ((result instanceof Double && expected instanceof Double)) {
if (!expected.equals(result)) {
System.out.println(String.format("%s result %s differed from expected %s", expr, result, expected));
}
assertEquals((Double) expected, (Double) result, 1e-12);
} else if (result instanceof XPathNodeset && expected instanceof XPathNodeset) {
XPathNodeset expectedAsXPathNodeset = (XPathNodeset) expected;
XPathNodeset resultAsXPathNodeset = (XPathNodeset) result;
assertEquals(expectedAsXPathNodeset.size(), resultAsXPathNodeset.size());
assertEquals(expectedAsXPathNodeset.getRefAt(0), resultAsXPathNodeset.getRefAt(0));
assertEquals(expectedAsXPathNodeset.unpack(), resultAsXPathNodeset.unpack());
assertEquals(expectedAsXPathNodeset.toArgList().length, resultAsXPathNodeset.toArgList().length);
for (int i = 0; i < expectedAsXPathNodeset.toArgList().length; i++) {
assertEquals(expectedAsXPathNodeset.toArgList()[i], resultAsXPathNodeset.toArgList()[i]);
}
} else {
assertEquals(expected, result);
}
} catch (XPathException xpex) {
if (!exceptionExpected) {
fail("Unexpected exception: " + xpex);
} else if (xpex.getClass() != expected.getClass()) {
fail("Did not get expected exception type");
}
}
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormInstanceParser method createMissingTemplates.
// if repeatables have no template node, duplicate first as template
private void createMissingTemplates(FormInstance instance, List<TreeReference> missingTemplates) {
// every ref is listed after a ref that could be its parent. checkRepeatsForTemplate currently behaves this way
for (TreeReference templRef : missingTemplates) {
final TreeReference firstMatch;
// make template ref generic and choose first matching node
final TreeReference ref = templRef.clone();
for (int j = 0; j < ref.size(); j++) {
ref.setMultiplicity(j, TreeReference.INDEX_UNBOUND);
}
final List<TreeReference> nodes = new EvaluationContext(instance).expandReference(ref);
if (nodes.size() == 0) {
// binding error; not a single node matches the repeat binding; will be reported later
continue;
} else {
firstMatch = nodes.get(0);
}
try {
instance.copyNode(firstMatch, templRef);
} catch (InvalidReferenceException e) {
reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Could not create a default repeat template; this is almost certainly a homogeneity error! Your form will not work! (Failed on " + templRef.toString() + ")", null);
}
trimRepeatChildren(instance.resolveReference(templRef));
}
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormDef method resetEvaluationContext.
private void resetEvaluationContext() {
EvaluationContext ec = new EvaluationContext(null);
ec = new EvaluationContext(mainInstance, formInstances, ec);
initEvalContext(ec);
this.exprEvalContext = ec;
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormDef method evaluateConstraint.
public boolean evaluateConstraint(TreeReference ref, IAnswerData data) {
if (data == null) {
return true;
}
TreeElement node = mainInstance.resolveReference(ref);
Constraint c = node.getConstraint();
if (c == null) {
return true;
}
EvaluationContext ec = new EvaluationContext(exprEvalContext, ref);
ec.isConstraint = true;
ec.candidateValue = data;
boolean result = c.constraint.eval(mainInstance, ec);
getEventNotifier().publishEvent(new Event("Constraint", new EvaluationResult(ref, result)));
return result;
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormDef method initEvalContext.
/**
* @param ec The new Evaluation Context
*/
private void initEvalContext(EvaluationContext ec) {
if (!ec.getFunctionHandlers().containsKey("jr:itext")) {
final FormDef f = this;
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "jr:itext";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
String textID = (String) args[0];
try {
// SUUUUPER HACKY
String form = ec.getOutputTextForm();
if (form != null) {
textID = textID + ";" + form;
String result = f.getLocalizer().getRawText(f.getLocalizer().getLocale(), textID);
return result == null ? "" : result;
} else {
String text = f.getLocalizer().getText(textID);
return text == null ? "[itext:" + textID + "]" : text;
}
} catch (NoSuchElementException nsee) {
return "[nolocale]";
}
}
@Override
public List<Class[]> getPrototypes() {
Class[] proto = { String.class };
List<Class[]> v = new ArrayList<Class[]>(1);
v.add(proto);
return v;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
}
/*
* function to reverse a select value into the display label for that
* choice in the question it came from
*
* arg 1: select value arg 2: string xpath referring to origin question;
* must be absolute path
*
* this won't work at all if the original label needed to be
* processed/calculated in some way (<output>s, etc.) (is this even
* allowed?) likely won't work with multi-media labels _might_ work for
* itemsets, but probably not very well or at all; could potentially work
* better if we had some context info DOES work with localization
*
* it's mainly intended for the simple case of reversing a question with
* compile-time-static fields, for use inside an <output>
*/
if (!ec.getFunctionHandlers().containsKey("jr:choice-name")) {
final FormDef f = this;
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "jr:choice-name";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
try {
String value = (String) args[0];
String questionXpath = (String) args[1];
TreeReference ref = RestoreUtils.xfFact.ref(questionXpath);
QuestionDef q = findQuestionByRef(ref, f);
if (q == null || (q.getControlType() != Constants.CONTROL_SELECT_ONE && q.getControlType() != Constants.CONTROL_SELECT_MULTI)) {
return "";
}
// NOTE: this is highly suspect. We have no context against
// which to evaluate
// a dynamic selection list. This will generally cause that
// evaluation to break
// if any filtering is done, or, worst case, give unexpected
// results.
//
// We should hook into the existing code (FormEntryPrompt) for
// pulling
// display text for select choices. however, it's hard,
// because we don't really have
// any context to work with, and all the situations where that
// context would be used
// don't make sense for trying to reverse a select value back
// to a label in an unrelated
// expression
List<SelectChoice> choices;
ItemsetBinding itemset = q.getDynamicChoices();
if (itemset != null) {
if (itemset.getChoices() == null) {
if (ref.isAmbiguous()) {
// SurveyCTO: We need a absolute "ref" to populate the dynamic choices,
// like we do when we populate those at FormEntryPrompt (line 251).
// The "ref" here is ambiguous, so we need to make it concrete first.
ref = ref.contextualize(ec.getContextRef());
}
f.populateDynamicChoices(itemset, ref);
}
choices = itemset.getChoices();
} else {
// static choices
choices = q.getChoices();
}
if (choices != null) {
for (SelectChoice ch : choices) {
if (ch.getValue().equals(value)) {
// this is really not ideal. we should hook into the
// existing code (FormEntryPrompt) for pulling
// display text for select choices. however, it's
// hard, because we don't really have
// any context to work with, and all the situations
// where that context would be used
// don't make sense for trying to reverse a select
// value back to a label in an unrelated
// expression
String textID = ch.getTextID();
String templateStr;
if (textID != null) {
templateStr = f.getLocalizer().getText(textID);
} else {
templateStr = ch.getLabelInnerText();
}
return fillTemplateString(templateStr, ref);
}
}
}
return "";
} catch (Exception e) {
throw new WrappedException("error in evaluation of xpath function [choice-name]", e);
}
}
@Override
public List<Class[]> getPrototypes() {
Class[] proto = { String.class, String.class };
List<Class[]> v = new ArrayList<Class[]>(1);
v.add(proto);
return v;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
}
}
Aggregations