use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.
the class FormInstanceParser method verifyItemsetSrcDstCompatibility.
private void verifyItemsetSrcDstCompatibility(FormInstance instance) {
for (ItemsetBinding itemset : itemsets) {
boolean destRepeatable = (instance.getTemplate(itemset.getDestRef()) != null);
if (itemset.copyMode) {
if (!destRepeatable) {
throw new XFormParseException("itemset copies to node(s) which are not repeatable");
}
// validate homogeneity between src and dst nodes
TreeElement srcNode = instance.getTemplatePath(itemset.copyRef);
TreeElement dstNode = instance.getTemplate(itemset.getDestRef());
if (!FormInstance.isHomogeneous(srcNode, dstNode)) {
reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Your itemset source [" + srcNode.getRef().toString() + "] and dest [" + dstNode.getRef().toString() + "] of appear to be incompatible!", null);
}
// TODO: i feel like, in theory, i should additionally check that the repeatable children of src and dst
// match up (Achild is repeatable <--> Bchild is repeatable). isHomogeneous doesn't check this. but i'm
// hard-pressed to think of scenarios where this would actually cause problems
} else {
if (destRepeatable) {
throw new XFormParseException("itemset sets value on repeatable nodes");
}
}
}
}
use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.
the class FormEntryPrompt method expireDynamicChoices.
public void expireDynamicChoices() {
dynamicChoicesPopulated = false;
ItemsetBinding itemset = getQuestion().getDynamicChoices();
if (itemset != null) {
itemset.clearChoices();
}
}
use of org.javarosa.core.model.ItemsetBinding in project javarosa by opendatakit.
the class FormEntryPrompt method getSelectChoices.
public List<SelectChoice> getSelectChoices() {
QuestionDef q = getQuestion();
ItemsetBinding itemset = q.getDynamicChoices();
if (itemset != null) {
if (!dynamicChoicesPopulated) {
form.populateDynamicChoices(itemset, mTreeElement.getRef());
dynamicChoicesPopulated = true;
}
return itemset.getChoices();
} else {
// static choices
return q.getChoices();
}
}
use of org.javarosa.core.model.ItemsetBinding 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));
}
}
use of org.javarosa.core.model.ItemsetBinding 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();
}
}
Aggregations