use of org.javarosa.core.model.IFormElement in project collect by opendatakit.
the class FormController method getIndicesForGroup.
private List<FormIndex> getIndicesForGroup(GroupDef gd, FormIndex currentChildIndex) {
List<FormIndex> indices = new ArrayList<>();
for (int i = 0; i < gd.getChildren().size(); i++) {
final FormEntryModel formEntryModel = formEntryController.getModel();
if (getEvent(currentChildIndex) == FormEntryController.EVENT_GROUP) {
IFormElement nestedElement = formEntryModel.getForm().getChild(currentChildIndex);
if (nestedElement instanceof GroupDef) {
indices.addAll(getIndicesForGroup((GroupDef) nestedElement, formEntryModel.incrementIndex(currentChildIndex, true)));
currentChildIndex = formEntryModel.incrementIndex(currentChildIndex, false);
}
} else {
indices.add(currentChildIndex);
currentChildIndex = formEntryModel.incrementIndex(currentChildIndex, false);
}
}
return indices;
}
use of org.javarosa.core.model.IFormElement 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.IFormElement in project javarosa by opendatakit.
the class XFormParser method collapseRepeatGroups.
/**
* Collapses groups whose only child is a repeat into a single repeat that uses the label of the wrapping group
*/
private static void collapseRepeatGroups(IFormElement fe) {
if (fe.getChildren() == null)
return;
for (int i = 0; i < fe.getChildren().size(); i++) {
IFormElement child = fe.getChild(i);
GroupDef group = null;
if (child instanceof GroupDef)
group = (GroupDef) child;
if (group != null) {
if (!group.getRepeat() && group.getChildren().size() == 1) {
IFormElement grandchild = group.getChildren().get(0);
GroupDef repeat = null;
if (grandchild instanceof GroupDef)
repeat = (GroupDef) grandchild;
if (repeat != null && repeat.getRepeat()) {
// collapse the wrapping group
// merge group into repeat
// id - later
// name - later
repeat.setLabelInnerText(group.getLabelInnerText());
repeat.setTextID(group.getTextID());
// don't merge binding; repeat will always already have one
// replace group with repeat
fe.getChildren().set(i, repeat);
group = repeat;
}
}
collapseRepeatGroups(group);
}
}
}
use of org.javarosa.core.model.IFormElement in project javarosa by opendatakit.
the class XFormParser method parseGroup.
private void parseGroup(IFormElement parent, Element e, int groupType) {
GroupDef group = new GroupDef();
// until we come up with a better scheme
group.setID(serialQuestionID++);
IDataReference dataRef = null;
boolean refFromBind = false;
List<String> usedAtts = new ArrayList<>();
usedAtts.add(REF_ATTR);
usedAtts.add(NODESET_ATTR);
usedAtts.add(BIND_ATTR);
usedAtts.add(APPEARANCE_ATTR);
usedAtts.add("count");
usedAtts.add("noAddRemove");
if (groupType == CONTAINER_REPEAT) {
group.setRepeat(true);
}
String ref = e.getAttributeValue(null, REF_ATTR);
String nodeset = e.getAttributeValue(null, NODESET_ATTR);
String bind = e.getAttributeValue(null, BIND_ATTR);
group.setAppearanceAttr(e.getAttributeValue(null, APPEARANCE_ATTR));
if (bind != null) {
DataBinding binding = bindingsByID.get(bind);
if (binding == null) {
throw new XFormParseException("XForm Parse: invalid binding ID [" + bind + "]", e);
}
dataRef = binding.getReference();
refFromBind = true;
} else {
if (group.getRepeat()) {
if (nodeset != null) {
dataRef = new XPathReference(nodeset);
} else {
throw new XFormParseException("XForm Parse: <repeat> with no binding ('bind' or 'nodeset')", e);
}
} else {
if (ref != null) {
dataRef = new XPathReference(ref);
} else if (nodeset != null) {
dataRef = new XPathReference(nodeset);
}
// <group> not required to have a binding so no exception thrown
}
}
if (!refFromBind) {
dataRef = getAbsRef(dataRef, parent);
}
group.setBind(dataRef);
if (group.getRepeat()) {
repeats.add((TreeReference) dataRef.getReference());
String countRef = e.getAttributeValue(NAMESPACE_JAVAROSA, "count");
if (countRef != null) {
group.count = getAbsRef(new XPathReference(countRef), parent);
group.noAddRemove = true;
} else {
group.noAddRemove = (e.getAttributeValue(NAMESPACE_JAVAROSA, "noAddRemove") != null);
}
}
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);
String childNamespace = (child != null ? child.getNamespace() : null);
if (group.getRepeat() && NAMESPACE_JAVAROSA.equals(childNamespace)) {
if ("chooseCaption".equals(childName)) {
group.chooseCaption = getLabel(child);
} else if ("addCaption".equals(childName)) {
group.addCaption = getLabel(child);
} else if ("delCaption".equals(childName)) {
group.delCaption = getLabel(child);
} else if ("doneCaption".equals(childName)) {
group.doneCaption = getLabel(child);
} else if ("addEmptyCaption".equals(childName)) {
group.addEmptyCaption = getLabel(child);
} else if ("doneEmptyCaption".equals(childName)) {
group.doneEmptyCaption = getLabel(child);
} else if ("entryHeader".equals(childName)) {
group.entryHeader = getLabel(child);
} else if ("delHeader".equals(childName)) {
group.delHeader = getLabel(child);
} else if ("mainHeader".equals(childName)) {
group.mainHeader = getLabel(child);
}
}
}
for (int i = 0; i < e.getChildCount(); i++) {
if (e.getType(i) == Element.ELEMENT) {
parseElement(e.getElement(i), group, groupLevelHandlers);
}
}
// save all the unused attributes verbatim...
for (int i = 0; i < e.getAttributeCount(); i++) {
String name = e.getAttributeName(i);
if (usedAtts.contains(name))
continue;
group.setAdditionalAttribute(e.getAttributeNamespace(i), name, e.getAttributeValue(i));
}
// 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));
}
parent.addChild(group);
}
use of org.javarosa.core.model.IFormElement 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);
}
}
Aggregations