use of org.javarosa.core.model.data.SelectMultiData in project collect by opendatakit.
the class GridMultiWidgetTest method getAnswerShouldReflectWhichSelectionsWereMade.
@Test
public void getAnswerShouldReflectWhichSelectionsWereMade() {
GridMultiWidget widget = getWidget();
assertNull(widget.getAnswer());
List<SelectChoice> selectChoices = getSelectChoices();
List<String> selectedValues = new ArrayList<>();
boolean atLeastOneSelected = false;
for (int i = 0; i < widget.selected.length; i++) {
boolean shouldBeSelected = random.nextBoolean();
widget.selected[i] = shouldBeSelected;
atLeastOneSelected = atLeastOneSelected || shouldBeSelected;
if (shouldBeSelected) {
SelectChoice selectChoice = selectChoices.get(i);
selectedValues.add(selectChoice.getValue());
}
}
// null answer case:
if (!atLeastOneSelected) {
int randomIndex = (Math.abs(random.nextInt()) % widget.selected.length);
widget.selected[randomIndex] = true;
SelectChoice selectChoice = selectChoices.get(randomIndex);
selectedValues.add(selectChoice.getValue());
}
SelectMultiData answer = (SelectMultiData) widget.getAnswer();
@SuppressWarnings("unchecked") List<Selection> answerSelections = (List<Selection>) answer.getValue();
List<String> answerValues = selectionsToValues(answerSelections);
for (String selectedValue : selectedValues) {
assertTrue(answerValues.contains(selectedValue));
}
}
use of org.javarosa.core.model.data.SelectMultiData in project collect by opendatakit.
the class GeneralSelectMultiWidgetTest method getAnswerShouldReflectWhichSelectionsWereMade.
@Test
public void getAnswerShouldReflectWhichSelectionsWereMade() {
W widget = getWidget();
assertNull(widget.getAnswer());
List<SelectChoice> selectChoices = getSelectChoices();
List<String> selectedValues = new ArrayList<>();
boolean atLeastOneSelected = false;
for (int i = 0; i < widget.getChoiceCount(); i++) {
boolean shouldBeSelected = random.nextBoolean();
widget.setChoiceSelected(i, shouldBeSelected);
atLeastOneSelected = atLeastOneSelected || shouldBeSelected;
if (shouldBeSelected) {
SelectChoice selectChoice = selectChoices.get(i);
selectedValues.add(selectChoice.getValue());
}
}
// null answer case:
if (!atLeastOneSelected) {
int randomIndex = (Math.abs(random.nextInt()) % widget.getChoiceCount());
widget.setChoiceSelected(randomIndex, true);
SelectChoice selectChoice = selectChoices.get(randomIndex);
selectedValues.add(selectChoice.getValue());
}
SelectMultiData answer = (SelectMultiData) widget.getAnswer();
@SuppressWarnings("unchecked") List<Selection> answerSelections = (List<Selection>) answer.getValue();
List<String> answerValues = selectionsToValues(answerSelections);
for (String selectedValue : selectedValues) {
assertTrue(answerValues.contains(selectedValue));
}
}
use of org.javarosa.core.model.data.SelectMultiData 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.data.SelectMultiData 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.data.SelectMultiData in project javarosa by opendatakit.
the class Recalculate method wrapData.
// droos 1/29/10: we need to come up with a consistent rule for whether the resulting data is determined
// by the type of the instance node, or the type of the expression result. right now it's a mix and a mess
// note a caveat with going solely by instance node type is that untyped nodes default to string!
// for now, these are the rules:
// if node type == bool, convert to boolean (for numbers, zero = f, non-zero = t; empty string = f, all other datatypes -> error)
// if numeric data, convert to int if node type is int OR data is an integer; else convert to double
// if string data or date data, keep as is
// if NaN or empty string, null
/**
* convert the data object returned by the xpath expression into an IAnswerData suitable for
* storage in the FormInstance
*/
public static IAnswerData wrapData(Object val, int dataType) {
if ((val instanceof String && ((String) val).length() == 0) || (val instanceof Double && ((Double) val).isNaN())) {
return null;
}
if (Constants.DATATYPE_BOOLEAN == dataType || val instanceof Boolean) {
// ctsims: We should really be using the boolean datatype for real, it's
// necessary for backend calculations and XSD compliance
boolean b;
if (val instanceof Boolean) {
b = (Boolean) val;
} else if (val instanceof Double) {
Double d = (Double) val;
b = Math.abs(d) > 1.0e-12 && !Double.isNaN(d);
} else if (val instanceof String) {
String s = (String) val;
b = s.length() > 0;
} else {
throw new RuntimeException("unrecognized data representation while trying to convert to BOOLEAN");
}
return new BooleanData(b);
} else if (val instanceof Double) {
double d = (Double) val;
long l = (long) d;
boolean isIntegral = Math.abs(d - l) < 1.0e-9;
if (Constants.DATATYPE_INTEGER == dataType || (isIntegral && (Integer.MAX_VALUE >= l) && (Integer.MIN_VALUE <= l))) {
return new IntegerData((int) d);
} else if (Constants.DATATYPE_LONG == dataType || isIntegral) {
return new LongData((long) d);
} else {
return new DecimalData(d);
}
} else if (dataType == Constants.DATATYPE_GEOPOINT) {
return new GeoPointData().cast(new UncastData(String.valueOf(val)));
} else if (dataType == Constants.DATATYPE_GEOSHAPE) {
return new GeoShapeData().cast(new UncastData(String.valueOf(val)));
} else if (dataType == Constants.DATATYPE_GEOTRACE) {
return new GeoTraceData().cast(new UncastData(String.valueOf(val)));
} else if (dataType == Constants.DATATYPE_CHOICE) {
return new SelectOneData().cast(new UncastData(String.valueOf(val)));
} else if (dataType == Constants.DATATYPE_CHOICE_LIST) {
return new SelectMultiData().cast(new UncastData(String.valueOf(val)));
} else if (val instanceof String) {
return new StringData((String) val);
} else if (val instanceof Date) {
if (dataType == Constants.DATATYPE_TIME)
return new TimeData((Date) val);
if (dataType == Constants.DATATYPE_DATE)
return new DateData((Date) val);
return new DateTimeData((Date) val);
} else {
throw new RuntimeException("unrecognized data type in 'calculate' expression: " + val.getClass().getName());
}
}
Aggregations