Fix validating capabilitystatements (#2214)

* Fix validating capabilitystatements

* Add changelog
This commit is contained in:
James Agnew 2020-12-03 05:31:04 -05:00 committed by GitHub
parent 7627a86176
commit 35f4d48eee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 52 deletions

View File

@ -0,0 +1,5 @@
---
type: fix
issue: 2214
title: "When using the validator from within the JPA server, validating CapabilityStatement resources failed with
an error when trying to load linked SearchParameter resources. This has been corrected."

View File

@ -119,71 +119,82 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
String resourceName = myFhirContext.getResourceType(theClass);
IBundleProvider search;
if ("ValueSet".equals(resourceName)) {
if (localReference) {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(IAnyResource.SP_RES_ID, new StringParam(theUri));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
if (search.size() == 0) {
params = new SearchParameterMap();
switch (resourceName) {
case "ValueSet":
if (localReference) {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(ValueSet.SP_URL, new UriParam(theUri));
params.add(IAnyResource.SP_RES_ID, new StringParam(theUri));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
if (search.size() == 0) {
params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(ValueSet.SP_URL, new UriParam(theUri));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
}
} else {
int versionSeparator = theUri.lastIndexOf('|');
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
if (versionSeparator != -1) {
params.add(ValueSet.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(ValueSet.SP_URL, new UriParam(theUri.substring(0, versionSeparator)));
} else {
params.add(ValueSet.SP_URL, new UriParam(theUri));
}
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
}
} else {
break;
case "StructureDefinition": {
// Don't allow the core FHIR definitions to be overwritten
if (theUri.startsWith("http://hl7.org/fhir/StructureDefinition/")) {
String typeName = theUri.substring("http://hl7.org/fhir/StructureDefinition/".length());
if (myFhirContext.getElementDefinition(typeName) != null) {
return myNoMatch;
}
}
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(StructureDefinition.SP_URL, new UriParam(theUri));
search = myDaoRegistry.getResourceDao("StructureDefinition").search(params);
break;
}
case "Questionnaire": {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
if (localReference || myFhirContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU2)) {
params.add(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
} else {
params.add(Questionnaire.SP_URL, new UriParam(id.getValue()));
}
search = myDaoRegistry.getResourceDao("Questionnaire").search(params);
break;
}
case "CodeSystem": {
int versionSeparator = theUri.lastIndexOf('|');
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
if (versionSeparator != -1) {
params.add(ValueSet.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(ValueSet.SP_URL, new UriParam(theUri.substring(0,versionSeparator)));
params.add(CodeSystem.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(CodeSystem.SP_URL, new UriParam(theUri.substring(0, versionSeparator)));
} else {
params.add(ValueSet.SP_URL, new UriParam(theUri));
params.add(CodeSystem.SP_URL, new UriParam(theUri));
}
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
break;
}
} else if ("StructureDefinition".equals(resourceName)) {
// Don't allow the core FHIR definitions to be overwritten
if (theUri.startsWith("http://hl7.org/fhir/StructureDefinition/")) {
String typeName = theUri.substring("http://hl7.org/fhir/StructureDefinition/".length());
if (myFhirContext.getElementDefinition(typeName) != null) {
return myNoMatch;
}
case "ImplementationGuide":
case "SearchParameter": {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(ImplementationGuide.SP_URL, new UriParam(theUri));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
break;
}
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(StructureDefinition.SP_URL, new UriParam(theUri));
search = myDaoRegistry.getResourceDao("StructureDefinition").search(params);
} else if ("Questionnaire".equals(resourceName)) {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
if (localReference || myFhirContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU2)) {
params.add(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
} else {
params.add(Questionnaire.SP_URL, new UriParam(id.getValue()));
}
search = myDaoRegistry.getResourceDao("Questionnaire").search(params);
} else if ("CodeSystem".equals(resourceName)) {
int versionSeparator = theUri.lastIndexOf('|');
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
if (versionSeparator != -1) {
params.add(CodeSystem.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(CodeSystem.SP_URL, new UriParam(theUri.substring(0,versionSeparator)));
} else {
params.add(CodeSystem.SP_URL, new UriParam(theUri));
}
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
} else if ("ImplementationGuide".equals(resourceName)) {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1);
params.add(ImplementationGuide.SP_URL, new UriParam(theUri));
search = myDaoRegistry.getResourceDao("ImplementationGuide").search(params);
} else {
throw new IllegalArgumentException("Can't fetch resource type: " + resourceName);
default:
throw new IllegalArgumentException("Can't fetch resource type: " + resourceName);
}
Integer size = search.size();

View File

@ -98,6 +98,7 @@ import org.hl7.fhir.r4.model.Appointment;
import org.hl7.fhir.r4.model.AuditEvent;
import org.hl7.fhir.r4.model.Binary;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.CapabilityStatement;
import org.hl7.fhir.r4.model.CarePlan;
import org.hl7.fhir.r4.model.CareTeam;
import org.hl7.fhir.r4.model.ChargeItem;
@ -356,6 +357,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
@Qualifier("myDocumentReferenceDaoR4")
protected IFhirResourceDao<DocumentReference> myDocumentReferenceDao;
@Autowired
@Qualifier("myCapabilityStatementDaoR4")
protected IFhirResourceDao<CapabilityStatement> myCapabilityStatementDao;
@Autowired
@Qualifier("myPatientDaoR4")
protected IFhirResourceDaoPatient<Patient> myPatientDao;
@Autowired

View File

@ -36,6 +36,7 @@ import org.hl7.fhir.r4.model.AllergyIntolerance;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.CapabilityStatement;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.Coding;
@ -56,6 +57,7 @@ import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.Questionnaire;
import org.hl7.fhir.r4.model.QuestionnaireResponse;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.SearchParameter;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r4.model.UriType;
@ -1236,6 +1238,40 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
}
@Test
public void testValidateCapabilityStatement() {
SearchParameter sp = new SearchParameter();
sp.setUrl("http://example.com/name");
sp.setId("name");
sp.setCode("name");
sp.setType(Enumerations.SearchParamType.STRING);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
sp.addBase("Patient");
sp.setExpression("Patient.name");
mySearchParameterDao.update(sp);
CapabilityStatement cs = new CapabilityStatement();
cs.getText().setStatus(Narrative.NarrativeStatus.GENERATED).getDiv().setValue("<div>aaaa</div>");
CapabilityStatement.CapabilityStatementRestComponent rest = cs.addRest();
CapabilityStatement.CapabilityStatementRestResourceComponent patient = rest.addResource();
patient .setType("Patient");
patient.addSearchParam().setName("foo").setType(Enumerations.SearchParamType.DATE).setDefinition("http://example.com/name");
try {
myCapabilityStatementDao.validate(cs, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
fail();
} catch (PreconditionFailedException e) {
String oo = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome());
ourLog.info(oo);
assertThat(oo, oo, containsString("Type mismatch - SearchParameter 'http://example.com/name' type is string, but type here is date"));
}
}
@Test
public void testValidateForCreate() {
String methodName = "testValidateForCreate";