Adding more tests for endpoint validation and repoitory validation with javascript configuration. Some changes in existing tests.
This commit is contained in:
parent
d3b1d75dce
commit
80519bf0c4
|
@ -0,0 +1,171 @@
|
||||||
|
package ca.uhn.fhir.jpa.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||||
|
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||||
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.PrePopulatedValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
|
import org.hl7.fhir.r4.model.Meta;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class EndpointResourceValidationR4Test extends BaseResourceProviderR4Test {
|
||||||
|
private static final String myResourceType = "Patient";
|
||||||
|
private final String myProfile = "http://example.org/fhir/StructureDefinition/TestPatient";
|
||||||
|
private PrePopulatedValidationSupport myPrePopulatedValidationSupport;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before() {
|
||||||
|
CachingValidationSupport myValidationSupport = createCachingValidationSupport();
|
||||||
|
FhirInstanceValidator fhirInstanceValidator = new FhirInstanceValidator(myValidationSupport);
|
||||||
|
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
|
||||||
|
interceptor.addValidatorModule(fhirInstanceValidator);
|
||||||
|
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||||
|
interceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||||
|
myServer.registerInterceptor(interceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private CachingValidationSupport createCachingValidationSupport() {
|
||||||
|
myPrePopulatedValidationSupport = new PrePopulatedValidationSupport(myFhirContext);
|
||||||
|
ValidationSupportChain chain = new ValidationSupportChain(
|
||||||
|
new DefaultProfileValidationSupport(myFhirContext),
|
||||||
|
new SnapshotGeneratingValidationSupport(myFhirContext),
|
||||||
|
new CommonCodeSystemsTerminologyService(myFhirContext),
|
||||||
|
new InMemoryTerminologyServerValidationSupport(myFhirContext),
|
||||||
|
myPrePopulatedValidationSupport);
|
||||||
|
return new CachingValidationSupport(chain, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatientRequest_withProfileNotRegistered_unknownProfile() {
|
||||||
|
createProfile(myProfile, "1", "Patient.identifier");
|
||||||
|
|
||||||
|
final Patient patient = new Patient();
|
||||||
|
patient.setMeta(new Meta().addProfile(myProfile));
|
||||||
|
|
||||||
|
try {
|
||||||
|
myClient.create().resource(patient).execute();
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("HTTP 422 Unprocessable Entity: Profile reference '" + myProfile + "' has not been checked because it is unknown", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatientRequest_withProfileNoVersion_throwsExceptionWithLatestVersion() {
|
||||||
|
createAndRegisterProfile("1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile("2", "Patient.name");
|
||||||
|
|
||||||
|
final Patient patient = new Patient();
|
||||||
|
patient.setMeta(new Meta().addProfile(myProfile));
|
||||||
|
|
||||||
|
try {
|
||||||
|
myClient.create().resource(patient).execute();
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("HTTP 422 Unprocessable Entity: Patient.name: minimum required = 1, but only found 0 (from " + myProfile + "|2)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatientRequest_withProfileWithVersion_throwsExceptionWithSpecifiedVersion() {
|
||||||
|
createAndRegisterProfile("1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile("2", "Patient.name");
|
||||||
|
|
||||||
|
final Patient patient = new Patient();
|
||||||
|
patient.setMeta(new Meta().addProfile(myProfile + "|1"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
myClient.create().resource(patient).execute();
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("HTTP 422 Unprocessable Entity: Patient.identifier: minimum required = 1, but only found 0 (from " + myProfile + "|1)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatientRequest_withMultipleProfiles_throwsExceptionWithFirstDeclaredProfile() {
|
||||||
|
final String sdIdentifier = myProfile + "-identifier";
|
||||||
|
final String sdName = myProfile + "-name";
|
||||||
|
|
||||||
|
createAndRegisterProfile(sdIdentifier, "1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile(sdName, "1", "Patient.name");
|
||||||
|
|
||||||
|
final Patient patient = new Patient();
|
||||||
|
patient.setMeta(new Meta().addProfile(sdIdentifier).addProfile(sdName));
|
||||||
|
|
||||||
|
try {
|
||||||
|
myClient.create().resource(patient).execute();
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("HTTP 422 Unprocessable Entity: Patient.identifier: minimum required = 1, but only found 0 (from " + sdIdentifier + "|1)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatientRequest_withMultipleVersions_throwsExceptionWithFirstDeclaredProfile() {
|
||||||
|
createAndRegisterProfile(myProfile, "1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile(myProfile, "2", "Patient.name");
|
||||||
|
createAndRegisterProfile(myProfile, "3", "Patient.birthDate");
|
||||||
|
|
||||||
|
final Patient patient = new Patient();
|
||||||
|
patient.setMeta(new Meta()
|
||||||
|
.addProfile(myProfile + "|2")
|
||||||
|
.addProfile(myProfile + "|1")
|
||||||
|
.addProfile(myProfile + "|3"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
myClient.create().resource(patient).execute();
|
||||||
|
fail();
|
||||||
|
} catch (UnprocessableEntityException e) {
|
||||||
|
assertEquals("HTTP 422 Unprocessable Entity: Patient.name: minimum required = 1, but only found 0 (from " + myProfile + "|2)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAndRegisterProfile(String theVersion, String thePath) {
|
||||||
|
createAndRegisterProfile(myProfile, theVersion, thePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAndRegisterProfile(String theUrl, String theVersion, String thePath) {
|
||||||
|
StructureDefinition sd = createProfile(theUrl, theVersion, thePath);
|
||||||
|
myPrePopulatedValidationSupport.addStructureDefinition(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StructureDefinition createProfile(String theUrl, String theVersion, String thePath) {
|
||||||
|
final String baseProfile = "http://hl7.org/fhir/StructureDefinition/Patient";
|
||||||
|
final String profileId = "TestProfile";
|
||||||
|
|
||||||
|
StructureDefinition sd = new StructureDefinition()
|
||||||
|
.setUrl(theUrl).setVersion(theVersion)
|
||||||
|
.setBaseDefinition(baseProfile)
|
||||||
|
.setType(myResourceType)
|
||||||
|
.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
||||||
|
sd.setId(profileId);
|
||||||
|
sd.getDifferential().addElement()
|
||||||
|
.setPath(thePath)
|
||||||
|
.setMin(1)
|
||||||
|
.setId(thePath);
|
||||||
|
|
||||||
|
DaoMethodOutcome outcome = myStructureDefinitionDao.update(sd, new SystemRequestDetails());
|
||||||
|
assertNotNull(outcome.getResource());
|
||||||
|
return (StructureDefinition) outcome.getResource();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
package ca.uhn.fhir.jpa.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||||
|
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||||
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
|
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||||
|
import ca.uhn.fhir.validation.ValidationResult;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.PrePopulatedValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||||
|
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
public class OnDemandResourceValidationR4Test extends BaseResourceProviderR4Test {
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forR4();
|
||||||
|
private static final String myResourceType = "Patient";
|
||||||
|
private final String myProfile = "http://example.org/fhir/StructureDefinition/TestPatient";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateStructureDefinition_createMultipleWithWithSameUrl_isStoredSuccessfully() {
|
||||||
|
createProfile("1", "Patient.identifier");
|
||||||
|
createProfile("2", "Patient.name");
|
||||||
|
createProfile("3", "Patient.birthdate");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FhirValidator myFhirValidator;
|
||||||
|
private static PrePopulatedValidationSupport ourValidationSupport;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before() {
|
||||||
|
myFhirValidator = ourCtx.newValidator();
|
||||||
|
myFhirValidator.setValidateAgainstStandardSchema(false);
|
||||||
|
myFhirValidator.setValidateAgainstStandardSchematron(false);
|
||||||
|
|
||||||
|
ourValidationSupport = new PrePopulatedValidationSupport(ourCtx);
|
||||||
|
|
||||||
|
ValidationSupportChain chain = new ValidationSupportChain(
|
||||||
|
new DefaultProfileValidationSupport(ourCtx),
|
||||||
|
new SnapshotGeneratingValidationSupport(ourCtx),
|
||||||
|
new CommonCodeSystemsTerminologyService(ourCtx),
|
||||||
|
new InMemoryTerminologyServerValidationSupport(ourCtx),
|
||||||
|
ourValidationSupport);
|
||||||
|
CachingValidationSupport myValidationSupport = new CachingValidationSupport(chain, true);
|
||||||
|
FhirInstanceValidator myInstanceVal = new FhirInstanceValidator(myValidationSupport);
|
||||||
|
myFhirValidator.registerValidatorModule(myInstanceVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePatient_withProfileNotRegistered_unknownProfile() {
|
||||||
|
createProfile(myProfile, "1", "Patient.identifier");
|
||||||
|
|
||||||
|
IIdType idType = createPatient(withProfile(myProfile));
|
||||||
|
Patient patient = myPatientDao.read(idType, mySrd);
|
||||||
|
|
||||||
|
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
||||||
|
assertFalse(validationResult.isSuccessful());
|
||||||
|
assertEquals(1, validationResult.getMessages().size());
|
||||||
|
|
||||||
|
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
||||||
|
assertEquals("Profile reference '" + myProfile + "' has not been checked because it is unknown", message.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePatient_withProfileNoVersion_shouldUsesLatestVersion() {
|
||||||
|
createAndRegisterProfile(myProfile, "1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile(myProfile, "2", "Patient.name");
|
||||||
|
|
||||||
|
IIdType idType = createPatient(withProfile(myProfile));
|
||||||
|
Patient patient = myPatientDao.read(idType, mySrd);
|
||||||
|
|
||||||
|
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
||||||
|
assertFalse(validationResult.isSuccessful());
|
||||||
|
assertEquals(1, validationResult.getMessages().size());
|
||||||
|
|
||||||
|
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
||||||
|
assertEquals("Patient.name: minimum required = 1, but only found 0 (from " + myProfile + "|2)", message.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePatient_withProfileWithVersion_shouldUseSpecifiedVersion() {
|
||||||
|
|
||||||
|
createAndRegisterProfile(myProfile, "1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile(myProfile, "2", "Patient.name");
|
||||||
|
|
||||||
|
IIdType idType = createPatient(withProfile(myProfile + "|1"));
|
||||||
|
Patient patient = myPatientDao.read(idType, mySrd);
|
||||||
|
|
||||||
|
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
||||||
|
assertFalse(validationResult.isSuccessful());
|
||||||
|
assertEquals(1, validationResult.getMessages().size());
|
||||||
|
|
||||||
|
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
||||||
|
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + myProfile + "|1)", message.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePatient_withMultipleProfiles_validatesAgainstAllProfiles() {
|
||||||
|
final String sdIdentifier = myProfile + "-identifier";
|
||||||
|
final String sdName = myProfile + "-name";
|
||||||
|
|
||||||
|
createAndRegisterProfile(sdIdentifier, "1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile(sdName, "1", "Patient.name");
|
||||||
|
|
||||||
|
IIdType idType = createPatient(withProfile(sdIdentifier), withProfile(sdName));
|
||||||
|
Patient patient = myPatientDao.read(idType, mySrd);
|
||||||
|
|
||||||
|
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
||||||
|
assertFalse(validationResult.isSuccessful());
|
||||||
|
assertEquals(2, validationResult.getMessages().size());
|
||||||
|
|
||||||
|
Iterator<SingleValidationMessage> messageIterator = validationResult.getMessages().iterator();
|
||||||
|
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + myProfile + "-identifier|1)", messageIterator.next().getMessage());
|
||||||
|
assertEquals("Patient.name: minimum required = 1, but only found 0 (from " + myProfile + "-name|1)", messageIterator.next().getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePatient_withMultipleVersions_validatesAgainstFirstVersion() {
|
||||||
|
createAndRegisterProfile(myProfile, "1", "Patient.identifier");
|
||||||
|
createAndRegisterProfile(myProfile, "2", "Patient.name");
|
||||||
|
createAndRegisterProfile(myProfile, "3", "Patient.birthDate");
|
||||||
|
|
||||||
|
IIdType idType = createPatient(
|
||||||
|
withProfile(myProfile + "|2"),
|
||||||
|
withProfile(myProfile + "|1"),
|
||||||
|
withProfile(myProfile + "|3"));
|
||||||
|
Patient patient = myPatientDao.read(idType, mySrd);
|
||||||
|
|
||||||
|
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
||||||
|
assertFalse(validationResult.isSuccessful());
|
||||||
|
assertEquals(1, validationResult.getMessages().size());
|
||||||
|
|
||||||
|
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
||||||
|
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + myProfile + "|1)", message.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAndRegisterProfile(String theUrl, String theVersion, String thePath) {
|
||||||
|
StructureDefinition sd = createProfile(theUrl, theVersion, thePath);
|
||||||
|
ourValidationSupport.addStructureDefinition(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProfile(String theVersion, String theRequiredPath) {
|
||||||
|
createProfile(myProfile, theVersion, theRequiredPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StructureDefinition createProfile(String theUrl, String theVersion, String theRequiredPath) {
|
||||||
|
final String myResourceTypeDefinition = "http://hl7.org/fhir/StructureDefinition/Patient";
|
||||||
|
final String myProfileId = "TestProfile";
|
||||||
|
|
||||||
|
StructureDefinition sd = new StructureDefinition()
|
||||||
|
.setUrl(theUrl).setVersion(theVersion)
|
||||||
|
.setBaseDefinition(myResourceTypeDefinition)
|
||||||
|
.setType(myResourceType)
|
||||||
|
.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
||||||
|
sd.setId(myProfileId);
|
||||||
|
sd.getDifferential().addElement()
|
||||||
|
.setPath(theRequiredPath)
|
||||||
|
.setMin(1)
|
||||||
|
.setId(theRequiredPath);
|
||||||
|
|
||||||
|
DaoMethodOutcome outcome = myStructureDefinitionDao.update(sd, mySrd);
|
||||||
|
assertNotNull(outcome.getResource());
|
||||||
|
return (StructureDefinition) outcome.getResource();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
package ca.uhn.fhir.jpa.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
|
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||||
|
import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule;
|
||||||
|
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor;
|
||||||
|
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||||
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||||
|
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||||
|
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class RepositoryValidationOnCreateResourceR4Test extends BaseResourceProviderR4Test {
|
||||||
|
private static final String myResourceType = "Patient";
|
||||||
|
private final String myProfile = "http://example.org/fhir/StructureDefinition/TestPatient";
|
||||||
|
|
||||||
|
private static final FhirContext ourCtx = FhirContext.forR4();
|
||||||
|
private final RepositoryValidatingInterceptor myRepositoryValidatingInterceptor = new RepositoryValidatingInterceptor(ourCtx, Collections.emptyList());
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before() {
|
||||||
|
myInterceptorRegistry.registerInterceptor(myRepositoryValidatingInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void after() {
|
||||||
|
myInterceptorRegistry.unregisterInterceptor(myRepositoryValidatingInterceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient_withValidationRuleNoVersion_validatesAgainstLatestVersion() {
|
||||||
|
createProfile("1", "Patient.identifier");
|
||||||
|
createProfile("2", "Patient.name");
|
||||||
|
|
||||||
|
setupRepositoryValidationRules(myProfile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
createPatient(withProfile(myProfile));
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals(Msg.code(574)
|
||||||
|
+ "Patient.name: minimum required = 1, but only found 0 (from " + myProfile + "|2)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient_withValidationRuleWithVersion_unknownProfile() {
|
||||||
|
createProfile("1", "Patient.identifier");
|
||||||
|
createProfile("2", "Patient.name");
|
||||||
|
|
||||||
|
setupRepositoryValidationRules(myProfile + "|1");
|
||||||
|
|
||||||
|
try {
|
||||||
|
createPatient(withProfile(myProfile + "|1"));
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals(Msg.code(574) + "Profile reference '" + myProfile
|
||||||
|
+ "|1' has not been checked because it is unknown, and the validator is set to not fetch unknown profiles", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient_withProfileWithVersion_doesNotConform() {
|
||||||
|
setupRepositoryValidationRules(myProfile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
createPatient(withProfile(myProfile + "|1"));
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals(Msg.code(575) + "Resource of type \"" + myResourceType
|
||||||
|
+ "\" does not declare conformance to profile from: [" + myProfile + "]", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient_withValidationRuleWithVersion_doesNotConform() {
|
||||||
|
setupRepositoryValidationRules(myProfile + "|1");
|
||||||
|
try {
|
||||||
|
createPatient(withProfile(myProfile));
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals(Msg.code(575) + "Resource of type \"" + myResourceType
|
||||||
|
+ "\" does not declare conformance to profile from: [" + myProfile + "|1]", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePatient_withMultipleProfiles_validatesAgainstLastProfile() {
|
||||||
|
final String sdIdentifier = myProfile + "-identifier";
|
||||||
|
final String sdName = myProfile + "-name";
|
||||||
|
|
||||||
|
createProfile(sdIdentifier, "1", "Patient.identifier");
|
||||||
|
createProfile(sdName, "1", "Patient.name");
|
||||||
|
|
||||||
|
setupRepositoryValidationRules(sdIdentifier, sdName);
|
||||||
|
try {
|
||||||
|
createPatient(withProfile(sdIdentifier), withProfile(sdName));
|
||||||
|
fail();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertEquals(Msg.code(574)
|
||||||
|
+ "Patient.name: minimum required = 1, but only found 0 (from " + sdName + "|1)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupRepositoryValidationRules(String... theProfiles) {
|
||||||
|
List<IRepositoryValidatingRule> rules = myAppCtx
|
||||||
|
.getBean(RepositoryValidatingRuleBuilder.REPOSITORY_VALIDATING_RULE_BUILDER, RepositoryValidatingRuleBuilder.class)
|
||||||
|
.forResourcesOfType(myResourceType)
|
||||||
|
.requireAtLeastOneProfileOf(theProfiles)
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles()
|
||||||
|
.withBestPracticeWarningLevel(BestPracticeWarningLevel.Ignore)
|
||||||
|
.rejectOnSeverity("error")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
myRepositoryValidatingInterceptor.setRules(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProfile(String theVersion, String theRequiredPath) {
|
||||||
|
createProfile(myProfile, theVersion, theRequiredPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProfile(String theUrl, String theVersion, String thePath) {
|
||||||
|
final String baseProfile = "http://hl7.org/fhir/StructureDefinition/Patient";
|
||||||
|
final String profileId = "TestProfile";
|
||||||
|
|
||||||
|
StructureDefinition sd = new StructureDefinition()
|
||||||
|
.setUrl(theUrl).setVersion(theVersion)
|
||||||
|
.setBaseDefinition(baseProfile)
|
||||||
|
.setType(myResourceType)
|
||||||
|
.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
||||||
|
sd.setId(profileId);
|
||||||
|
sd.getDifferential().addElement()
|
||||||
|
.setPath(thePath)
|
||||||
|
.setMin(1)
|
||||||
|
.setId(thePath);
|
||||||
|
|
||||||
|
DaoMethodOutcome outcome = myStructureDefinitionDao.update(sd, new SystemRequestDetails());
|
||||||
|
assertNotNull(outcome.getResource());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,333 +0,0 @@
|
||||||
package ca.uhn.fhir.jpa.validation;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
|
||||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
|
||||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
|
||||||
import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule;
|
|
||||||
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor;
|
|
||||||
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder;
|
|
||||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
|
||||||
import ca.uhn.fhir.rest.gclient.TokenClientParam;
|
|
||||||
import ca.uhn.fhir.rest.param.UriParam;
|
|
||||||
import ca.uhn.fhir.rest.param.UriParamQualifierEnum;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
|
||||||
import ca.uhn.fhir.validation.FhirValidator;
|
|
||||||
import ca.uhn.fhir.validation.SingleValidationMessage;
|
|
||||||
import ca.uhn.fhir.validation.ValidationResult;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.PrePopulatedValidationSupport;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
|
||||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
|
||||||
import org.hl7.fhir.r4.model.StructureDefinition;
|
|
||||||
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Nested;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
|
||||||
|
|
||||||
public class ResourceValidationR4Test extends BaseResourceProviderR4Test {
|
|
||||||
private static final FhirContext ourCtx = FhirContext.forR4();
|
|
||||||
private static FhirValidator myFhirValidator;
|
|
||||||
private static PrePopulatedValidationSupport ourValidationSupport;
|
|
||||||
private static final String myResourceType = "Patient";
|
|
||||||
private static final String myResourceTypeDefinition = "http://hl7.org/fhir/StructureDefinition/Patient";
|
|
||||||
private static final String PATIENT_STRUCTURE_DEFINITION_URL = "http://example.org/fhir/StructureDefinition/TestPatient";
|
|
||||||
|
|
||||||
private final RepositoryValidatingInterceptor myRepositoryValidatingInterceptor = new RepositoryValidatingInterceptor(ourCtx, Collections.emptyList());
|
|
||||||
@Autowired
|
|
||||||
private ApplicationContext myApplicationContext;
|
|
||||||
|
|
||||||
private final String profile = PATIENT_STRUCTURE_DEFINITION_URL;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void setup() {
|
|
||||||
myFhirValidator = ourCtx.newValidator();
|
|
||||||
myFhirValidator.setValidateAgainstStandardSchema(false);
|
|
||||||
myFhirValidator.setValidateAgainstStandardSchematron(false);
|
|
||||||
|
|
||||||
ourValidationSupport = new PrePopulatedValidationSupport(ourCtx);
|
|
||||||
|
|
||||||
ValidationSupportChain chain = new ValidationSupportChain(
|
|
||||||
new DefaultProfileValidationSupport(ourCtx),
|
|
||||||
new SnapshotGeneratingValidationSupport(ourCtx),
|
|
||||||
new CommonCodeSystemsTerminologyService(ourCtx),
|
|
||||||
new InMemoryTerminologyServerValidationSupport(ourCtx),
|
|
||||||
ourValidationSupport);
|
|
||||||
CachingValidationSupport myValidationSupport = new CachingValidationSupport(chain, true);
|
|
||||||
FhirInstanceValidator myInstanceVal = new FhirInstanceValidator(myValidationSupport);
|
|
||||||
myFhirValidator.registerValidatorModule(myInstanceVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void before() {
|
|
||||||
myInterceptorRegistry.registerInterceptor(myRepositoryValidatingInterceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
public void after() {
|
|
||||||
myInterceptorRegistry.unregisterInterceptor(myRepositoryValidatingInterceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateStructureDefinition_createMultipleWithWithSameUrl_isStoredSuccessfully() {
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "2", "Patient.name");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "3", "Patient.birthdate");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
public class OnDemandResourceValidationTests {
|
|
||||||
@Test
|
|
||||||
public void testValidatePatient_withProfileIncludingVersion_shouldUseSpecifiedVersion() {
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "2", "Patient.name");
|
|
||||||
|
|
||||||
IIdType idType = createPatient(withProfile(profile + "|1"));
|
|
||||||
Patient patient = myPatientDao.read(idType, mySrd);
|
|
||||||
|
|
||||||
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
|
||||||
assertFalse(validationResult.isSuccessful());
|
|
||||||
assertEquals(1, validationResult.getMessages().size());
|
|
||||||
|
|
||||||
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
|
||||||
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + profile + "|1)", message.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidatePatient_withProfileNoVersion_shouldUsesLatestVersion() {
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "2", "Patient.name");
|
|
||||||
|
|
||||||
IIdType idType = createPatient(withProfile(profile));
|
|
||||||
Patient patient = myPatientDao.read(idType, mySrd);
|
|
||||||
|
|
||||||
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
|
||||||
assertFalse(validationResult.isSuccessful());
|
|
||||||
assertEquals(1, validationResult.getMessages().size());
|
|
||||||
|
|
||||||
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
|
||||||
assertEquals("Patient.name: minimum required = 1, but only found 0 (from " + profile + "|2)", message.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidatePatient_withMultipleProfilesDifferentUrls_validatesAgainstAllProfiles() {
|
|
||||||
final String sdIdentifier = PATIENT_STRUCTURE_DEFINITION_URL + "-identifier";
|
|
||||||
final String sdName = PATIENT_STRUCTURE_DEFINITION_URL + "-name";
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(sdIdentifier, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(sdName, "1", "Patient.name");
|
|
||||||
|
|
||||||
IIdType idType = createPatient(withProfile(sdIdentifier), withProfile(sdName));
|
|
||||||
Patient patient = myPatientDao.read(idType, mySrd);
|
|
||||||
|
|
||||||
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
|
||||||
assertFalse(validationResult.isSuccessful());
|
|
||||||
assertEquals(2, validationResult.getMessages().size());
|
|
||||||
|
|
||||||
Iterator<SingleValidationMessage> messageIterator = validationResult.getMessages().iterator();
|
|
||||||
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + profile + "-identifier|1)", messageIterator.next().getMessage());
|
|
||||||
assertEquals("Patient.name: minimum required = 1, but only found 0 (from " + profile + "-name|1)", messageIterator.next().getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testValidatePatient_withMultipleProfilesSameUrlDifferentVersions_validatesAgainstFirstVersion() {
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "2", "Patient.name");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "3", "Patient.birthDate");
|
|
||||||
|
|
||||||
IIdType idType = createPatient(
|
|
||||||
withProfile(profile + "|2"),
|
|
||||||
withProfile(profile + "|1"),
|
|
||||||
withProfile(profile + "|3"));
|
|
||||||
Patient patient = myPatientDao.read(idType, mySrd);
|
|
||||||
|
|
||||||
ValidationResult validationResult = myFhirValidator.validateWithResult(patient);
|
|
||||||
assertFalse(validationResult.isSuccessful());
|
|
||||||
assertEquals(1, validationResult.getMessages().size());
|
|
||||||
|
|
||||||
SingleValidationMessage message = validationResult.getMessages().iterator().next();
|
|
||||||
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + profile + "|1)", message.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
public class RepositoryValidationOnCreateTests {
|
|
||||||
@Test
|
|
||||||
public void testCreatePatient_withProfileNoVersionAndRepositoryValidationRuleNoVersion_validatesAgainstFirstVersion() {
|
|
||||||
setupRepositoryValidationRules(profile);
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "2", "Patient.name");
|
|
||||||
|
|
||||||
try {
|
|
||||||
createPatient(withProfile(profile));
|
|
||||||
fail();
|
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
ourLog.info(e.getMessage());
|
|
||||||
assertEquals(Msg.code(574)
|
|
||||||
+ "Patient.identifier: minimum required = 1, but only found 0 (from " + profile + "|1)", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreatePatient_withProfileWithVersionAndRepositoryValidationRuleWithVersion_unknownProfile() {
|
|
||||||
setupRepositoryValidationRules(profile + "|1");
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "2", "Patient.name");
|
|
||||||
|
|
||||||
try {
|
|
||||||
createPatient(withProfile(profile + "|1"));
|
|
||||||
fail();
|
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
assertEquals(Msg.code(574) + "Profile reference '" + profile
|
|
||||||
+ "|1' has not been checked because it is unknown, and the validator is set to not fetch unknown profiles", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreatePatient_withProfileWithVersionAndRepositoryValidationRuleNoVersion_doesNotConform() {
|
|
||||||
setupRepositoryValidationRules(profile);
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "2", "Patient.name");
|
|
||||||
|
|
||||||
try {
|
|
||||||
createPatient(withProfile(profile + "|1"));
|
|
||||||
fail();
|
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
assertEquals(Msg.code(575) + "Resource of type \"" + myResourceType
|
|
||||||
+ "\" does not declare conformance to profile from: [" + profile + "]", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreatePatient_withPatientProfileWithoutVersionAndRepositoryValidationRuleWithVersion_doesNotConform() {
|
|
||||||
setupRepositoryValidationRules(profile + "|1");
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "2", "Patient.name");
|
|
||||||
|
|
||||||
try {
|
|
||||||
createPatient(withProfile(profile));
|
|
||||||
fail();
|
|
||||||
} catch (PreconditionFailedException e) {
|
|
||||||
assertEquals(Msg.code(575) + "Resource of type \"" + myResourceType
|
|
||||||
+ "\" does not declare conformance to profile from: [" + profile + "|1]", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupRepositoryValidationRules(String... theProfiles) {
|
|
||||||
List<IRepositoryValidatingRule> rules = myApplicationContext
|
|
||||||
.getBean(RepositoryValidatingRuleBuilder.REPOSITORY_VALIDATING_RULE_BUILDER, RepositoryValidatingRuleBuilder.class)
|
|
||||||
.forResourcesOfType(myResourceType)
|
|
||||||
.requireAtLeastOneProfileOf(theProfiles)
|
|
||||||
.and()
|
|
||||||
.requireValidationToDeclaredProfiles()
|
|
||||||
.withBestPracticeWarningLevel(BestPracticeWarningLevel.Ignore)
|
|
||||||
.rejectOnSeverity("error")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
myRepositoryValidatingInterceptor.setRules(rules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
|
||||||
public class SearchWithProfileTests {
|
|
||||||
@Test
|
|
||||||
public void testSearchPatient_withProfileBelowCriteria_returnsAllMatches() {
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
IIdType id1 = createPatient(withProfile(profile));
|
|
||||||
IIdType id2 = createPatient(withProfile(profile + "|1"));
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add("_profile", new UriParam(profile).setQualifier(UriParamQualifierEnum.BELOW));
|
|
||||||
IBundleProvider bundleProvider = myPatientDao.search(params, mySrd);
|
|
||||||
assertFalse(bundleProvider.isEmpty());
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(bundleProvider),
|
|
||||||
containsInAnyOrder(id1.toUnqualifiedVersionless().getValue(), id2.toUnqualifiedVersionless().getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchPatient_withProfileExactCriteriaWithoutVersionAndPatientProfileWithoutVersion_returnsExactMatch() {
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
|
|
||||||
IIdType id1 = createPatient(withProfile(profile));
|
|
||||||
IIdType id2 = createPatient(withProfile(profile));
|
|
||||||
|
|
||||||
Bundle outcome = myClient.search().forResource(myResourceType)
|
|
||||||
.where(new TokenClientParam("_profile").exactly().code(profile))
|
|
||||||
.returnBundle(Bundle.class).execute();
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(outcome),
|
|
||||||
containsInAnyOrder(id1.toUnqualifiedVersionless().getValue(), id2.toUnqualifiedVersionless().getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchPatient_withProfileExactCriteriaWithVersionAndPatientProfileWithVersion_returnsExactMatch() {
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
IIdType id1 = createPatient(withProfile(profile + "|1"));
|
|
||||||
|
|
||||||
Bundle outcome = myClient.search().forResource(myResourceType)
|
|
||||||
.where(new TokenClientParam("_profile").exactly().code(profile + "|1"))
|
|
||||||
.returnBundle(Bundle.class).execute();
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(outcome),
|
|
||||||
containsInAnyOrder(id1.toUnqualifiedVersionless().getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchPatient_withProfileExactCriteriaWithoutVersionAndPatientProfileWithVersion_returnsNoMatch() {
|
|
||||||
final String profile = PATIENT_STRUCTURE_DEFINITION_URL;
|
|
||||||
|
|
||||||
createPatientStructureDefinitionWithMandatoryField(profile, "1", "Patient.identifier");
|
|
||||||
createPatient(withProfile(profile + "|1"));
|
|
||||||
|
|
||||||
Bundle outcome = myClient.search().forResource(myResourceType)
|
|
||||||
.where(new TokenClientParam("_profile").exactly().code(profile))
|
|
||||||
.returnBundle(Bundle.class).execute();
|
|
||||||
assertTrue(outcome.getEntryFirstRep().isEmpty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createPatientStructureDefinitionWithMandatoryField(String theUrl, String theVersion, String thePath) {
|
|
||||||
StructureDefinition sd = new StructureDefinition()
|
|
||||||
.setUrl(theUrl).setVersion(theVersion)
|
|
||||||
.setBaseDefinition(myResourceTypeDefinition)
|
|
||||||
.setType(myResourceType)
|
|
||||||
.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
|
||||||
sd.getDifferential().addElement()
|
|
||||||
.setPath(thePath)
|
|
||||||
.setMin(1)
|
|
||||||
.setId(thePath);
|
|
||||||
|
|
||||||
DaoMethodOutcome outcome = myStructureDefinitionDao.create(sd, mySrd);
|
|
||||||
assertTrue(outcome.getCreated());
|
|
||||||
ourValidationSupport.addStructureDefinition(sd);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package ca.uhn.fhir.jpa.validation;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||||
|
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.gclient.TokenClientParam;
|
||||||
|
import ca.uhn.fhir.rest.param.UriParam;
|
||||||
|
import ca.uhn.fhir.rest.param.UriParamQualifierEnum;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class SearchWithResourceProfileR4Test extends BaseResourceProviderR4Test {
|
||||||
|
private static final String myResourceType = "Patient";
|
||||||
|
private final String myProfile = "http://example.org/fhir/StructureDefinition/TestPatient";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchPatient_withProfileBelowCriteria_returnsAllMatches() {
|
||||||
|
createProfile();
|
||||||
|
IIdType id1 = createPatient(withProfile(myProfile));
|
||||||
|
IIdType id2 = createPatient(withProfile(myProfile + "|1"));
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add("_profile", new UriParam(myProfile).setQualifier(UriParamQualifierEnum.BELOW));
|
||||||
|
IBundleProvider bundleProvider = myPatientDao.search(params, mySrd);
|
||||||
|
assertFalse(bundleProvider.isEmpty());
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(bundleProvider),
|
||||||
|
containsInAnyOrder(id1.toUnqualifiedVersionless().getValue(), id2.toUnqualifiedVersionless().getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchPatient_withProfileExactCriteriaWithoutVersionAndPatientProfileWithoutVersion_returnsExactMatch() {
|
||||||
|
createProfile();
|
||||||
|
IIdType id1 = createPatient(withProfile(myProfile));
|
||||||
|
IIdType id2 = createPatient(withProfile(myProfile));
|
||||||
|
|
||||||
|
Bundle outcome = myClient.search().forResource(myResourceType)
|
||||||
|
.where(new TokenClientParam("_profile").exactly().code(myProfile))
|
||||||
|
.returnBundle(Bundle.class).execute();
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(outcome),
|
||||||
|
containsInAnyOrder(id1.toUnqualifiedVersionless().getValue(), id2.toUnqualifiedVersionless().getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchPatient_withProfileExactCriteriaWithVersionAndPatientProfileWithVersion_returnsExactMatch() {
|
||||||
|
createProfile();
|
||||||
|
IIdType id1 = createPatient(withProfile(myProfile + "|1"));
|
||||||
|
|
||||||
|
Bundle outcome = myClient.search().forResource(myResourceType)
|
||||||
|
.where(new TokenClientParam("_profile").exactly().code(myProfile + "|1"))
|
||||||
|
.returnBundle(Bundle.class).execute();
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(outcome),
|
||||||
|
containsInAnyOrder(id1.toUnqualifiedVersionless().getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchPatient_withProfileExactCriteria_returnsNoMatch() {
|
||||||
|
createProfile();
|
||||||
|
createPatient(withProfile(myProfile + "|1"));
|
||||||
|
|
||||||
|
Bundle outcome = myClient.search().forResource(myResourceType)
|
||||||
|
.where(new TokenClientParam("_profile").exactly().code(myProfile))
|
||||||
|
.returnBundle(Bundle.class).execute();
|
||||||
|
assertTrue(outcome.getEntryFirstRep().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProfile() {
|
||||||
|
final String baseProfile = "http://hl7.org/fhir/StructureDefinition/Patient";
|
||||||
|
final String profileId = "TestProfile";
|
||||||
|
final String version = "1";
|
||||||
|
final String rulePath = "Patient.identifier";
|
||||||
|
|
||||||
|
StructureDefinition sd = new StructureDefinition()
|
||||||
|
.setUrl(myProfile).setVersion(version)
|
||||||
|
.setBaseDefinition(baseProfile)
|
||||||
|
.setType(myResourceType)
|
||||||
|
.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
|
||||||
|
sd.setId(profileId);
|
||||||
|
sd.getDifferential().addElement()
|
||||||
|
.setPath(rulePath)
|
||||||
|
.setMin(1)
|
||||||
|
.setId(rulePath);
|
||||||
|
|
||||||
|
DaoMethodOutcome outcome = myStructureDefinitionDao.update(sd, new SystemRequestDetails());
|
||||||
|
assertNotNull(outcome.getResource());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue