use of org.javarosa.core.model.instance.TreeReference 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.instance.TreeReference 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.instance.TreeReference in project javarosa by opendatakit.
the class Fast2014DagImpl method evaluateChildrenTriggerables.
private void evaluateChildrenTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeElement newNode, boolean createdOrDeleted, boolean midSurvey, Set<QuickTriggerable> alreadyEvaluated) {
// iterate into the group children and evaluate any triggerables that
// depend one them, if they are not already calculated.
int numChildren = newNode.getNumChildren();
for (int i = 0; i < numChildren; i++) {
TreeReference anchorRef = newNode.getChildAt(i).getRef();
Set<QuickTriggerable> childTriggerables = triggerTriggerables(mainInstance, evalContext, anchorRef, midSurvey, alreadyEvaluated);
publishSummary((createdOrDeleted ? "Created" : "Deleted"), anchorRef, childTriggerables);
}
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class Fast2014DagImpl method fillTriggeredElements.
/**
* Get all of the elements which will need to be evaluated (in order) when
* the triggerable is fired.
*
* @param qt
* @param destinationSet
* where to store the triggerables
* @param midSurvey
* if true, then the slow code will execute, if false, then
* old/fast code will execute that suffers from
* https://code.google.com/p/opendatakit/issues/detail?id=888
*/
public void fillTriggeredElements(FormInstance mainInstance, EvaluationContext evalContext, QuickTriggerable qt, Set<QuickTriggerable> destinationSet, Set<QuickTriggerable> newDestinationSet, boolean midSurvey) {
if (qt.t.canCascade()) {
List<TreeReference> targets = qt.t.getTargets();
if (!midSurvey) {
for (TreeReference target : targets) {
ArrayList<QuickTriggerable> triggered = triggerIndex.get(target);
if (triggered != null) {
for (QuickTriggerable qu : triggered) {
if (!destinationSet.contains(qu)) {
destinationSet.add(qu);
newDestinationSet.add(qu);
}
}
}
}
} else {
boolean expandRepeatables = true;
for (TreeReference target : targets) {
Set<TreeReference> updatedNodes = new HashSet<TreeReference>();
updatedNodes.add(target);
// to the list of updated elements as well.
if (qt.t.isCascadingToChildren()) {
addChildrenOfReference(mainInstance, evalContext, target, updatedNodes, expandRepeatables);
}
// multiple nodes if there's a relevance cascade.
for (TreeReference ref : updatedNodes) {
// Check our index to see if that target is a Trigger
// for
// other
// conditions
// IE: if they are an element of a different calculation
// or
// relevancy calc
// We can't make this reference generic before now or
// we'll
// lose the
// target information,
// so we'll be more inclusive than needed and see if any
// of
// our
// triggers are keyed on
// the predicate-less path of this ref
ArrayList<QuickTriggerable> triggered = triggerIndex.get(ref.hasPredicates() ? ref.removePredicates() : ref);
if (triggered != null) {
// found
for (QuickTriggerable qu : triggered) {
// already
if (!destinationSet.contains(qu)) {
destinationSet.add(qu);
newDestinationSet.add(qu);
}
}
}
}
}
}
}
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class Fast2014DagImpl method triggerTriggerables.
private Set<QuickTriggerable> triggerTriggerables(FormInstance mainInstance, EvaluationContext evalContext, TreeReference ref, boolean midSurvey, Set<QuickTriggerable> alreadyEvaluated) {
// turn unambiguous ref into a generic ref
// to identify what nodes should be triggered by this
// reference changing
TreeReference genericRef = ref.genericize();
// get triggerables which are activated by the generic reference
ArrayList<QuickTriggerable> triggered = triggerIndex.get(genericRef);
if (triggered == null) {
return alreadyEvaluated;
}
Set<QuickTriggerable> triggeredCopy = new HashSet<QuickTriggerable>(triggered);
// Evaluate all of the triggerables in our new set
return evaluateTriggerables(mainInstance, evalContext, triggeredCopy, ref, midSurvey, alreadyEvaluated);
}
Aggregations