Validation fixes
This commit is contained in:
parent
9226e43090
commit
d63e289cbe
|
@ -41,6 +41,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.util.DeleteConflict;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
@ -129,9 +130,20 @@ public class FhirResourceDaoDstu3<T extends IAnyResource> extends BaseHapiFhirRe
|
|||
|
||||
validator.registerValidatorModule(new IdChecker(theMode));
|
||||
|
||||
IBaseResource resourceToValidateById = null;
|
||||
if (theId != null && theId.hasResourceType() && theId.hasIdPart()) {
|
||||
Class<? extends IBaseResource> type = getContext().getResourceDefinition(theId.getResourceType()).getImplementingClass();
|
||||
IFhirResourceDao<? extends IBaseResource> dao = getDao(type);
|
||||
resourceToValidateById = dao.read(theId, theRequestDetails);
|
||||
}
|
||||
|
||||
ValidationResult result;
|
||||
if (theResource == null) {
|
||||
throw new InvalidRequestException("No resource supplied for $validate operation (resource is required unless mode is \"delete\")");
|
||||
if (resourceToValidateById != null) {
|
||||
result = validator.validateWithResult(resourceToValidateById);
|
||||
} else {
|
||||
throw new InvalidRequestException("No resource supplied for $validate operation (resource is required unless mode is \"delete\")");
|
||||
}
|
||||
} else if (isNotBlank(theRawResource)) {
|
||||
result = validator.validateWithResult(theRawResource);
|
||||
} else {
|
||||
|
|
|
@ -610,12 +610,12 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
public void testSearchCompositeParamDate() {
|
||||
Observation o1 = new Observation();
|
||||
o1.getCode().addCoding().setSystem("foo").setCode("testSearchCompositeParamDateN01");
|
||||
o1.setValue(new Period().setStartElement(new DateTimeType("2001-01-01T11:11:11")).setEndElement(new DateTimeType("2001-01-01T12:11:11")));
|
||||
o1.setValue(new Period().setStartElement(new DateTimeType("2001-01-01T11:11:11Z")).setEndElement(new DateTimeType("2001-01-01T12:11:11Z")));
|
||||
IIdType id1 = myObservationDao.create(o1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Observation o2 = new Observation();
|
||||
o2.getCode().addCoding().setSystem("foo").setCode("testSearchCompositeParamDateN01");
|
||||
o2.setValue(new Period().setStartElement(new DateTimeType("2001-01-02T11:11:11")).setEndElement(new DateTimeType("2001-01-02T12:11:11")));
|
||||
o2.setValue(new Period().setStartElement(new DateTimeType("2001-01-02T11:11:11Z")).setEndElement(new DateTimeType("2001-01-02T12:11:11Z")));
|
||||
IIdType id2 = myObservationDao.create(o2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
{
|
||||
|
@ -627,21 +627,21 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
{
|
||||
TokenParam v0 = new TokenParam("foo", "testSearchCompositeParamDateN01");
|
||||
DateParam v1 = new DateParam(">2001-01-01T10:12:12");
|
||||
DateParam v1 = new DateParam(">2001-01-01T10:12:12Z");
|
||||
CompositeParam<TokenParam, DateParam> val = new CompositeParam<TokenParam, DateParam>(v0, v1);
|
||||
IBundleProvider result = myObservationDao.search(Observation.SP_CODE_VALUE_DATE, val);
|
||||
assertThat(toUnqualifiedVersionlessIds(result), containsInAnyOrder(id1, id2));
|
||||
}
|
||||
{
|
||||
TokenParam v0 = new TokenParam("foo", "testSearchCompositeParamDateN01");
|
||||
DateParam v1 = new DateParam("gt2001-01-01T11:12:12");
|
||||
DateParam v1 = new DateParam("gt2001-01-01T11:12:12Z");
|
||||
CompositeParam<TokenParam, DateParam> val = new CompositeParam<TokenParam, DateParam>(v0, v1);
|
||||
IBundleProvider result = myObservationDao.search(Observation.SP_CODE_VALUE_DATE, val);
|
||||
assertThat(toUnqualifiedVersionlessIds(result), containsInAnyOrder(id1, id2));
|
||||
}
|
||||
{
|
||||
TokenParam v0 = new TokenParam("foo", "testSearchCompositeParamDateN01");
|
||||
DateParam v1 = new DateParam("gt2001-01-01T15:12:12");
|
||||
DateParam v1 = new DateParam("gt2001-01-01T15:12:12Z");
|
||||
CompositeParam<TokenParam, DateParam> val = new CompositeParam<TokenParam, DateParam>(v0, v1);
|
||||
IBundleProvider result = myObservationDao.search(Observation.SP_CODE_VALUE_DATE, val);
|
||||
assertThat(toUnqualifiedVersionlessIds(result), containsInAnyOrder(id2));
|
||||
|
|
|
@ -10,6 +10,8 @@ import static org.junit.Assert.fail;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -135,7 +137,7 @@ public class ResourceProviderDstu1Test extends BaseJpaTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithClientSuppliedId() {
|
||||
public void testCreateWithClientSuppliedId() throws Exception {
|
||||
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testCreateWithId01");
|
||||
|
||||
Patient p1 = new Patient();
|
||||
|
|
|
@ -2706,6 +2706,30 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceInstanceOnServer() throws IOException {
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addGiven("James");
|
||||
patient.setBirthDateElement(new DateType("2011-02-02"));
|
||||
patient.addContact().setGender(AdministrativeGender.MALE);
|
||||
patient.addCommunication().setPreferred(true); // missing language
|
||||
|
||||
IIdType id = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
HttpGet get = new HttpGet(ourServerBase + "/Patient/" + id.getIdPart() + "/$validate");
|
||||
CloseableHttpResponse response = ourHttpClient.execute(get);
|
||||
try {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent());
|
||||
ourLog.info(resp);
|
||||
assertEquals(412, response.getStatusLine().getStatusCode());
|
||||
assertThat(resp, containsString("SHALL at least contain a contact's details or a reference to an organization"));
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Y
|
||||
@Test
|
||||
public void testValidateResourceHuge() throws IOException {
|
||||
|
|
|
@ -813,6 +813,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private void checkPrimitive(List<ValidationMessage> errors, String path, String type, ElementDefinition context, Element e, StructureDefinition profile) {
|
||||
if (isBlank(e.primitiveValue())) {
|
||||
return;
|
||||
}
|
||||
if (type.equals("boolean")) {
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, "true".equals(e.primitiveValue()) || "false".equals(e.primitiveValue()), "boolean values must be 'true' or 'false'");
|
||||
}
|
||||
|
@ -821,7 +824,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !e.primitiveValue().startsWith("uuid:"), "URI values cannot start with uuid:");
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, e.primitiveValue().equals(e.primitiveValue().trim()), "URI values cannot have leading or trailing whitespace");
|
||||
}
|
||||
if (!type.equalsIgnoreCase("string") && e.hasPrimitiveValue()) {
|
||||
if (!type.equalsIgnoreCase("string")) {
|
||||
if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, e.primitiveValue() == null || e.primitiveValue().length() > 0, "@value cannot be empty")) {
|
||||
warning(errors, IssueType.INVALID, e.line(), e.col(), path, e.primitiveValue() == null || e.primitiveValue().trim().equals(e.primitiveValue()), "value should not start or finish with whitespace");
|
||||
}
|
||||
|
@ -842,13 +845,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, yearIsValid(e.primitiveValue()), "The value '" + e.primitiveValue() + "' does not have a valid year");
|
||||
}
|
||||
|
||||
if (type.equals("code") && e.primitiveValue() != null) {
|
||||
if (type.equals("code")) {
|
||||
// Technically, a code is restricted to string which has at least one character and no leading or trailing whitespace, and where there is no whitespace
|
||||
// other than single spaces in the contents
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, passesCodeWhitespaceRules(e.primitiveValue()), "The code '" + e.primitiveValue() + "' is not valid (whitespace rules)");
|
||||
}
|
||||
|
||||
if (context.hasBinding() && e.primitiveValue() != null) {
|
||||
if (context.hasBinding()) {
|
||||
checkPrimitiveBinding(errors, path, type, context, e, profile);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
|
@ -30,6 +31,7 @@ import org.junit.BeforeClass;
|
|||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Validate;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
@ -48,6 +50,7 @@ public class ValidateDstu3Test {
|
|||
private static int ourPort;
|
||||
private static Server ourServer;
|
||||
public static Patient ourLastPatient;
|
||||
private static IdType ourLastId;
|
||||
|
||||
@Before()
|
||||
public void before() {
|
||||
|
@ -58,7 +61,6 @@ public class ValidateDstu3Test {
|
|||
ourLastProfile = null;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testValidate() throws Exception {
|
||||
|
||||
|
@ -218,6 +220,25 @@ public class ValidateDstu3Test {
|
|||
assertThat(resp, stringContainsInOrder("<OperationOutcome", "FOOBAR"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateWithGet() throws Exception {
|
||||
ourOutcomeToReturn = new OperationOutcome();
|
||||
ourOutcomeToReturn.addIssue().setDiagnostics("FOOBAR");
|
||||
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$validate");
|
||||
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String resp = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(resp, stringContainsInOrder("<OperationOutcome", "FOOBAR"));
|
||||
assertEquals(null, ourLastPatient);
|
||||
assertEquals("Patient", ourLastId.getResourceType());
|
||||
assertEquals("123", ourLastId.getIdPart());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() throws Exception {
|
||||
ourServer.stop();
|
||||
|
@ -271,15 +292,16 @@ public class ValidateDstu3Test {
|
|||
}
|
||||
|
||||
@Validate()
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient, @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile) {
|
||||
|
||||
public MethodOutcome validatePatient(@ResourceParam Patient thePatient, @IdParam IdType theId, @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile) {
|
||||
|
||||
ourLastPatient = thePatient;
|
||||
ourLastId = theId;
|
||||
IdType id;
|
||||
if (thePatient != null) {
|
||||
id = new IdType(thePatient.getIdentifier().get(0).getValue());
|
||||
if (thePatient.getIdElement().isEmpty() == false) {
|
||||
id = thePatient.getIdElement();
|
||||
}
|
||||
id = new IdType(thePatient.getIdentifier().get(0).getValue());
|
||||
if (thePatient.getIdElement().isEmpty() == false) {
|
||||
id = thePatient.getIdElement();
|
||||
}
|
||||
} else {
|
||||
id = new IdType("1");
|
||||
}
|
||||
|
|
|
@ -422,6 +422,60 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(output.toString(), 0, output.getMessages().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResourceWithEmptyPrimitive() {
|
||||
// @formatter:off
|
||||
String input = "<Patient xmlns=\"http://hl7.org/fhir\"><name><given/></name></Patient>";
|
||||
// @formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
assertThat(output.getMessages().get(0).getMessage(), containsString("Element must have some content"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResourceWithPrimitiveContainingOnlyAnExtension() {
|
||||
// @formatter:off
|
||||
String input = "<ActivityDefinition xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
" <id value=\"referralToMentalHealthCare\"/>\n" +
|
||||
" <status value=\"draft\"/>\n" +
|
||||
" <description value=\"refer to primary care mental-health integrated care program for evaluation and treatment of mental health conditions now\"/>\n" +
|
||||
" <relatedResource>\n" +
|
||||
" <type value=\"citation\"/>\n" +
|
||||
" <document>\n" +
|
||||
" <url value=\"blah blah blah\"/>\n" +
|
||||
" <title value=\"citation title\"/>\n" +
|
||||
" </document>\n" +
|
||||
" <resource>\n" +
|
||||
" <reference value=\"DocumentReference/123\"/> <!-- DocumentReference -->\n" +
|
||||
" <display value=\"citation title\"/>\n" +
|
||||
" </resource>\n" +
|
||||
" </relatedResource>\n" +
|
||||
" <category value=\"referral\"/>\n" +
|
||||
" <code>\n" +
|
||||
" <coding>\n" +
|
||||
" <!-- Error: Connection to http://localhost:960 refused -->\n" +
|
||||
" <!--<system value=\"http://snomed.info/sct\"/>-->\n" +
|
||||
" <code value=\"306206005\"/>\n" +
|
||||
" </coding>\n" +
|
||||
" </code>\n" +
|
||||
" <!-- Specifying this this way results in a null reference exception in the validator -->\n" +
|
||||
" <timingTiming>\n" +
|
||||
" <event>\n" +
|
||||
" <extension url=\"http://fhir.org/cql-expression\">\n" +
|
||||
" <valueString value=\"Now()\"/>\n" +
|
||||
" </extension>\n" +
|
||||
" </event>\n" +
|
||||
" </timingTiming>\n" +
|
||||
" <participantType value=\"practitioner\"/>\n" +
|
||||
" </ActivityDefinition>";
|
||||
// @formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
List<SingleValidationMessage> res = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertEquals(output.toString(), 0, res.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResourceBadAttributes() {
|
||||
//@formatter:off
|
||||
|
|
|
@ -404,6 +404,10 @@
|
|||
end of the resource instead of in the correct
|
||||
order
|
||||
</action>
|
||||
<action type="fix">
|
||||
Fix STU3 JPA resource providers to allow validate operation
|
||||
at instance level
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.5" date="2016-04-20">
|
||||
<action type="fix" issue="339">
|
||||
|
|
Loading…
Reference in New Issue