Handle canonical questionnaire refs in validator (#1544)
* Handle canonical questionnaire refs in validator * FIx changelog * Fix canonical reference * Build tweak * Change to trigger a build
This commit is contained in:
parent
1618ccc14c
commit
8b2ab51bc6
|
@ -58,3 +58,5 @@ jobs:
|
|||
#checkStyleRunAnalysis: false # Optional
|
||||
#pmdRunAnalysis: false # Optional
|
||||
#findBugsRunAnalysis: false # Optional
|
||||
|
||||
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaValidationSupport;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.transaction.Transactional;
|
||||
import javax.transaction.Transactional.TxType;
|
||||
import java.util.Collections;
|
||||
|
@ -45,18 +37,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||
*/
|
||||
|
||||
@Transactional(value = TxType.REQUIRED)
|
||||
public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3, ApplicationContextAware {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaValidationSupportDstu3.class);
|
||||
|
||||
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
|
||||
private IFhirResourceDao<ValueSet> myValueSetDao;
|
||||
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
|
||||
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
|
||||
private IFhirResourceDao<ImplementationGuide> myImplementationGuideDao;
|
||||
@Autowired
|
||||
private FhirContext myDstu3Ctx;
|
||||
private ApplicationContext myApplicationContext;
|
||||
public class JpaValidationSupportDstu3 extends BaseJpaValidationSupport implements IJpaValidationSupportDstu3 {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -98,76 +79,6 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3, Ap
|
|||
return fetchResource(theCtx, ValueSet.class, theSystem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
IdType id = new IdType(theUri);
|
||||
boolean localReference = false;
|
||||
if (id.hasBaseUrl() == false && id.hasIdPart() == true) {
|
||||
localReference = true;
|
||||
}
|
||||
|
||||
String resourceName = myDstu3Ctx.getResourceDefinition(theClass).getName();
|
||||
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 = myValueSetDao.search(params);
|
||||
if (search.size() == 0) {
|
||||
params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} else {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} else if ("StructureDefinition".equals(resourceName)) {
|
||||
if (theUri.startsWith("http://hl7.org/fhir/StructureDefinition/")) {
|
||||
// Don't allow the core FHIR definitions to be overwritten
|
||||
String typeName = theUri.substring("http://hl7.org/fhir/StructureDefinition/".length());
|
||||
if (myDstu3Ctx.getElementDefinition(typeName) != null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(StructureDefinition.SP_URL, new UriParam(theUri));
|
||||
search = myStructureDefinitionDao.search(params);
|
||||
} else if ("Questionnaire".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
|
||||
search = myQuestionnaireDao.search(params);
|
||||
} else if ("CodeSystem".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(CodeSystem.SP_URL, new UriParam(theUri));
|
||||
search = myCodeSystemDao.search(params);
|
||||
} else if ("ImplementationGuide".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ImplementationGuide.SP_URL, new UriParam(theUri));
|
||||
search = myImplementationGuideDao.search(params);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't fetch resource type: " + resourceName);
|
||||
}
|
||||
|
||||
if (search.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (search.size() > 1) {
|
||||
ourLog.warn("Found multiple {} instances with URL search value of: {}", resourceName, theUri);
|
||||
}
|
||||
|
||||
return (T) search.getResources(0, 1).get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
|
||||
|
@ -180,20 +91,6 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3, Ap
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
|
||||
myApplicationContext = theApplicationContext;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myStructureDefinitionDao = myApplicationContext.getBean("myStructureDefinitionDaoDstu3", IFhirResourceDao.class);
|
||||
myValueSetDao = myApplicationContext.getBean("myValueSetDaoDstu3", IFhirResourceDao.class);
|
||||
myQuestionnaireDao = myApplicationContext.getBean("myQuestionnaireDaoDstu3", IFhirResourceDao.class);
|
||||
myCodeSystemDao = myApplicationContext.getBean("myCodeSystemDaoDstu3", IFhirResourceDao.class);
|
||||
myImplementationGuideDao = myApplicationContext.getBean("myImplementationGuideDaoDstu3", IFhirResourceDao.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(value = TxType.SUPPORTS)
|
||||
public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) {
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
public abstract class BaseJpaValidationSupport {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseJpaValidationSupport.class);
|
||||
|
||||
@Autowired
|
||||
private FhirContext myR4Ctx;
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
private IFhirResourceDao<?> myStructureDefinitionDao;
|
||||
private IFhirResourceDao<?> myValueSetDao;
|
||||
private IFhirResourceDao<?> myQuestionnaireDao;
|
||||
private IFhirResourceDao<?> myCodeSystemDao;
|
||||
private IFhirResourceDao<?> myImplementationGuideDao;
|
||||
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
IdType id = new IdType(theUri);
|
||||
boolean localReference = false;
|
||||
if (id.hasBaseUrl() == false && id.hasIdPart() == true) {
|
||||
localReference = true;
|
||||
}
|
||||
|
||||
String resourceName = myR4Ctx.getResourceDefinition(theClass).getName();
|
||||
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 = myValueSetDao.search(params);
|
||||
if (search.size() == 0) {
|
||||
params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} else {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} 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 (myR4Ctx.getElementDefinition(typeName) != null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(StructureDefinition.SP_URL, new UriParam(theUri));
|
||||
search = myStructureDefinitionDao.search(params);
|
||||
} else if ("Questionnaire".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
if (localReference) {
|
||||
params.add(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
|
||||
} else {
|
||||
params.add(Questionnaire.SP_URL, new UriParam(id.getValue()));
|
||||
}
|
||||
search = myQuestionnaireDao.search(params);
|
||||
} else if ("CodeSystem".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(CodeSystem.SP_URL, new UriParam(theUri));
|
||||
search = myCodeSystemDao.search(params);
|
||||
} else if ("ImplementationGuide".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ImplementationGuide.SP_URL, new UriParam(theUri));
|
||||
search = myImplementationGuideDao.search(params);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't fetch resource type: " + resourceName);
|
||||
}
|
||||
|
||||
Integer size = search.size();
|
||||
if (size == null || size == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (size > 1) {
|
||||
ourLog.warn("Found multiple {} instances with URL search value of: {}", resourceName, theUri);
|
||||
}
|
||||
|
||||
return (T) search.getResources(0, 1).get(0);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myStructureDefinitionDao = myDaoRegistry.getResourceDao("StructureDefinition");
|
||||
myValueSetDao = myDaoRegistry.getResourceDao("ValueSet");
|
||||
myQuestionnaireDao = myDaoRegistry.getResourceDao("Questionnaire");
|
||||
myCodeSystemDao = myDaoRegistry.getResourceDao("CodeSystem");
|
||||
myImplementationGuideDao = myDaoRegistry.getResourceDao("ImplementationGuide");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,22 +1,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r4.terminologies.ValueSetExpander;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.transaction.Transactional;
|
||||
import javax.transaction.Transactional.TxType;
|
||||
import java.util.Collections;
|
||||
|
@ -43,19 +35,7 @@ import java.util.List;
|
|||
*/
|
||||
|
||||
@Transactional(value = TxType.REQUIRED)
|
||||
public class JpaValidationSupportR4 implements IJpaValidationSupportR4, ApplicationContextAware {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaValidationSupportR4.class);
|
||||
|
||||
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
|
||||
private IFhirResourceDao<ValueSet> myValueSetDao;
|
||||
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
|
||||
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
|
||||
private IFhirResourceDao<ImplementationGuide> myImplementationGuideDao;
|
||||
|
||||
@Autowired
|
||||
private FhirContext myR4Ctx;
|
||||
private ApplicationContext myApplicationContext;
|
||||
public class JpaValidationSupportR4 extends BaseJpaValidationSupport implements IJpaValidationSupportR4 {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -92,77 +72,6 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4, Applicat
|
|||
return fetchResource(theCtx, ValueSet.class, theSystem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
IdType id = new IdType(theUri);
|
||||
boolean localReference = false;
|
||||
if (id.hasBaseUrl() == false && id.hasIdPart() == true) {
|
||||
localReference = true;
|
||||
}
|
||||
|
||||
String resourceName = myR4Ctx.getResourceDefinition(theClass).getName();
|
||||
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 = myValueSetDao.search(params);
|
||||
if (search.size() == 0) {
|
||||
params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} else {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} 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 (myR4Ctx.getElementDefinition(typeName) != null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(StructureDefinition.SP_URL, new UriParam(theUri));
|
||||
search = myStructureDefinitionDao.search(params);
|
||||
} else if ("Questionnaire".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
|
||||
search = myQuestionnaireDao.search(params);
|
||||
} else if ("CodeSystem".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(CodeSystem.SP_URL, new UriParam(theUri));
|
||||
search = myCodeSystemDao.search(params);
|
||||
} else if ("ImplementationGuide".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ImplementationGuide.SP_URL, new UriParam(theUri));
|
||||
search = myImplementationGuideDao.search(params);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't fetch resource type: " + resourceName);
|
||||
}
|
||||
|
||||
if (search.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (search.size() > 1) {
|
||||
ourLog.warn("Found multiple {} instances with URL search value of: {}", resourceName, theUri);
|
||||
}
|
||||
|
||||
return (T) search.getResources(0, 1).get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
|
||||
return fetchResource(theCtx, StructureDefinition.class, theUrl);
|
||||
|
@ -174,23 +83,9 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4, Applicat
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
|
||||
myApplicationContext = theApplicationContext;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myStructureDefinitionDao = myApplicationContext.getBean("myStructureDefinitionDaoR4", IFhirResourceDao.class);
|
||||
myValueSetDao = myApplicationContext.getBean("myValueSetDaoR4", IFhirResourceDao.class);
|
||||
myQuestionnaireDao = myApplicationContext.getBean("myQuestionnaireDaoR4", IFhirResourceDao.class);
|
||||
myCodeSystemDao = myApplicationContext.getBean("myCodeSystemDaoR4", IFhirResourceDao.class);
|
||||
myImplementationGuideDao = myApplicationContext.getBean("myImplementationGuideDaoR4", IFhirResourceDao.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(value = TxType.SUPPORTS)
|
||||
public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) {
|
||||
public IValidationSupport.CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
package ca.uhn.fhir.jpa.dao.r5;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaValidationSupport;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r5.model.*;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.transaction.Transactional;
|
||||
import javax.transaction.Transactional.TxType;
|
||||
import java.util.Collections;
|
||||
|
@ -43,19 +35,7 @@ import java.util.List;
|
|||
*/
|
||||
|
||||
@Transactional(value = TxType.REQUIRED)
|
||||
public class JpaValidationSupportR5 implements IJpaValidationSupportR5, ApplicationContextAware {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaValidationSupportR5.class);
|
||||
|
||||
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
|
||||
private IFhirResourceDao<ValueSet> myValueSetDao;
|
||||
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
|
||||
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
|
||||
private IFhirResourceDao<ImplementationGuide> myImplementationGuideDao;
|
||||
|
||||
@Autowired
|
||||
private FhirContext myR5Ctx;
|
||||
private ApplicationContext myApplicationContext;
|
||||
public class JpaValidationSupportR5 extends BaseJpaValidationSupport implements IJpaValidationSupportR5 {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -92,76 +72,6 @@ public class JpaValidationSupportR5 implements IJpaValidationSupportR5, Applicat
|
|||
return fetchResource(theCtx, ValueSet.class, theSystem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
IdType id = new IdType(theUri);
|
||||
boolean localReference = false;
|
||||
if (id.hasBaseUrl() == false && id.hasIdPart() == true) {
|
||||
localReference = true;
|
||||
}
|
||||
|
||||
String resourceName = myR5Ctx.getResourceDefinition(theClass).getName();
|
||||
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 = myValueSetDao.search(params);
|
||||
if (search.size() == 0) {
|
||||
params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} else {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
search = myValueSetDao.search(params);
|
||||
}
|
||||
} 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 (myR5Ctx.getElementDefinition(typeName) != null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(StructureDefinition.SP_URL, new UriParam(theUri));
|
||||
search = myStructureDefinitionDao.search(params);
|
||||
} else if ("Questionnaire".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
|
||||
search = myQuestionnaireDao.search(params);
|
||||
} else if ("CodeSystem".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(CodeSystem.SP_URL, new UriParam(theUri));
|
||||
search = myCodeSystemDao.search(params);
|
||||
} else if ("ImplementationGuide".equals(resourceName)) {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ImplementationGuide.SP_URL, new UriParam(theUri));
|
||||
search = myImplementationGuideDao.search(params);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't fetch resource type: " + resourceName);
|
||||
}
|
||||
|
||||
if (search.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (search.size() > 1) {
|
||||
ourLog.warn("Found multiple {} instances with URL search value of: {}", resourceName, theUri);
|
||||
}
|
||||
|
||||
return (T) search.getResources(0, 1).get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
|
||||
|
@ -174,19 +84,6 @@ public class JpaValidationSupportR5 implements IJpaValidationSupportR5, Applicat
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
|
||||
myApplicationContext = theApplicationContext;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myStructureDefinitionDao = myApplicationContext.getBean("myStructureDefinitionDaoR5", IFhirResourceDao.class);
|
||||
myValueSetDao = myApplicationContext.getBean("myValueSetDaoR5", IFhirResourceDao.class);
|
||||
myQuestionnaireDao = myApplicationContext.getBean("myQuestionnaireDaoR5", IFhirResourceDao.class);
|
||||
myCodeSystemDao = myApplicationContext.getBean("myCodeSystemDaoR5", IFhirResourceDao.class);
|
||||
myImplementationGuideDao = myApplicationContext.getBean("myImplementationGuideDaoR5", IFhirResourceDao.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(value = TxType.SUPPORTS)
|
||||
|
|
|
@ -144,8 +144,8 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
private String encode(Patient thePatient) {
|
||||
return myFhirCtx.newJsonParser().encodeResourceToString(thePatient);
|
||||
private String encode(IBaseResource thePatient) {
|
||||
return myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(thePatient);
|
||||
}
|
||||
|
||||
|
||||
|
@ -472,6 +472,85 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithCanonicalReference() {
|
||||
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setId("q");
|
||||
q.addItem().setLinkId("link0").setRequired(true).setType(Questionnaire.QuestionnaireItemType.STRING);
|
||||
q.addItem().setLinkId("link1").setRequired(true).setType(Questionnaire.QuestionnaireItemType.STRING);
|
||||
q.setUrl("http://foo/q");
|
||||
myQuestionnaireDao.update(q);
|
||||
|
||||
QuestionnaireResponse qa = new QuestionnaireResponse();
|
||||
qa.getText().setStatus(Narrative.NarrativeStatus.GENERATED).setDivAsString("<div>aaa</div>");
|
||||
qa.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED);
|
||||
qa.getQuestionnaireElement().setValue("http://foo/q");
|
||||
qa.addItem().setLinkId("link1").addAnswer().setValue(new StringType("FOO"));
|
||||
|
||||
try {
|
||||
MethodOutcome validationOutcome = myQuestionnaireResponseDao.validate(qa, null, null, null, null, null, null);
|
||||
OperationOutcome oo = (OperationOutcome) validationOutcome.getOperationOutcome();
|
||||
String encode = encode(oo);
|
||||
ourLog.info(encode);
|
||||
fail("Didn't fail- response was " + encode);
|
||||
} catch (PreconditionFailedException e) {
|
||||
OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
||||
assertEquals("No response found for required item with id = 'link0'", oo.getIssueFirstRep().getDiagnostics());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithLocalReference() {
|
||||
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setId("q");
|
||||
q.addItem().setLinkId("link0").setRequired(true).setType(Questionnaire.QuestionnaireItemType.STRING);
|
||||
q.addItem().setLinkId("link1").setRequired(true).setType(Questionnaire.QuestionnaireItemType.STRING);
|
||||
q.setUrl("http://foo/q");
|
||||
myQuestionnaireDao.update(q);
|
||||
|
||||
QuestionnaireResponse qa = new QuestionnaireResponse();
|
||||
qa.getText().setStatus(Narrative.NarrativeStatus.GENERATED).setDivAsString("<div>aaa</div>");
|
||||
qa.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED);
|
||||
qa.getQuestionnaireElement().setValue("Questionnaire/q");
|
||||
qa.addItem().setLinkId("link1").addAnswer().setValue(new StringType("FOO"));
|
||||
|
||||
try {
|
||||
MethodOutcome validationOutcome = myQuestionnaireResponseDao.validate(qa, null, null, null, null, null, null);
|
||||
OperationOutcome oo = (OperationOutcome) validationOutcome.getOperationOutcome();
|
||||
String encode = encode(oo);
|
||||
ourLog.info(encode);
|
||||
fail("Didn't fail- response was " + encode);
|
||||
} catch (PreconditionFailedException e) {
|
||||
OperationOutcome oo = (OperationOutcome) e.getOperationOutcome();
|
||||
assertEquals("No response found for required item with id = 'link0'", oo.getIssueFirstRep().getDiagnostics());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponseWithUnknownReference() {
|
||||
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setId("q");
|
||||
q.addItem().setLinkId("link0").setRequired(true).setType(Questionnaire.QuestionnaireItemType.STRING);
|
||||
q.addItem().setLinkId("link1").setRequired(true).setType(Questionnaire.QuestionnaireItemType.STRING);
|
||||
q.setUrl("http://foo/q");
|
||||
myQuestionnaireDao.update(q);
|
||||
|
||||
QuestionnaireResponse qa = new QuestionnaireResponse();
|
||||
qa.getText().setStatus(Narrative.NarrativeStatus.GENERATED).setDivAsString("<div>aaa</div>");
|
||||
qa.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED);
|
||||
qa.getQuestionnaireElement().setValue("Questionnaire/DOES_NOT_EXIST");
|
||||
qa.addItem().setLinkId("link1").addAnswer().setValue(new StringType("FOO"));
|
||||
|
||||
MethodOutcome validationOutcome = myQuestionnaireResponseDao.validate(qa, null, null, null, null, null, null);
|
||||
OperationOutcome oo = (OperationOutcome) validationOutcome.getOperationOutcome();
|
||||
assertEquals("The questionnaire \"Questionnaire/DOES_NOT_EXIST\" could not be resolved, so no validation can be performed against the base questionnaire", oo.getIssueFirstRep().getDiagnostics());
|
||||
}
|
||||
|
||||
private IBaseResource findResourceByIdInBundle(Bundle vss, String name) {
|
||||
IBaseResource retVal = null;
|
||||
for (BundleEntryComponent next : vss.getEntry()) {
|
||||
|
|
|
@ -79,30 +79,6 @@ public class ResourceProviderQuestionnaireResponseDstu3Test extends BaseResource
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCreateWithAbsoluteReference() {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.addName().setFamily("Everything").addGiven("Arthur");
|
||||
IIdType ptId1 = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Questionnaire q1 = new Questionnaire();
|
||||
q1.addItem().setLinkId("link1").setType(QuestionnaireItemType.STRING);
|
||||
IIdType qId = myQuestionnaireDao.create(q1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
QuestionnaireResponse qr1 = new QuestionnaireResponse();
|
||||
qr1.getQuestionnaire().setReferenceElement(qId.withServerBase(null, "Questionnaire"));
|
||||
qr1.setStatus(QuestionnaireResponseStatus.COMPLETED);
|
||||
qr1.addItem().setLinkId("link1").addAnswer().setValue(new DecimalType(123));
|
||||
try {
|
||||
ourClient.create().resource(qr1).execute();
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.toString(), containsString("Answer value must be of type string"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveQuestionnaire() throws Exception {
|
||||
String input = "<QuestionnaireResponse xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
|
|
|
@ -79,29 +79,6 @@ public class ResourceProviderQuestionnaireResponseR4Test extends BaseResourcePro
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testCreateWithAbsoluteReference() {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.addName().setFamily("Everything").addGiven("Arthur");
|
||||
IIdType ptId1 = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Questionnaire q1 = new Questionnaire();
|
||||
q1.addItem().setLinkId("link1").setType(QuestionnaireItemType.STRING);
|
||||
IIdType qId = myQuestionnaireDao.create(q1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
QuestionnaireResponse qr1 = new QuestionnaireResponse();
|
||||
qr1.setQuestionnaire(qId.withServerBase("http://example.com", "Questionnaire").getValue());
|
||||
qr1.setStatus(QuestionnaireResponseStatus.COMPLETED);
|
||||
qr1.addItem().setLinkId("link1").addAnswer().setValue(new DecimalType(123));
|
||||
try {
|
||||
ourClient.create().resource(qr1).execute();
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(myFhirCtx.newJsonParser().encodeResourceToString(e.getOperationOutcome()), containsString("Answer value must be of type string"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveQuestionnaire() throws Exception {
|
||||
String input = "<QuestionnaireResponse xmlns=\"http://hl7.org/fhir\">\n" +
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package ca.uhn.fhir.jpa.model.sched;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.quartz.JobExecutionContext;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.sched.FireAtIntervalJob.NEXT_EXECUTION_TIME;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FireAtIntervalJobTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private JobExecutionContext myJobExecutionContext;
|
||||
|
||||
@Test
|
||||
public void testExecutionThrowsException() {
|
||||
|
||||
FireAtIntervalJob job = new FireAtIntervalJob(1000) {
|
||||
@Override
|
||||
protected void doExecute(JobExecutionContext theContext) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
};
|
||||
|
||||
// No exception thrown please
|
||||
job.execute(myJobExecutionContext);
|
||||
|
||||
verify(myJobExecutionContext.getJobDetail().getJobDataMap(), times(1)).put(eq(NEXT_EXECUTION_TIME), anyLong());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -361,6 +361,11 @@ public abstract class BaseSearchParamRegistry<SP extends IBaseResource> implemen
|
|||
return refreshCacheRetrier.runWithRetry();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setSearchParamProviderForUnitTest(ISearchParamProvider theSearchParamProvider) {
|
||||
mySearchParamProvider = theSearchParamProvider;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void registerScheduledJob() {
|
||||
ScheduledJobDefinition jobDetail = new ScheduledJobDefinition();
|
||||
|
|
|
@ -367,6 +367,10 @@
|
|||
The @Metadata annotation now has an attribute that can be used to control
|
||||
the cache timeout
|
||||
</action>
|
||||
<action type="fix" issue="1544">
|
||||
QuestionnaireResponse validation in the JPA server was not able to load Questionnaire resources that
|
||||
were referenced using a canonical URI instead of a local reference. Thanks to Vu Vuong for reporting!
|
||||
</action>
|
||||
</release>
|
||||
<release version="4.0.3" date="2019-09-03" description="Igloo (Point Release)">
|
||||
<action type="fix">
|
||||
|
|
Loading…
Reference in New Issue