Support required questionnaireitem groups

This commit is contained in:
Matti Uusitalo 2018-12-07 16:33:09 +02:00
parent b2e20b5c31
commit 64f378ae78
2 changed files with 75 additions and 27 deletions

View File

@ -2639,9 +2639,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
List<Element> answers = new ArrayList<Element>();
element.getNamedChildren("answer", answers);
if (inProgress)
warning(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), (answers.size() > 0) || !qItem.getRequired(), "No response answer found for required item "+qItem.getLinkId());
warning(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), "No response answer found for required item "+qItem.getLinkId());
else
rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), (answers.size() > 0) || !qItem.getRequired(), "No response answer found for required item "+qItem.getLinkId());
rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), "No response answer found for required item "+qItem.getLinkId());
if (answers.size() > 1)
rule(errors, IssueType.INVALID, answers.get(1).line(), answers.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), "Only one response answer item with this linkId allowed");
@ -2729,6 +2729,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, List<Element> answers) {
return !answers.isEmpty() || !qItem.getRequired() || qItem.getType() == QuestionnaireItemType.GROUP;
}
private void validateQuestionannaireResponseItem(Questionnaire qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<Element> elements, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot) {
if (elements.size() > 1)
rule(errors, IssueType.INVALID, elements.get(1).line(), elements.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), "Only one response item with this linkId allowed - " + qItem.getLinkId());

View File

@ -22,6 +22,7 @@ import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseItemC
import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseStatus;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
@ -40,17 +41,23 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
public class QuestionnaireResponseValidatorDstu3Test {
private static final String QUESTIONNAIRE_URL = "http://example.com/Questionnaire/q1";
public static final IdType ID_ICC_QUESTIONNAIRE_SETUP = new IdType("Questionnaire/profile");
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(QuestionnaireResponseValidatorDstu3Test.class);
private static final String CODE_ICC_SCHOOLTYPE_PT = "PT";
private static final IdType ID_VS_SCHOOLTYPE = new IdType("ValueSet/schooltype");
private static final String SYSTEMURI_ICC_SCHOOLTYPE = "http://ehealthinnovation/icc/ns/schooltype";
private static DefaultProfileValidationSupport myDefaultValidationSupport = new DefaultProfileValidationSupport();
private static FhirContext ourCtx = FhirContext.forDstu3();
private static FhirContext ourCtx;
private FhirInstanceValidator myInstanceVal;
private FhirValidator myVal;
private IValidationSupport myValSupport;
@BeforeClass
public static void beforeClass() {
ourCtx = FhirContext.forDstu3();
}
@Before
public void before() {
myValSupport = mock(IValidationSupport.class);
@ -122,7 +129,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
answerValues[11] = new Coding().setSystem("http://codesystems.com/system").setCode("code0");
answerValues[12] = new StringType("some value");
answerValues[13] = new Attachment().setData("some data".getBytes()).setContentType("txt");
answerValues[14] = new Reference("http://example.com/Questionnaire/q1");
answerValues[14] = new Reference(QUESTIONNAIRE_URL);
answerValues[15] = new Quantity(42);
for (int i = 0; i < itemCnt; i++) {
@ -132,7 +139,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
reset(myValSupport);
Questionnaire q = new Questionnaire();
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class),
eq("http://example.com/Questionnaire/q1"))).thenReturn(q);
eq(QUESTIONNAIRE_URL))).thenReturn(q);
when(myValSupport.fetchCodeSystem(any(FhirContext.class), eq("http://codesystems.com/system"))).thenReturn(codeSystem);
when(myValSupport.fetchResource(any(FhirContext.class), eq(ValueSet.class), eq("http://somevalueset"))).thenReturn(options);
myInstanceVal.flushCaches();
@ -149,7 +156,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.INPROGRESS);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId(linkId).addAnswer().setValue(answerValues[i]);
ValidationResult errors = myVal.validateWithResult(qa);
@ -165,7 +172,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link0").addAnswer().setValue(new StringType("FOO"));
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(qa.getQuestionnaire().getReference()))).thenReturn(q);
@ -178,11 +185,11 @@ public class QuestionnaireResponseValidatorDstu3Test {
@Test
public void testCodedAnswer() {
String questionnaireRef = "http://example.com/Questionnaire/q1";
String questionnaireRef = QUESTIONNAIRE_URL;
Questionnaire q = new Questionnaire();
q.addItem().setLinkId("link0").setRequired(false).setType(QuestionnaireItemType.CHOICE).setOptions(new Reference("http://somevalueset"));
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq("http://example.com/Questionnaire/q1"))).thenReturn(q);
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(QUESTIONNAIRE_URL))).thenReturn(q);
CodeSystem codeSystem = new CodeSystem();
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
@ -246,7 +253,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
QuestionnaireResponseItemComponent qaGroup = qa.addItem();
qaGroup.addItem().setLinkId("link0").addAnswer().setValue(new StringType("FOO"));
@ -256,6 +263,43 @@ public class QuestionnaireResponseValidatorDstu3Test {
ourLog.info(errors.toString());
assertThat(errors.toString(), containsString("No LinkId, so can't be validated"));
}
@Test
public void testMissingAnswerInNestedStructureIsReported() throws Exception {
Questionnaire q = new Questionnaire();
q.addItem().setType(QuestionnaireItemType.GROUP).setRequired(true)
.addItem().setType(QuestionnaireItemType.GROUP).setRequired(true)
.addItem().setType(QuestionnaireItemType.BOOLEAN).setLinkId("link0").setRequired(true);
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(qa.getQuestionnaire().getReference()))).thenReturn(q);
ValidationResult errors = myVal.validateWithResult(qa);
assertThat(errors.toString(), Matchers.not(containsString("No issues")));
}
@Test
public void testGroupMarkedAsRequiredIsOk() throws Exception {
Questionnaire q = new Questionnaire();
q.addItem().setType(QuestionnaireItemType.GROUP).setRequired(true).setLinkId("link1")
.addItem().setType(QuestionnaireItemType.BOOLEAN).setLinkId("link0").setRequired(true);
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link1")
.addItem().setLinkId("link0").addAnswer().setValue(new BooleanType(true));
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(qa.getQuestionnaire().getReference()))).thenReturn(q);
ValidationResult errors = myVal.validateWithResult(qa);
assertThat(errors.toString(), containsString("No issues"));
}
@Test
public void testItemWithNoType() {
@ -266,7 +310,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
QuestionnaireResponseItemComponent qaGroup = qa.addItem().setLinkId("link0");
qaGroup.addItem().setLinkId("link1").addAnswer().setValue(new StringType("FOO"));
@ -287,7 +331,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link1").addAnswer().setValue(new StringType("FOO"));
String reference = qa.getQuestionnaire().getReference();
@ -315,7 +359,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
String reference = qa.getQuestionnaire().getReference();
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(reference))).thenReturn(q);
@ -343,7 +387,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
String reference = qa.getQuestionnaire().getReference();
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(reference))).thenReturn(q);
@ -370,7 +414,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link0").addAnswer().setValue(new Quantity().setValue(1L));
String reference = qa.getQuestionnaire().getReference();
@ -398,7 +442,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link0").addAnswer().setValue(new Quantity().setValue(1L));
String reference = qa.getQuestionnaire().getReference();
@ -426,7 +470,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link0").addAnswer().setValue(new StringType("FOO"));
qa.addItem().setLinkId("link1").addAnswer().setValue(new StringType("BAR"));
@ -454,7 +498,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
// link1 should be disabled, because the enableWhen enables it when link0 doesn't haven an answer
qa.addItem().setLinkId("link0").addAnswer().setValue(new StringType("FOO"));
@ -475,7 +519,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qr = new QuestionnaireResponse();
qr.setStatus(QuestionnaireResponseStatus.COMPLETED);
qr.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qr.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qr.addItem().setLinkId("link2").addAnswer().setValue(new StringType("FOO"));
@ -495,7 +539,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qr = new QuestionnaireResponse();
qr.setStatus(QuestionnaireResponseStatus.COMPLETED);
qr.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qr.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qr.addItem().setLinkId("link0").setText("Text");
qr.addItem().setLinkId("link1").addAnswer().setValue(new StringType("Answer"));
String reference = qr.getQuestionnaire().getReference();
@ -510,7 +554,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
@Test
public void testEmbeddedItemInChoice() {
String questionnaireRef = "http://example.com/Questionnaire/q1";
String questionnaireRef = QUESTIONNAIRE_URL;
String valueSetRef = "http://somevalueset";
String codeSystemUrl = "http://codesystems.com/system";
String codeValue = "code0";
@ -566,7 +610,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
@Test
public void testEmbeddedItemInOpenChoice() {
String questionnaireRef = "http://example.com/Questionnaire/q1";
String questionnaireRef = QUESTIONNAIRE_URL;
String valueSetRef = "http://somevalueset";
String codeSystemUrl = "http://codesystems.com/system";
String codeValue = "code0";
@ -622,7 +666,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
@Test
public void testEmbeddedItemInString() {
String questionnaireRef = "http://example.com/Questionnaire/q1";
String questionnaireRef = QUESTIONNAIRE_URL;
// create the questionnaire
QuestionnaireItemComponent item1 = new QuestionnaireItemComponent();
@ -723,7 +767,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
.setType(QuestionnaireItemType.STRING)
.setRequired(true);
String reference = "http://example.com/Questionnaire/q1";
String reference = QUESTIONNAIRE_URL;
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(reference)))
.thenReturn(q);
@ -747,7 +791,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
@Test
public void testOpenchoiceAnswer() {
String questionnaireRef = "http://example.com/Questionnaire/q1";
String questionnaireRef = QUESTIONNAIRE_URL;
Questionnaire q = new Questionnaire();
QuestionnaireItemComponent item = q.addItem();
@ -870,7 +914,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link1").addAnswer().setValue(new StringType("FOO"));
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(qa.getQuestionnaire().getReference()))).thenReturn(q);
@ -888,7 +932,7 @@ public class QuestionnaireResponseValidatorDstu3Test {
QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
qa.getQuestionnaire().setReference("http://example.com/Questionnaire/q1");
qa.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qa.addItem().setLinkId("link1").addItem().setLinkId("link2");
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(qa.getQuestionnaire().getReference()))).thenReturn(q);