Fix validation issue with open-choice questions in R4 questionnaires
This commit is contained in:
parent
56965820ea
commit
3b8b2a94c3
|
@ -0,0 +1,37 @@
|
|||
package org.hl7.fhir.convertors.conv40_50;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class Questionnaire40_50Test {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test r5 -> r4 Questionnaire conversion.")
|
||||
public void testR5_R4() throws IOException {
|
||||
InputStream r4_input = this.getClass().getResourceAsStream("/q_open_40.json");
|
||||
String source = TextFile.streamToString(r4_input);
|
||||
System.out.println(source);
|
||||
|
||||
org.hl7.fhir.r4.model.Questionnaire r4_actual = (org.hl7.fhir.r4.model.Questionnaire) new org.hl7.fhir.r4.formats.JsonParser().parse(source);
|
||||
org.hl7.fhir.r5.model.Resource r5_conv = VersionConvertorFactory_40_50.convertResource(r4_actual);
|
||||
|
||||
org.hl7.fhir.r5.formats.JsonParser r5_parser = new org.hl7.fhir.r5.formats.JsonParser();
|
||||
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
r5_parser.compose(stream, r5_conv);
|
||||
|
||||
org.hl7.fhir.r5.model.Resource r5_streamed = (org.hl7.fhir.r5.model.Questionnaire) new org.hl7.fhir.r5.formats.JsonParser().parse(new ByteArrayInputStream(stream.toByteArray()));
|
||||
org.hl7.fhir.r4.model.Resource r4_conv = VersionConvertorFactory_40_50.convertResource(r5_streamed);
|
||||
|
||||
assertTrue(r4_actual.equalsDeep(r4_conv), "should be the same");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
{"resourceType": "Questionnaire",
|
||||
"id": "ed364266b937bb3bd73082b1",
|
||||
"item": [
|
||||
{
|
||||
"extension": [
|
||||
{
|
||||
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
||||
"valueCodeableConcept": {
|
||||
"coding": [
|
||||
{
|
||||
"code": "editableDropdown"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "specimen-source",
|
||||
"answerOption": [
|
||||
{
|
||||
"valueCoding": {
|
||||
"code": "U",
|
||||
"display": "Urine"
|
||||
}
|
||||
},
|
||||
{
|
||||
"valueCoding": {
|
||||
"code": "B",
|
||||
"display": "Blood"
|
||||
}
|
||||
},
|
||||
{
|
||||
"valueCoding": {
|
||||
"code": "S",
|
||||
"display": "Saliva"
|
||||
}
|
||||
}
|
||||
],
|
||||
"code": [
|
||||
{
|
||||
"code": "specimen-source"
|
||||
}
|
||||
],
|
||||
"linkId": "specimen-source",
|
||||
"text": "Source of specimen",
|
||||
"type": "open-choice"
|
||||
}
|
||||
],
|
||||
"name": "Test Open Choice question",
|
||||
"status": "active",
|
||||
"subjectType": [
|
||||
"Patient"
|
||||
]
|
||||
}
|
|
@ -514,6 +514,7 @@ public class I18nConstants {
|
|||
public static final String QUESTIONNAIRE_QR_ITEM_ONLYONEI = "Questionnaire_QR_Item_OnlyOneI";
|
||||
public static final String QUESTIONNAIRE_QR_ITEM_ORDER = "Questionnaire_QR_Item_Order";
|
||||
public static final String QUESTIONNAIRE_QR_ITEM_STRINGNOOPTIONS = "Questionnaire_QR_Item_StringNoOptions";
|
||||
public static final String QUESTIONNAIRE_QR_ITEM_STRING_IN_CODING = "QUESTIONNAIRE_QR_ITEM_STRING_IN_CODING";
|
||||
public static final String QUESTIONNAIRE_QR_ITEM_TEXT = "Questionnaire_QR_Item_Text";
|
||||
public static final String QUESTIONNAIRE_QR_ITEM_TIMENOOPTIONS = "Questionnaire_QR_Item_TimeNoOptions";
|
||||
public static final String QUESTIONNAIRE_QR_ITEM_WRONGTYPE = "Questionnaire_QR_Item_WrongType";
|
||||
|
|
|
@ -524,6 +524,7 @@ Questionnaire_QR_Item_NoOptionsCoding = Option list has no option values of type
|
|||
Questionnaire_QR_Item_NoOptionsDate = Option list has no option values of type date
|
||||
Questionnaire_QR_Item_NoOptionsInteger = Option list has no option values of type integer
|
||||
Questionnaire_QR_Item_NoOptionsString = Option list has no option values of type string
|
||||
QUESTIONNAIRE_QR_ITEM_STRING_IN_CODING = The string value ''{0}'' matches an entry in the list of valid Codings, so this is probably an error
|
||||
Questionnaire_QR_Item_NoOptionsTime = Option list has no option values of type time
|
||||
Questionnaire_QR_Item_NoString = The string {0} is not a valid option
|
||||
Questionnaire_QR_Item_NoTime = The time {0} is not a valid option
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hl7.fhir.r5.model.Coding;
|
|||
import org.hl7.fhir.r5.model.DateType;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.Questionnaire;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireAnswerConstraint;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemAnswerOptionComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType;
|
||||
|
@ -812,7 +813,7 @@ public class QuestionnaireValidator extends BaseValidator {
|
|||
}
|
||||
|
||||
private boolean checkOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, String type) {
|
||||
return checkOption(errors, answer, stack, qSrc, qItem, type, false);
|
||||
return checkOption(errors, answer, stack, qSrc, qItem, type, qItem.getAnswerConstraint() == QuestionnaireAnswerConstraint.OPTIONSORSTRING);
|
||||
}
|
||||
|
||||
private boolean checkOption(List<ValidationMessage> errors, Element answer, NodeStack stack, QuestionnaireWithContext qSrc, QuestionnaireItemComponent qItem, String type, boolean openChoice) {
|
||||
|
@ -928,31 +929,29 @@ public class QuestionnaireValidator extends BaseValidator {
|
|||
Element v = answer.getNamedChild("valueString", false);
|
||||
NodeStack ns = stack.push(v, -1, null, null);
|
||||
if (qItem.getAnswerOption().size() > 0) {
|
||||
List<StringType> list = new ArrayList<StringType>();
|
||||
boolean found = false;
|
||||
boolean empty = true;
|
||||
for (QuestionnaireItemAnswerOptionComponent components : qItem.getAnswerOption()) {
|
||||
try {
|
||||
if (components.getValue() != null) {
|
||||
list.add(components.getValueStringType());
|
||||
}
|
||||
} catch (FHIRException e) {
|
||||
// If it's the wrong type, just keep going
|
||||
if (components.getValue() != null && components.hasValueStringType()) {
|
||||
empty = false;
|
||||
found = found || components.getValue().primitiveValue().equals((v.primitiveValue()));
|
||||
}
|
||||
}
|
||||
if (!openChoice) {
|
||||
if (list.isEmpty()) {
|
||||
if (empty) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSSTRING) && ok;
|
||||
} else {
|
||||
boolean found = false;
|
||||
for (StringType item : list) {
|
||||
if (item.getValue().equals((v.primitiveValue()))) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOSTRING, v.primitiveValue()) && ok;
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOSTRING, v.primitiveValue()) && ok;
|
||||
}
|
||||
} else {
|
||||
found = false;
|
||||
for (QuestionnaireItemAnswerOptionComponent components : qItem.getAnswerOption()) {
|
||||
if (components.getValue() != null && components.hasValueCoding()) {
|
||||
Coding c = components.getValueCoding();
|
||||
found = found || (c.hasDisplay() && c.getDisplay().equalsIgnoreCase(v.primitiveValue())) || (c.hasCode() && c.getCode().equalsIgnoreCase(v.primitiveValue()));
|
||||
}
|
||||
}
|
||||
ok = warning(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), !found, I18nConstants.QUESTIONNAIRE_QR_ITEM_STRING_IN_CODING, v.primitiveValue()) && ok;
|
||||
}
|
||||
} else {
|
||||
hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_STRINGNOOPTIONS);
|
||||
|
|
Loading…
Reference in New Issue