Skip to content

Commit

Permalink
Merge pull request #711 from getodk/JAVAROSA-686
Browse files Browse the repository at this point in the history
Values referenced from jr:repeat-count should be coerced to int
  • Loading branch information
seadowg authored Aug 1, 2023
2 parents 8b35777 + 195b648 commit fe1f7ba
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 4 deletions.
5 changes: 2 additions & 3 deletions src/main/java/org/javarosa/core/model/FormDef.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.data.MultipleItemsData;
import org.javarosa.core.model.data.SelectOneData;
import org.javarosa.core.model.data.helper.AnswerDataUtil;
import org.javarosa.core.model.data.helper.Selection;
import org.javarosa.core.model.instance.DataInstance;
import org.javarosa.core.model.instance.ExternalDataInstance;
Expand Down Expand Up @@ -580,9 +581,7 @@ public boolean canCreateRepeat(TreeReference repeatRef, FormIndex repeatIndex) {
+ repeat.getCountReference().getReference().toString());
}
// get the total multiplicity possible
IAnswerData count = countNode.getValue();
long fullcount = count == null ? 0 : (Integer) count.getValue();

long fullcount = AnswerDataUtil.answerDataToInt(countNode.getValue());
if (fullcount <= currentMultiplicity) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.javarosa.core.model.data.helper;

import org.javarosa.core.model.data.IAnswerData;

public class AnswerDataUtil {
public static int answerDataToInt(IAnswerData countData) {
if (countData == null) {
return 0;
}

Object count = countData.getValue();
if (count instanceof Integer) {
return (int) count;
} else if (count instanceof Double) {
return (int) Math.floor((Double) count);
} else if (count instanceof Long) {
return (int) ((Long) count).longValue();
} else {
return 0;
}
}
}
3 changes: 2 additions & 1 deletion src/main/java/org/javarosa/form/api/FormEntryModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.javarosa.core.model.IFormElement;
import org.javarosa.core.model.QuestionDef;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.data.helper.AnswerDataUtil;
import org.javarosa.core.model.instance.FormInstance;
import org.javarosa.core.model.instance.InvalidReferenceException;
import org.javarosa.core.model.instance.TreeElement;
Expand Down Expand Up @@ -433,7 +434,7 @@ private void createModelIfNecessary(FormIndex index) {
TreeReference contextualized = countRef.contextualize(index.getReference());
IAnswerData count = getForm().getMainInstance().resolveReference(contextualized).getValue();
if (count != null) {
long fullcount = ((Integer) count.getValue()).intValue();
long fullcount = AnswerDataUtil.answerDataToInt(count);
TreeReference ref = getForm().getChildInstanceRef(index);
TreeElement element = getForm().getMainInstance().resolveReference(ref);
if (element == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,34 @@ public void setValueOnRepeatWithCount_setsValueForEachRepeat() throws XFormParse

}

@Test
public void setOtherThanIntegerValueOnRepeatWithCount_convertsValueToInteger() throws XFormParser.ParseException {
Scenario scenario = Scenario.init(r("event-odk-new-repeat.xml"));

// String
scenario.answer("/data/repeat-count", "1");
while (!scenario.atTheEndOfForm()) {
scenario.next();
}
assertThat(scenario.countRepeatInstancesOf("/data/my-jr-count-repeat"), is(0));

// Decimal
scenario.jumpToBeginningOfForm();
scenario.answer("/data/repeat-count", 2.5);
while (!scenario.atTheEndOfForm()) {
scenario.next();
}
assertThat(scenario.countRepeatInstancesOf("/data/my-jr-count-repeat"), is(2));

// Long
scenario.jumpToBeginningOfForm();
scenario.answer("/data/repeat-count", 3L);
while (!scenario.atTheEndOfForm()) {
scenario.next();
}
assertThat(scenario.countRepeatInstancesOf("/data/my-jr-count-repeat"), is(3));
}

@Test
public void repeatInFormDefInstance_neverFiresNewRepeatEvent() throws XFormParser.ParseException {
Scenario scenario = Scenario.init(r("event-odk-new-repeat.xml"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.javarosa.core.model.data.helper;

import org.javarosa.core.model.data.BooleanData;
import org.javarosa.core.model.data.DateData;
import org.javarosa.core.model.data.DecimalData;
import org.javarosa.core.model.data.IntegerData;
import org.javarosa.core.model.data.LongData;
import org.javarosa.core.model.data.SelectOneData;
import org.javarosa.core.model.data.StringData;
import org.junit.Test;

import java.util.Date;

import static org.junit.Assert.assertEquals;

public class AnswerDataUtilTest {

@Test
public void NumericalDataReturnsProperValueWhenConvertedToInt() {
assertEquals(5, AnswerDataUtil.answerDataToInt(new IntegerData(5)));

assertEquals(7, AnswerDataUtil.answerDataToInt(new DecimalData(7.35)));

assertEquals(3, AnswerDataUtil.answerDataToInt(new LongData(3L)));
}

@Test
public void NonNumericalDataReturnsZeroWhenConvertedToInt() {
assertEquals(0, AnswerDataUtil.answerDataToInt(new BooleanData(true)));
assertEquals(0, AnswerDataUtil.answerDataToInt(new SelectOneData(new Selection("Selection1"))));
assertEquals(0, AnswerDataUtil.answerDataToInt(new DateData(new Date())));
assertEquals(0, AnswerDataUtil.answerDataToInt(new StringData("blah")));
}

@Test
public void IfDataTypeHasNoAnswerReturnsZeroWhenConvertedToInt() {
assertEquals(0, AnswerDataUtil.answerDataToInt(new IntegerData()));
assertEquals(0, AnswerDataUtil.answerDataToInt(new DecimalData()));
assertEquals(0, AnswerDataUtil.answerDataToInt(new LongData()));
assertEquals(0, AnswerDataUtil.answerDataToInt(new BooleanData()));
}
}
23 changes: 23 additions & 0 deletions src/test/java/org/javarosa/core/test/Scenario.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.model.data.BooleanData;
import org.javarosa.core.model.data.DateData;
import org.javarosa.core.model.data.DecimalData;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.data.IntegerData;
import org.javarosa.core.model.data.MultipleItemsData;
Expand Down Expand Up @@ -509,6 +510,21 @@ public AnswerResult answer(String xPath, int value) {
return answer(value);
}

/**
* Answers with an double value the question at the form index
* corresponding to the provided reference.
* <p>
* This method has side effects:
* - It will create all the required middle and end repeat group instances
* - It changes the current form index
*/
public AnswerResult answer(String xPath, double value) {
createMissingRepeats(xPath);
TreeReference ref = getRef(xPath);
silentJump(getIndexOf(ref));
return answer(value);
}

/**
* Answers with a boolean value the question at the form index
* corresponding to the provided reference.
Expand Down Expand Up @@ -554,6 +570,13 @@ public AnswerResult answer(int value) {
return answer(new IntegerData(value));
}

/**
* Answers the question at the form index
*/
public AnswerResult answer(double value) {
return answer(new DecimalData(value));
}

/**
* Answers the question at the form index
*/
Expand Down

0 comments on commit fe1f7ba

Please sign in to comment.