use of org.javarosa.core.model.QuestionDef 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.QuestionDef in project collect by opendatakit.
the class ExternalAnswerResolver method resolveAnswer.
@Override
public IAnswerData resolveAnswer(String textVal, TreeElement treeElement, FormDef formDef) {
QuestionDef questionDef = XFormParser.ghettoGetQuestionDef(treeElement.getDataType(), formDef, treeElement.getRef());
if (questionDef != null && (questionDef.getControlType() == Constants.CONTROL_SELECT_ONE || questionDef.getControlType() == Constants.CONTROL_SELECT_MULTI)) {
boolean containsSearchExpression = false;
XPathFuncExpr xpathExpression = null;
try {
xpathExpression = ExternalDataUtil.getSearchXPathExpression(questionDef.getAppearanceAttr());
} catch (Exception e) {
Timber.e(e);
// there is a search expression, but has syntax errors
containsSearchExpression = true;
}
if (xpathExpression != null || containsSearchExpression) {
// that means that we have dynamic selects
// read the static choices from the options sheet
List<SelectChoice> staticChoices = questionDef.getChoices();
for (int index = 0; index < staticChoices.size(); index++) {
SelectChoice selectChoice = staticChoices.get(index);
String selectChoiceValue = selectChoice.getValue();
if (ExternalDataUtil.isAnInteger(selectChoiceValue)) {
Selection selection = selectChoice.selection();
switch(questionDef.getControlType()) {
case Constants.CONTROL_SELECT_ONE:
{
if (selectChoiceValue.equals(textVal)) {
// we just need to make sure, so we will override that.
if (questionDef.getControlType() == Constants.CONTROL_SELECT_ONE) {
// we don't need another, just return the static choice.
return new SelectOneData(selection);
}
}
break;
}
case Constants.CONTROL_SELECT_MULTI:
{
// we should search in a potential comma-separated string of
// values for a match
// copied from org.javarosa.xform.util.XFormAnswerDataParser
// .getSelections()
List<String> textValues = DateUtils.split(textVal, XFormAnswerDataSerializer.DELIMITER, true);
if (textValues.contains(textVal)) {
// choice.
if (selectChoiceValue.equals(textVal)) {
// this means that the user selected ONLY the static
// answer, so just return that
List<Selection> customSelections = new ArrayList<Selection>();
customSelections.add(selection);
return new SelectMultiData(customSelections);
} else {
// we will ignore it for now since we will return that
// selection together with the dynamic ones.
}
}
break;
}
default:
{
// There is a bug if we get here, so let's throw an Exception
throw createBugRuntimeException(treeElement, textVal);
}
}
} else {
switch(questionDef.getControlType()) {
case Constants.CONTROL_SELECT_ONE:
{
// the default implementation will search for the "textVal"
// (saved answer) inside the static choices.
// Since we know that there isn't such, we just wrap the textVal
// in a virtual choice in order to
// create a SelectOneData object to be used as the IAnswer to the
// TreeElement.
// (the caller of this function is searching for such an answer
// to populate the in-memory model.)
SelectChoice customSelectChoice = new SelectChoice(textVal, textVal, false);
customSelectChoice.setIndex(index);
return new SelectOneData(customSelectChoice.selection());
}
case Constants.CONTROL_SELECT_MULTI:
{
// we should create multiple selections and add them to the pile
List<SelectChoice> customSelectChoices = createCustomSelectChoices(textVal);
List<Selection> customSelections = new ArrayList<Selection>();
for (SelectChoice customSelectChoice : customSelectChoices) {
customSelections.add(customSelectChoice.selection());
}
return new SelectMultiData(customSelections);
}
default:
{
// There is a bug if we get here, so let's throw an Exception
throw createBugRuntimeException(treeElement, textVal);
}
}
}
}
// if we get there then that means that we have a bug
throw createBugRuntimeException(treeElement, textVal);
}
}
// default behavior matches original behavior (for static selects, etc.)
return super.resolveAnswer(textVal, treeElement, formDef);
}
use of org.javarosa.core.model.QuestionDef 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.QuestionDef in project javarosa by opendatakit.
the class FormEntryModel method getCaptionHierarchy.
/**
* Returns a hierarchical list of FormEntryCaption objects for the given
* FormIndex
*
* @param index
* @return list of FormEntryCaptions in hierarchical order
*/
public FormEntryCaption[] getCaptionHierarchy(FormIndex index) {
List<FormEntryCaption> captions = new ArrayList<FormEntryCaption>();
FormIndex remaining = index;
while (remaining != null) {
remaining = remaining.getNextLevel();
FormIndex localIndex = index.diff(remaining);
IFormElement element = form.getChild(localIndex);
if (element != null) {
FormEntryCaption caption = null;
if (element instanceof GroupDef)
caption = new FormEntryCaption(getForm(), localIndex);
else if (element instanceof QuestionDef)
caption = new FormEntryPrompt(getForm(), localIndex);
if (caption != null) {
captions.add(caption);
}
}
}
FormEntryCaption[] captionArray = new FormEntryCaption[captions.size()];
return captions.toArray(captionArray);
}
use of org.javarosa.core.model.QuestionDef in project javarosa by opendatakit.
the class FormEntryController method answerQuestion.
/**
* Attempts to save the answer at the specified FormIndex into the
* datamodel.
*
* @param index
* @param data
* @return OK if save was successful, error if a constraint was violated.
*/
public int answerQuestion(FormIndex index, IAnswerData data, boolean midSurvey) {
QuestionDef q = model.getQuestionPrompt(index).getQuestion();
if (model.getEvent(index) != FormEntryController.EVENT_QUESTION) {
throw new RuntimeException("Non-Question object at the form index.");
}
TreeElement element = model.getTreeElement(index);
boolean complexQuestion = q.isComplex();
boolean hasConstraints = false;
if (element.isRequired() && data == null) {
return ANSWER_REQUIRED_BUT_EMPTY;
} else if (!complexQuestion && !model.getForm().evaluateConstraint(index.getReference(), data)) {
return ANSWER_CONSTRAINT_VIOLATED;
} else if (!complexQuestion) {
commitAnswer(element, index, data, midSurvey);
return ANSWER_OK;
} else if (complexQuestion && hasConstraints) {
// TODO: itemsets: don't currently evaluate constraints for itemset/copy -- haven't figured out how handle it yet
throw new RuntimeException("Itemsets do not currently evaluate constraints. Your constraint will not work, please remove it before proceeding.");
} else {
try {
model.getForm().copyItemsetAnswer(q, element, data, midSurvey);
} catch (InvalidReferenceException ire) {
Std.printStack(ire);
throw new RuntimeException("Invalid reference while copying itemset answer: " + ire.getMessage());
}
return ANSWER_OK;
}
}
Aggregations