use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method copyItemsetAnswer.
public void copyItemsetAnswer(QuestionDef q, TreeElement targetNode, IAnswerData data, boolean midSurvey) throws InvalidReferenceException {
ItemsetBinding itemset = q.getDynamicChoices();
TreeReference targetRef = targetNode.getRef();
TreeReference destRef = itemset.getDestRef().contextualize(targetRef);
List<Selection> selections = null;
if (data instanceof SelectMultiData) {
selections = (List<Selection>) data.getValue();
} else if (data instanceof SelectOneData) {
selections = new ArrayList<Selection>(1);
selections.add((Selection) data.getValue());
}
List<String> selectedValues;
if (itemset.valueRef != null) {
selectedValues = new ArrayList<String>(selections.size());
for (Selection selection : selections) {
selectedValues.add(selection.choice.getValue());
}
} else {
selectedValues = new ArrayList<String>(0);
}
// delete existing dest nodes that are not in the answer selection
HashMap<String, TreeElement> existingValues = new HashMap<String, TreeElement>();
List<TreeReference> existingNodes = exprEvalContext.expandReference(destRef);
for (TreeReference existingNode : existingNodes) {
TreeElement node = getMainInstance().resolveReference(existingNode);
if (itemset.valueRef != null) {
String value = itemset.getRelativeValue().evalReadable(this.getMainInstance(), new EvaluationContext(exprEvalContext, node.getRef()));
if (selectedValues.contains(value)) {
// cache node if in selection
existingValues.put(value, node);
// and already exists
}
}
// delete from target
targetNode.removeChild(node);
}
// copy in nodes for new answer; preserve ordering in answer
for (int i = 0; i < selections.size(); i++) {
Selection s = selections.get(i);
SelectChoice ch = s.choice;
TreeElement cachedNode = null;
if (itemset.valueRef != null) {
String value = ch.getValue();
if (existingValues.containsKey(value)) {
cachedNode = existingValues.get(value);
}
}
if (cachedNode != null) {
cachedNode.setMult(i);
targetNode.addChild(cachedNode);
} else {
getMainInstance().copyItemsetNode(ch.copyNode, destRef, this);
}
}
dagImpl.copyItemsetAnswer(getMainInstance(), getEvaluationContext(), destRef, targetNode, midSurvey);
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method findQuestionByRef.
public static QuestionDef findQuestionByRef(TreeReference ref, IFormElement fe) {
if (fe instanceof FormDef) {
ref = ref.genericize();
}
if (fe instanceof QuestionDef) {
QuestionDef q = (QuestionDef) fe;
TreeReference bind = FormInstance.unpackReference(q.getBind());
return (ref.equals(bind) ? q : null);
} else {
for (int i = 0; i < fe.getChildren().size(); i++) {
QuestionDef ret = findQuestionByRef(ref, fe.getChild(i));
if (ret != null)
return ret;
}
return null;
}
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method getNumRepetitions.
public int getNumRepetitions(FormIndex index) {
List<Integer> indexes = new ArrayList<Integer>();
List<Integer> multiplicities = new ArrayList<Integer>();
List<IFormElement> elements = new ArrayList<IFormElement>();
if (!index.isInForm()) {
throw new RuntimeException("not an in-form index");
}
collapseIndex(index, indexes, multiplicities, elements);
if (!(elements.get(elements.size() - 1) instanceof GroupDef) || !((GroupDef) elements.get(elements.size() - 1)).getRepeat()) {
throw new RuntimeException("current element not a repeat");
}
// so painful
TreeElement templNode = mainInstance.getTemplate(index.getReference());
TreeReference parentPath = templNode.getParent().getRef().genericize();
TreeElement parentNode = mainInstance.resolveReference(parentPath.contextualize(index.getReference()));
return parentNode.getChildMultiplicity(templNode.getName());
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method populateDynamicChoices.
/**
* Identify the itemset in the backend model, and create a set of
* SelectChoice objects at the current question reference based on the data
* in the model.
* <p/>
* Will modify the itemset binding to contain the relevant choices
*
* @param itemset The binding for an itemset, where the choices will be populated
* @param curQRef A reference to the current question's element, which will be
* used to determine the values to be chosen from.
*/
public void populateDynamicChoices(ItemsetBinding itemset, TreeReference curQRef) {
getEventNotifier().publishEvent(new Event("Dynamic choices", new EvaluationResult(curQRef, null)));
List<SelectChoice> choices = new ArrayList<SelectChoice>();
List<TreeReference> matches = itemset.nodesetExpr.evalNodeset(this.getMainInstance(), new EvaluationContext(exprEvalContext, itemset.contextRef.contextualize(curQRef)));
DataInstance fi = null;
if (// We're not dealing
itemset.nodesetRef.getInstanceName() != null) // with the default
// instance
{
fi = getNonMainInstance(itemset.nodesetRef.getInstanceName());
if (fi == null) {
throw new XPathException("Instance " + itemset.nodesetRef.getInstanceName() + " not found");
}
} else {
fi = getMainInstance();
}
if (matches == null) {
throw new XPathException("Could not find references depended on by" + itemset.nodesetRef.getInstanceName());
}
for (int i = 0; i < matches.size(); i++) {
TreeReference item = matches.get(i);
// String label =
// itemset.labelExpr.evalReadable(this.getMainInstance(), new
// EvaluationContext(exprEvalContext, item));
String label = itemset.labelExpr.evalReadable(fi, new EvaluationContext(exprEvalContext, item));
String value = null;
TreeElement copyNode = null;
if (itemset.copyMode) {
copyNode = this.getMainInstance().resolveReference(itemset.copyRef.contextualize(item));
}
if (itemset.valueRef != null) {
// value = itemset.valueExpr.evalReadable(this.getMainInstance(),
// new EvaluationContext(exprEvalContext, item));
value = itemset.valueExpr.evalReadable(fi, new EvaluationContext(exprEvalContext, item));
}
// SelectChoice choice = new
// SelectChoice(labelID,labelInnerText,value,isLocalizable);
SelectChoice choice = new SelectChoice(label, value != null ? value : "dynamic:" + i, itemset.labelIsItext);
choice.setIndex(i);
if (itemset.copyMode)
choice.copyNode = copyNode;
choices.add(choice);
}
if (choices.size() == 0) {
// throw new
// RuntimeException("dynamic select question has no choices! [" +
// itemset.nodesetRef + "]");
// When you exit a survey mid way through and want to save it, it seems
// that Collect wants to
// go through all the questions. Well of course not all the questions
// are going to have answers
// to chose from if the user hasn't filled them out. So I'm just going
// to make a note of this
// and not throw an exception.
Std.out.println("Dynamic select question has no choices! [" + itemset.nodesetRef + "]. If this occurs while filling out a form (and not while saving an incomplete form), the filter condition may have eliminated all the choices. Is that what you intended?\n");
}
itemset.clearChoices();
itemset.setChoices(choices, this.getLocalizer());
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method deleteRepeat.
/**
* Deletes the inner-most repeat that this node belongs to and returns the
* corresponding FormIndex. Behavior is currently undefined if you call this
* method on a node that is not contained within a repeat.
*
* @param index
* @return
*/
public FormIndex deleteRepeat(FormIndex index) {
List<Integer> indexes = new ArrayList<Integer>();
List<Integer> multiplicities = new ArrayList<Integer>();
List<IFormElement> elements = new ArrayList<IFormElement>();
collapseIndex(index, indexes, multiplicities, elements);
// TODO: should probably check to make sure size > 0
for (int i = elements.size() - 1; i >= 0; i--) {
IFormElement e = elements.get(i);
if (e instanceof GroupDef && ((GroupDef) e).getRepeat()) {
break;
} else {
indexes.remove(i);
multiplicities.remove(i);
elements.remove(i);
}
}
// build new formIndex which includes everything
// up to the node we're going to remove
FormIndex newIndex = buildIndex(indexes, multiplicities, elements);
TreeReference deleteRef = getChildInstanceRef(newIndex);
TreeElement deleteElement = mainInstance.resolveReference(deleteRef);
TreeReference parentRef = deleteRef.getParentRef();
TreeElement parentElement = mainInstance.resolveReference(parentRef);
int childMult = deleteElement.getMult();
parentElement.removeChild(deleteElement);
// update multiplicities of other child nodes
for (int i = 0; i < parentElement.getNumChildren(); i++) {
TreeElement child = parentElement.getChildAt(i);
if (child.getName().equals(deleteElement.getName()) && child.getMult() > childMult) {
child.setMult(child.getMult() - 1);
// When a group changes it multiplicity, then all caches of its
// children must clear.
child.clearChildrenCaches();
}
}
dagImpl.deleteRepeatGroup(getMainInstance(), getEvaluationContext(), deleteRef, parentElement, deleteElement);
return newIndex;
}
Aggregations