Allowing items without answers even if item is disabled.

This commit is contained in:
Eeva Turkka 2019-01-31 13:00:41 +02:00
parent e6df4a21e4
commit 7e7d4d8879
4 changed files with 60 additions and 15 deletions

View File

@ -9,9 +9,11 @@
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
<groupId>fi.kela.kanta.phr</groupId>
<artifactId>hapi-fhir-validation</artifactId> <artifactId>hapi-fhir-validation</artifactId>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<version>3.6.4-PHRFIX</version> <version>3.6.5-PHRFIX</version>
<name>HAPI FHIR - Validation</name> <name>HAPI FHIR - Validation</name>

View File

@ -196,6 +196,7 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator {
} }
return true; return true;
} }
private List<Element> findSubItems(Element item) { private List<Element> findSubItems(Element item) {
List<Element> results = item.getChildren(ITEM_ELEMENT) List<Element> results = item.getChildren(ITEM_ELEMENT)
.stream() .stream()
@ -213,6 +214,4 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator {
return false; return false;
} }
} }

View File

@ -2640,8 +2640,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
element.getNamedChildren("answer", answers); element.getNamedChildren("answer", answers);
if (inProgress) if (inProgress)
warning(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), "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 else if(myEnableWhenEvaluator.isQuestionEnabled(qItem, questionnaireResponseRoot))
rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), "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());
else if (!answers.isEmpty()) // items without answers should be allowed, but not items with answers to questions that are disabled
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !isAnswerRequirementFulfilled(qItem, answers), "Item has answer, even though it is not enabled "+qItem.getLinkId());
if (answers.size() > 1) 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"); 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");
@ -2786,7 +2790,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
for (QuestionnaireItemComponent qItem : qItems) { for (QuestionnaireItemComponent qItem : qItems) {
List<Element> mapItem = map.get(qItem.getLinkId()); List<Element> mapItem = map.get(qItem.getLinkId());
if (mapItem != null) { if (mapItem != null) {
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), myEnableWhenEvaluator.isQuestionEnabled(qItem, questionnaireResponseRoot), "Item has answer, even though it is not enabled "+qItem.getLinkId()); //rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), myEnableWhenEvaluator.isQuestionEnabled(qItem, questionnaireResponseRoot), "Item has answer, even though it is not enabled "+qItem.getLinkId());
validateQuestionannaireResponseItem(qsrc, qItem, errors, mapItem, stack, inProgress, questionnaireResponseRoot); validateQuestionannaireResponseItem(qsrc, qItem, errors, mapItem, stack, inProgress, questionnaireResponseRoot);
} else { } else {
//item is missing, is the question enabled? //item is missing, is the question enabled?
@ -2797,6 +2801,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
} }
} }
private String misplacedItemError(QuestionnaireItemComponent qItem) { private String misplacedItemError(QuestionnaireItemComponent qItem) {
return qItem.hasLinkId() ? return qItem.hasLinkId() ?
String.format("Structural Error: item with linkid %s is in the wrong place", qItem.getLinkId()) String.format("Structural Error: item with linkid %s is in the wrong place", qItem.getLinkId())

View File

@ -351,17 +351,12 @@ public class QuestionnaireResponseValidatorDstu3Test {
public void testRequiredQuestionWithEnableWhenHidesQuestionHasAnswerTrue() { public void testRequiredQuestionWithEnableWhenHidesQuestionHasAnswerTrue() {
Questionnaire q = new Questionnaire(); Questionnaire q = new Questionnaire();
q.addItem().setLinkId("link0").setRequired(true).setType(QuestionnaireItemType.STRING); q.addItem().setLinkId("link0").setRequired(false).setType(QuestionnaireItemType.STRING);
// create the questionnaire // create the questionnaire
QuestionnaireItemComponent item1 = new QuestionnaireItemComponent(); QuestionnaireItemComponent item1 = new QuestionnaireItemComponent();
item1.setLinkId("link1").setRequired(true); item1.setLinkId("link1").setRequired(true).addEnableWhen().setQuestion("link0").setHasAnswer(true);
q.addItem(item1); q.addItem(item1);
QuestionnaireItemEnableWhenComponent enable = new QuestionnaireItemEnableWhenComponent();
item1.addEnableWhen(enable);
enable.setQuestion("link0");
enable.setHasAnswer(true);
QuestionnaireResponse qa = new QuestionnaireResponse(); QuestionnaireResponse qa = new QuestionnaireResponse();
qa.setStatus(QuestionnaireResponseStatus.COMPLETED); qa.setStatus(QuestionnaireResponseStatus.COMPLETED);
@ -531,6 +526,50 @@ public class QuestionnaireResponseValidatorDstu3Test {
assertThat(errors.toString(), Matchers.not(containsString("No issues"))); assertThat(errors.toString(), Matchers.not(containsString("No issues")));
} }
@Test
public void testGivenQuestionIsNotEnabledWithEnableWhenButHasItemsWithoutAnswersAreOk() throws Exception {
Questionnaire q = new Questionnaire();
q.addItem().setLinkId("link0").setRequired(false).setType(QuestionnaireItemType.STRING);
q.addItem().setLinkId("link2").setRequired(false).setType(QuestionnaireItemType.STRING).addEnableWhen().setQuestion("link0").setHasAnswer(true);
QuestionnaireResponse qr = new QuestionnaireResponse();
qr.setStatus(QuestionnaireResponseStatus.COMPLETED);
qr.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qr.addItem().setLinkId("link2");
String reference = qr.getQuestionnaire().getReference();
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(reference))).thenReturn(q);
ValidationResult errors = myVal.validateWithResult(qr);
assertThat(errors.toString(), containsString("No issues"));
}
@Test
public void testGivenQuestionIsNotEnabledWithEnableWhenButHasItemsWithoutAnswersAreOk2() throws Exception {
Questionnaire q = new Questionnaire();
q.addItem().setLinkId("link0").setRequired(false).setType(QuestionnaireItemType.STRING);
q.addItem().setLinkId("link1").setRequired(false).setType(QuestionnaireItemType.STRING);
q.addItem().setLinkId("link2").setRequired(true).setType(QuestionnaireItemType.STRING).addEnableWhen().setQuestion("link0").setHasAnswer(true);
QuestionnaireResponse qr = new QuestionnaireResponse();
qr.setStatus(QuestionnaireResponseStatus.COMPLETED);
qr.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
qr.addItem().setLinkId("link0");
qr.addItem().setLinkId("link1").addAnswer().setValue(new StringType("Answer"));
qr.addItem().setLinkId("link2");
String reference = qr.getQuestionnaire().getReference();
when(myValSupport.fetchResource(any(FhirContext.class), eq(Questionnaire.class), eq(reference))).thenReturn(q);
ValidationResult errors = myVal.validateWithResult(qr);
assertThat(errors.toString(), containsString("No issues"));
}
@Test @Test
public void testGivenQuestionnaireResponseHasSiblingItemsWhenTheyShouldBeChildItems() throws Exception { public void testGivenQuestionnaireResponseHasSiblingItemsWhenTheyShouldBeChildItems() throws Exception {
Questionnaire q = new Questionnaire(); Questionnaire q = new Questionnaire();