Don't evaluate Extensions when determining type of answer

This commit is contained in:
Matti Uusitalo 2018-12-13 12:12:56 +02:00
parent 82387e6902
commit c85f4b8362
3 changed files with 57 additions and 9 deletions

View File

@ -11,7 +11,7 @@
<artifactId>hapi-fhir-validation</artifactId> <artifactId>hapi-fhir-validation</artifactId>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<version>3.6.2-PHRFIX</version> <version>3.6.3-PHRFIX</version>
<name>HAPI FHIR - Validation</name> <name>HAPI FHIR - Validation</name>

View File

@ -64,11 +64,33 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator {
.anyMatch(answer -> evaluateAnswer(answer, enableCondition.getAnswer(), enableCondition.getOperator())); .anyMatch(answer -> evaluateAnswer(answer, enableCondition.getAnswer(), enableCondition.getOperator()));
return new EnableWhenResult(result, linkId, enableCondition, questionnaireResponse); return new EnableWhenResult(result, linkId, enableCondition, questionnaireResponse);
} }
public Type convertToType(Element element) {
Type b = new Factory().create(element.fhirType());
if (b instanceof PrimitiveType) {
((PrimitiveType<?>) b).setValueAsString(element.primitiveValue());
} else {
for (Element child : element.getChildren()) {
if (!isExtension(child)) {
b.setProperty(child.getName(), convertToType(child));
}
}
}
return b;
}
private boolean isExtension(Element element) {
return "Extension".equals(element.fhirType());
}
protected boolean evaluateAnswer(Element answer, Type expectedAnswer, QuestionnaireItemOperator questionnaireItemOperator) { protected boolean evaluateAnswer(Element answer, Type expectedAnswer, QuestionnaireItemOperator questionnaireItemOperator) {
Type actualAnswer; Type actualAnswer;
if (isExtension(answer)) {
return false;
}
try { try {
actualAnswer = answer.asType(); actualAnswer = convertToType(answer);
} catch (FHIRException e) { } catch (FHIRException e) {
throw new UnprocessableEntityException("Unexpected answer type", e); throw new UnprocessableEntityException("Unexpected answer type", e);
} }
@ -80,7 +102,7 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator {
} else if ((expectedAnswer instanceof PrimitiveType)) { } else if ((expectedAnswer instanceof PrimitiveType)) {
return comparePrimitiveAnswer((PrimitiveType<?>)actualAnswer, (PrimitiveType<?>)expectedAnswer, questionnaireItemOperator); return comparePrimitiveAnswer((PrimitiveType<?>)actualAnswer, (PrimitiveType<?>)expectedAnswer, questionnaireItemOperator);
} else if (expectedAnswer instanceof Quantity) { } else if (expectedAnswer instanceof Quantity) {
return compareQuantityAnswer((Quantity)expectedAnswer, (Quantity)actualAnswer, questionnaireItemOperator); return compareQuantityAnswer((Quantity)actualAnswer, (Quantity)expectedAnswer, questionnaireItemOperator);
} }
// TODO: Attachment, reference? // TODO: Attachment, reference?
throw new UnprocessableEntityException("Unimplemented answer type: " + expectedAnswer.getClass()); throw new UnprocessableEntityException("Unimplemented answer type: " + expectedAnswer.getClass());
@ -142,14 +164,9 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator {
return item.getChildrenByName(ANSWER_ELEMENT) return item.getChildrenByName(ANSWER_ELEMENT)
.stream() .stream()
.flatMap(c -> c.getChildren().stream()) .flatMap(c -> c.getChildren().stream())
.filter(DefaultEnableWhenEvaluator::notExtension)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private static boolean notExtension(Element e) {
return !Extension.class.isAssignableFrom(e.getClass());
}
private boolean compareCodingAnswer(Coding expectedAnswer, Coding actualAnswer, QuestionnaireItemOperator questionnaireItemOperator) { private boolean compareCodingAnswer(Coding expectedAnswer, Coding actualAnswer, QuestionnaireItemOperator questionnaireItemOperator) {
boolean result = compareSystems(expectedAnswer, actualAnswer) && compareCodes(expectedAnswer, actualAnswer); boolean result = compareSystems(expectedAnswer, actualAnswer) && compareCodes(expectedAnswer, actualAnswer);
if (questionnaireItemOperator == QuestionnaireItemOperator.EQUAL){ if (questionnaireItemOperator == QuestionnaireItemOperator.EQUAL){

View File

@ -18,6 +18,7 @@ import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemComponent;
import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemEnableWhenComponent; import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemEnableWhenComponent;
import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemOptionComponent; import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemOptionComponent;
import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType; import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseItemComponent; import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseItemComponent;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseStatus; import org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseStatus;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -33,6 +34,9 @@ import java.util.List;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.BOOLEAN;
import static org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType.CHOICE;
import static org.hl7.fhir.dstu3.model.QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
@ -551,7 +555,34 @@ public class QuestionnaireResponseValidatorDstu3Test {
errors.getMessages().stream().filter(vm -> vm.getMessage().contains("Structural Error")) errors.getMessages().stream().filter(vm -> vm.getMessage().contains("Structural Error"))
.anyMatch(vm -> vm.getMessage().contains("link1"))); .anyMatch(vm -> vm.getMessage().contains("link1")));
} }
@Test
public void testAnswerIsValueCodingWithExtensionInside() throws Exception {
Questionnaire q = new Questionnaire();
Coding qcoding = new Coding();
qcoding.setCode("1293");
q.addItem().setLinkId("1B").setRequired(true).setType(CHOICE).addOption().setValue(qcoding);
q.addItem().setLinkId("2B").setType(BOOLEAN).addEnableWhen().setQuestion("1B").setAnswer(qcoding);
QuestionnaireResponse qr = new QuestionnaireResponse();
qr.setStatus(COMPLETED);
qr.getQuestionnaire().setReference(QUESTIONNAIRE_URL);
QuestionnaireResponseItemComponent qrItem = qr.addItem().setLinkId("1B");
Coding coding = new Coding();
coding.setCode("1293");
QuestionnaireResponseItemAnswerComponent answer = qrItem.addAnswer();
answer.setValue(coding);
coding.addExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-hidden", new BooleanType(true));
qr.addItem().setLinkId("2B").addAnswer().setValue(new BooleanType(true));
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 testEmbeddedItemInChoice() { public void testEmbeddedItemInChoice() {
String questionnaireRef = QUESTIONNAIRE_URL; String questionnaireRef = QUESTIONNAIRE_URL;