use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormInstanceParser method verifyControlBindings.
private void verifyControlBindings(IFormElement fe, FormInstance instance, List<String> errors) {
// throws XmlPullParserException {
if (fe.getChildren() == null)
return;
for (int i = 0; i < fe.getChildren().size(); i++) {
IFormElement child = fe.getChildren().get(i);
IDataReference ref = null;
String type = null;
if (child instanceof GroupDef) {
ref = child.getBind();
type = (((GroupDef) child).getRepeat() ? "Repeat" : "Group");
} else if (child instanceof QuestionDef) {
ref = child.getBind();
type = "Question";
}
TreeReference tref = FormInstance.unpackReference(ref);
if (child instanceof QuestionDef && tref.size() == 0) {
// group can bind to '/'; repeat can't, but that's checked above
reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Cannot bind control to '/'", null);
} else {
List<TreeReference> nodes = new EvaluationContext(instance).expandReference(tref, true);
if (nodes.size() == 0) {
String error = type + " bound to non-existent node: [" + tref.toString() + "]";
reporter.error(error);
errors.add(error);
}
// we can't check whether questions map to the right kind of node ('data' node vs. 'sub-tree' node) as that depends
// on the question's data type, which we don't know yet
}
verifyControlBindings(child, instance, errors);
}
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormInstanceParser method applyInstanceProperties.
private void applyInstanceProperties(FormInstance instance) {
for (DataBinding bind : bindings) {
final TreeReference ref = FormInstance.unpackReference(bind.getReference());
final List<TreeReference> nodes = new EvaluationContext(instance).expandReference(ref, true);
if (nodes.size() > 0) {
attachBindGeneral(bind);
}
for (TreeReference nref : nodes) {
attachBind(instance.resolveReference(nref), bind);
}
}
applyControlProperties(instance);
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class XPathFuncExpr method indexedRepeat.
/**
* This provides a method of indexing fields stored in prior repeat groups.
*
* args[0] = generic XPath expression to index
* args[1] = generic XPath expression for group to index
* args[2] = index number for group
* args[3] = generic XPath expression for add'l group to index (if 5 or 7 parameters passed)
* args[4] = index number for group (if 5 or 7 parameters passed)
* args[5] = generic XPath expression for add'l group to index (if 7 parameters passed)
* args[6] = index number for group (if 7 parameters passed)
*
* @param model
* @param ec
* @param args
* @param argVals
* @return
*/
public static Object indexedRepeat(DataInstance model, EvaluationContext ec, XPathExpression[] args, Object[] argVals) throws XPathTypeMismatchException {
// initialize target and context references
if (!(args[0] instanceof XPathPathExpr)) {
throw new XPathTypeMismatchException("indexed-repeat(): first parameter must be XPath field reference");
}
XPathPathExpr targetPath = (XPathPathExpr) args[0];
TreeReference targetRef = targetPath.getReference();
TreeReference contextRef = targetRef.clone();
// process passed index(es)
for (int pathargi = 1, idxargi = 2; idxargi < args.length; pathargi += 2, idxargi += 2) {
// confirm that we were passed an XPath
if (!(args[pathargi] instanceof XPathPathExpr)) {
throw new XPathTypeMismatchException("indexed-repeat(): parameter " + (pathargi + 1) + " must be XPath repeat-group reference");
}
// confirm that the passed XPath is a parent of our overall target path
TreeReference groupRef = ((XPathPathExpr) args[pathargi]).getReference();
if (!groupRef.isParentOf(targetRef, true)) {
throw new XPathTypeMismatchException("indexed-repeat(): parameter " + (pathargi + 1) + " must be a parent of the field in parameter 1");
}
// process index (if valid)
int groupIdx = toInt(args[idxargi].eval(model, ec)).intValue();
if (groupIdx <= 0) {
/*
Don't allow invalid index otherwise an exception will be thrown later by XPathNodeset#unpack().
This may happen if referenced node hadn't gotten a value yet but the calculation was fired. For example when adding a new repeat.
*/
groupIdx = 1;
}
contextRef.setMultiplicity(groupRef.size() - 1, groupIdx - 1);
}
// evaluate and return the XPath expression, in context
EvaluationContext revisedec = new EvaluationContext(ec, contextRef);
return (targetPath.eval(model, revisedec));
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormEntryPrompt method getAnswerValue.
// note: code overlap with FormDef.copyItemsetAnswer
public IAnswerData getAnswerValue() {
QuestionDef q = getQuestion();
ItemsetBinding itemset = q.getDynamicChoices();
if (itemset != null) {
if (itemset.valueRef != null) {
List<SelectChoice> choices = getSelectChoices();
List<String> preselectedValues = new ArrayList<String>();
// determine which selections are already present in the answer
if (itemset.copyMode) {
TreeReference destRef = itemset.getDestRef().contextualize(mTreeElement.getRef());
List<TreeReference> subNodes = form.getEvaluationContext().expandReference(destRef);
for (int i = 0; i < subNodes.size(); i++) {
TreeElement node = form.getMainInstance().resolveReference(subNodes.get(i));
String value = itemset.getRelativeValue().evalReadable(form.getMainInstance(), new EvaluationContext(form.getEvaluationContext(), node.getRef()));
preselectedValues.add(value);
}
} else {
List<Selection> sels;
IAnswerData data = mTreeElement.getValue();
if (data instanceof SelectMultiData) {
sels = (List<Selection>) data.getValue();
} else if (data instanceof SelectOneData) {
sels = new ArrayList<Selection>(1);
sels.add((Selection) data.getValue());
} else {
sels = new ArrayList<Selection>(0);
}
for (int i = 0; i < sels.size(); i++) {
preselectedValues.add(sels.get(i).xmlValue);
}
}
// populate 'selection' with the corresponding choices (matching 'value') from the dynamic choiceset
List<Selection> selection = new ArrayList<Selection>();
for (int i = 0; i < preselectedValues.size(); i++) {
String value = preselectedValues.get(i);
SelectChoice choice = null;
for (int j = 0; j < choices.size(); j++) {
SelectChoice ch = choices.get(j);
if (value.equals(ch.getValue())) {
choice = ch;
break;
}
}
// will no longer be an option this go around
if (choice != null) {
selection.add(choice.selection());
}
}
// convert to IAnswerData
if (selection.size() == 0) {
return null;
} else if (q.getControlType() == Constants.CONTROL_SELECT_MULTI) {
return new SelectMultiData(selection);
} else if (q.getControlType() == Constants.CONTROL_SELECT_ONE) {
// do something if more than one selected?
return new SelectOneData(selection.get(0));
} else {
throw new RuntimeException("can't happen");
}
} else {
// cannot map up selections without <value>
return null;
}
} else {
// static choices
return mTreeElement.getValue();
}
}
use of org.javarosa.core.model.condition.EvaluationContext in project javarosa by opendatakit.
the class FormEntryPrompt method getConstraintText.
public String getConstraintText(String textForm, IAnswerData attemptedValue) {
if (mTreeElement.getConstraint() == null) {
return null;
} else {
EvaluationContext ec = new EvaluationContext(form.getEvaluationContext(), mTreeElement.getRef());
if (textForm != null) {
ec.setOutputTextForm(textForm);
}
if (attemptedValue != null) {
ec.isConstraint = true;
ec.candidateValue = attemptedValue;
}
String constraintMessage = mTreeElement.getConstraint().getConstraintMessage(ec, form.getMainInstance(), textForm);
return substituteStringArgs(constraintMessage);
}
}
Aggregations