Add terminology delta operations (#1401)
* Start work on delta operations * Add changelog * Some build fixes * Move upload terminology command to CodeSystem resource * Updates * Some test fixes * Add changelog * Some test fixes * More test fixes * Test fix * Add additional tests * Transaction boundary fixes
This commit is contained in:
parent
8158292665
commit
a4ca5374ec
|
@ -48,11 +48,11 @@ public class ExampleServlet extends ca.uhn.fhir.rest.server.RestfulServer {
|
|||
*/
|
||||
List<Object> plainProviders=new ArrayList<Object>();
|
||||
plainProviders.add(new PlainProvider());
|
||||
setPlainProviders(plainProviders);
|
||||
registerProviders(plainProviders);
|
||||
|
||||
List<IResourceProvider> resourceProviders = new ArrayList<IResourceProvider>();
|
||||
// ...add some resource providers...
|
||||
setResourceProviders(resourceProviders);
|
||||
registerProviders(resourceProviders);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -264,6 +264,12 @@ public class ValidatorExamples {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
// TODO: implement
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
// TODO: implement
|
||||
|
|
|
@ -79,7 +79,7 @@ public class FhirContext {
|
|||
private AddProfileTagEnum myAddProfileTagWhenEncoding = AddProfileTagEnum.ONLY_FOR_CUSTOM;
|
||||
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
||||
private ArrayList<Class<? extends IBase>> myCustomTypes;
|
||||
private Map<String, Class<? extends IBaseResource>> myDefaultTypeForProfile = new HashMap<String, Class<? extends IBaseResource>>();
|
||||
private Map<String, Class<? extends IBaseResource>> myDefaultTypeForProfile = new HashMap<>();
|
||||
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
||||
private volatile boolean myInitialized;
|
||||
private volatile boolean myInitializing = false;
|
||||
|
@ -90,7 +90,7 @@ public class FhirContext {
|
|||
private volatile INarrativeGenerator myNarrativeGenerator;
|
||||
private volatile IParserErrorHandler myParserErrorHandler = new LenientErrorHandler();
|
||||
private ParserOptions myParserOptions = new ParserOptions();
|
||||
private Set<PerformanceOptionsEnum> myPerformanceOptions = new HashSet<PerformanceOptionsEnum>();
|
||||
private Set<PerformanceOptionsEnum> myPerformanceOptions = new HashSet<>();
|
||||
private Collection<Class<? extends IBaseResource>> myResourceTypesToScan;
|
||||
private volatile IRestfulClientFactory myRestfulClientFactory;
|
||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||
|
@ -198,7 +198,7 @@ public class FhirContext {
|
|||
private void ensureCustomTypeList() {
|
||||
myClassToElementDefinition.clear();
|
||||
if (myCustomTypes == null) {
|
||||
myCustomTypes = new ArrayList<Class<? extends IBase>>();
|
||||
myCustomTypes = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,14 +278,6 @@ public class FhirContext {
|
|||
return myNameToElementDefinition.get(theElementName.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* For unit tests only
|
||||
*/
|
||||
int getElementDefinitionCount() {
|
||||
validateInitialized();
|
||||
return myClassToElementDefinition.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all element definitions (resources, datatypes, etc.)
|
||||
*/
|
||||
|
@ -741,21 +733,21 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
private BaseRuntimeElementDefinition<?> scanDatatype(Class<? extends IElement> theResourceType) {
|
||||
ArrayList<Class<? extends IElement>> resourceTypes = new ArrayList<Class<? extends IElement>>();
|
||||
ArrayList<Class<? extends IElement>> resourceTypes = new ArrayList<>();
|
||||
resourceTypes.add(theResourceType);
|
||||
Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> defs = scanResourceTypes(resourceTypes);
|
||||
return defs.get(theResourceType);
|
||||
}
|
||||
|
||||
private RuntimeResourceDefinition scanResourceType(Class<? extends IBaseResource> theResourceType) {
|
||||
ArrayList<Class<? extends IElement>> resourceTypes = new ArrayList<Class<? extends IElement>>();
|
||||
ArrayList<Class<? extends IElement>> resourceTypes = new ArrayList<>();
|
||||
resourceTypes.add(theResourceType);
|
||||
Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> defs = scanResourceTypes(resourceTypes);
|
||||
return (RuntimeResourceDefinition) defs.get(theResourceType);
|
||||
}
|
||||
|
||||
private synchronized Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> scanResourceTypes(Collection<Class<? extends IElement>> theResourceTypes) {
|
||||
List<Class<? extends IBase>> typesToScan = new ArrayList<Class<? extends IBase>>();
|
||||
List<Class<? extends IBase>> typesToScan = new ArrayList<>();
|
||||
if (theResourceTypes != null) {
|
||||
typesToScan.addAll(theResourceTypes);
|
||||
}
|
||||
|
@ -769,7 +761,7 @@ public class FhirContext {
|
|||
myRuntimeChildUndeclaredExtensionDefinition = scanner.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
}
|
||||
|
||||
Map<String, BaseRuntimeElementDefinition<?>> nameToElementDefinition = new HashMap<String, BaseRuntimeElementDefinition<?>>();
|
||||
Map<String, BaseRuntimeElementDefinition<?>> nameToElementDefinition = new HashMap<>();
|
||||
nameToElementDefinition.putAll(myNameToElementDefinition);
|
||||
for (Entry<String, BaseRuntimeElementDefinition<?>> next : scanner.getNameToElementDefinitions().entrySet()) {
|
||||
if (!nameToElementDefinition.containsKey(next.getKey())) {
|
||||
|
@ -777,7 +769,7 @@ public class FhirContext {
|
|||
}
|
||||
}
|
||||
|
||||
Map<String, RuntimeResourceDefinition> nameToResourceDefinition = new HashMap<String, RuntimeResourceDefinition>();
|
||||
Map<String, RuntimeResourceDefinition> nameToResourceDefinition = new HashMap<>();
|
||||
nameToResourceDefinition.putAll(myNameToResourceDefinition);
|
||||
for (Entry<String, RuntimeResourceDefinition> next : scanner.getNameToResourceDefinition().entrySet()) {
|
||||
if (!nameToResourceDefinition.containsKey(next.getKey())) {
|
||||
|
@ -785,7 +777,7 @@ public class FhirContext {
|
|||
}
|
||||
}
|
||||
|
||||
Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> classToElementDefinition = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>();
|
||||
Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> classToElementDefinition = new HashMap<>();
|
||||
classToElementDefinition.putAll(myClassToElementDefinition);
|
||||
classToElementDefinition.putAll(scanner.getClassToElementDefinitions());
|
||||
for (BaseRuntimeElementDefinition<?> next : classToElementDefinition.values()) {
|
||||
|
@ -798,7 +790,7 @@ public class FhirContext {
|
|||
}
|
||||
}
|
||||
|
||||
Map<String, RuntimeResourceDefinition> idToElementDefinition = new HashMap<String, RuntimeResourceDefinition>();
|
||||
Map<String, RuntimeResourceDefinition> idToElementDefinition = new HashMap<>();
|
||||
idToElementDefinition.putAll(myIdToResourceDefinition);
|
||||
idToElementDefinition.putAll(scanner.getIdToResourceDefinition());
|
||||
|
||||
|
@ -864,9 +856,9 @@ public class FhirContext {
|
|||
if (theResourceTypes == null) {
|
||||
return null;
|
||||
}
|
||||
List<Class<? extends IElement>> resTypes = new ArrayList<Class<? extends IElement>>();
|
||||
List<Class<? extends IElement>> resTypes = new ArrayList<>();
|
||||
for (Class<? extends IBaseResource> next : theResourceTypes) {
|
||||
resTypes.add((Class<? extends IElement>) next);
|
||||
resTypes.add(next);
|
||||
}
|
||||
return resTypes;
|
||||
}
|
||||
|
@ -924,14 +916,14 @@ public class FhirContext {
|
|||
}
|
||||
|
||||
private static Collection<Class<? extends IBaseResource>> toCollection(Class<? extends IBaseResource> theResourceType) {
|
||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<>(1);
|
||||
retVal.add(theResourceType);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<Class<? extends IBaseResource>> toCollection(Class<?>[] theResourceTypes) {
|
||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<Class<? extends IBaseResource>>(1);
|
||||
ArrayList<Class<? extends IBaseResource>> retVal = new ArrayList<>(1);
|
||||
for (Class<?> clazz : theResourceTypes) {
|
||||
if (!IResource.class.isAssignableFrom(clazz)) {
|
||||
throw new IllegalArgumentException(clazz.getCanonicalName() + " is not an instance of " + IResource.class.getSimpleName());
|
||||
|
|
|
@ -21,9 +21,21 @@ package ca.uhn.fhir.context.support;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/**
|
||||
* This interface is a version-independent representation of the
|
||||
|
@ -102,6 +114,68 @@ public interface IContextValidationSupport<EVS_IN, EVS_OUT, SDT, CST, CDCT, IST>
|
|||
*/
|
||||
CodeValidationResult<CDCT, IST> validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay);
|
||||
|
||||
/**
|
||||
* Look up a code using the system and code value
|
||||
*
|
||||
* @param theContext The FHIR context
|
||||
* @param theSystem The CodeSystem URL
|
||||
* @param theCode The code
|
||||
*/
|
||||
LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode);
|
||||
|
||||
class ConceptDesignation {
|
||||
private String myLanguage;
|
||||
private String myUseSystem;
|
||||
private String myUseCode;
|
||||
private String myUseDisplay;
|
||||
private String myValue;
|
||||
|
||||
public String getLanguage() {
|
||||
return myLanguage;
|
||||
}
|
||||
|
||||
public ConceptDesignation setLanguage(String theLanguage) {
|
||||
myLanguage = theLanguage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getUseSystem() {
|
||||
return myUseSystem;
|
||||
}
|
||||
|
||||
public ConceptDesignation setUseSystem(String theUseSystem) {
|
||||
myUseSystem = theUseSystem;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getUseCode() {
|
||||
return myUseCode;
|
||||
}
|
||||
|
||||
public ConceptDesignation setUseCode(String theUseCode) {
|
||||
myUseCode = theUseCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getUseDisplay() {
|
||||
return myUseDisplay;
|
||||
}
|
||||
|
||||
public ConceptDesignation setUseDisplay(String theUseDisplay) {
|
||||
myUseDisplay = theUseDisplay;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public ConceptDesignation setValue(String theValue) {
|
||||
myValue = theValue;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseConceptProperty {
|
||||
private final String myPropertyName;
|
||||
|
||||
|
@ -165,7 +239,7 @@ public interface IContextValidationSupport<EVS_IN, EVS_OUT, SDT, CST, CDCT, IST>
|
|||
}
|
||||
}
|
||||
|
||||
class CodeValidationResult<CDCT, IST> {
|
||||
abstract class CodeValidationResult<CDCT, IST> {
|
||||
private CDCT myDefinition;
|
||||
private String myMessage;
|
||||
private IST mySeverity;
|
||||
|
@ -228,6 +302,190 @@ public interface IContextValidationSupport<EVS_IN, EVS_OUT, SDT, CST, CDCT, IST>
|
|||
return myDefinition != null;
|
||||
}
|
||||
|
||||
public LookupCodeResult asLookupCodeResult(String theSearchedForSystem, String theSearchedForCode) {
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
retVal.setSearchedForSystem(theSearchedForSystem);
|
||||
retVal.setSearchedForCode(theSearchedForCode);
|
||||
if (isOk()) {
|
||||
retVal.setFound(true);
|
||||
retVal.setCodeDisplay(getDisplay());
|
||||
retVal.setCodeSystemDisplayName(getCodeSystemName());
|
||||
retVal.setCodeSystemVersion(getCodeSystemVersion());
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected abstract String getDisplay();
|
||||
|
||||
}
|
||||
|
||||
class LookupCodeResult {
|
||||
|
||||
private String myCodeDisplay;
|
||||
private boolean myCodeIsAbstract;
|
||||
private String myCodeSystemDisplayName;
|
||||
private String myCodeSystemVersion;
|
||||
private boolean myFound;
|
||||
private String mySearchedForCode;
|
||||
private String mySearchedForSystem;
|
||||
private List<IContextValidationSupport.BaseConceptProperty> myProperties;
|
||||
private List<ConceptDesignation> myDesignations;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public LookupCodeResult() {
|
||||
super();
|
||||
}
|
||||
|
||||
public List<BaseConceptProperty> getProperties() {
|
||||
if (myProperties == null) {
|
||||
myProperties = new ArrayList<>();
|
||||
}
|
||||
return myProperties;
|
||||
}
|
||||
|
||||
public void setProperties(List<IContextValidationSupport.BaseConceptProperty> theProperties) {
|
||||
myProperties = theProperties;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<ConceptDesignation> getDesignations() {
|
||||
if (myDesignations == null) {
|
||||
myDesignations = new ArrayList<>();
|
||||
}
|
||||
return myDesignations;
|
||||
}
|
||||
|
||||
public String getCodeDisplay() {
|
||||
return myCodeDisplay;
|
||||
}
|
||||
|
||||
public void setCodeDisplay(String theCodeDisplay) {
|
||||
myCodeDisplay = theCodeDisplay;
|
||||
}
|
||||
|
||||
public String getCodeSystemDisplayName() {
|
||||
return myCodeSystemDisplayName;
|
||||
}
|
||||
|
||||
public void setCodeSystemDisplayName(String theCodeSystemDisplayName) {
|
||||
myCodeSystemDisplayName = theCodeSystemDisplayName;
|
||||
}
|
||||
|
||||
public String getCodeSystemVersion() {
|
||||
return myCodeSystemVersion;
|
||||
}
|
||||
|
||||
public void setCodeSystemVersion(String theCodeSystemVersion) {
|
||||
myCodeSystemVersion = theCodeSystemVersion;
|
||||
}
|
||||
|
||||
public String getSearchedForCode() {
|
||||
return mySearchedForCode;
|
||||
}
|
||||
|
||||
public LookupCodeResult setSearchedForCode(String theSearchedForCode) {
|
||||
mySearchedForCode = theSearchedForCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSearchedForSystem() {
|
||||
return mySearchedForSystem;
|
||||
}
|
||||
|
||||
public LookupCodeResult setSearchedForSystem(String theSearchedForSystem) {
|
||||
mySearchedForSystem = theSearchedForSystem;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isCodeIsAbstract() {
|
||||
return myCodeIsAbstract;
|
||||
}
|
||||
|
||||
public void setCodeIsAbstract(boolean theCodeIsAbstract) {
|
||||
myCodeIsAbstract = theCodeIsAbstract;
|
||||
}
|
||||
|
||||
public boolean isFound() {
|
||||
return myFound;
|
||||
}
|
||||
|
||||
public LookupCodeResult setFound(boolean theFound) {
|
||||
myFound = theFound;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void throwNotFoundIfAppropriate() {
|
||||
if (isFound() == false) {
|
||||
throw new ResourceNotFoundException("Unable to find code[" + getSearchedForCode() + "] in system[" + getSearchedForSystem() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public IBaseParameters toParameters(FhirContext theContext, List<? extends IPrimitiveType<String>> theProperties) {
|
||||
|
||||
IBaseParameters retVal = ParametersUtil.newInstance(theContext);
|
||||
if (isNotBlank(getCodeSystemDisplayName())) {
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "name", getCodeSystemDisplayName());
|
||||
}
|
||||
if (isNotBlank(getCodeSystemVersion())) {
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "version", getCodeSystemVersion());
|
||||
}
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "display", getCodeDisplay());
|
||||
ParametersUtil.addParameterToParametersBoolean(theContext, retVal, "abstract", isCodeIsAbstract());
|
||||
|
||||
if (myProperties != null) {
|
||||
|
||||
Set<String> properties = Collections.emptySet();
|
||||
if (theProperties != null) {
|
||||
properties = theProperties
|
||||
.stream()
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
for (IContextValidationSupport.BaseConceptProperty next : myProperties) {
|
||||
|
||||
if (!properties.isEmpty()) {
|
||||
if (!properties.contains(next.getPropertyName())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
IBase property = ParametersUtil.addParameterToParameters(theContext, retVal, "property");
|
||||
ParametersUtil.addPartCode(theContext, property, "code", next.getPropertyName());
|
||||
|
||||
if (next instanceof IContextValidationSupport.StringConceptProperty) {
|
||||
IContextValidationSupport.StringConceptProperty prop = (IContextValidationSupport.StringConceptProperty) next;
|
||||
ParametersUtil.addPartString(theContext, property, "value", prop.getValue());
|
||||
} else if (next instanceof IContextValidationSupport.CodingConceptProperty) {
|
||||
IContextValidationSupport.CodingConceptProperty prop = (IContextValidationSupport.CodingConceptProperty) next;
|
||||
ParametersUtil.addPartCoding(theContext, property, "value", prop.getCodeSystem(), prop.getCode(), prop.getDisplay());
|
||||
} else {
|
||||
throw new IllegalStateException("Don't know how to handle " + next.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myDesignations != null) {
|
||||
for (ConceptDesignation next : myDesignations) {
|
||||
|
||||
IBase property = ParametersUtil.addParameterToParameters(theContext, retVal, "designation");
|
||||
ParametersUtil.addPartCode(theContext, property, "language", next.getLanguage());
|
||||
ParametersUtil.addPartCoding(theContext, property, "use", next.getUseSystem(), next.getUseCode(), next.getUseDisplay());
|
||||
ParametersUtil.addPartString(theContext, property, "value", next.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static LookupCodeResult notFound(String theSearchedForSystem, String theSearchedForCode) {
|
||||
return new LookupCodeResult()
|
||||
.setFound(false)
|
||||
.setSearchedForSystem(theSearchedForSystem)
|
||||
.setSearchedForCode(theSearchedForCode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,15 +54,31 @@ public @interface Operation {
|
|||
String name();
|
||||
|
||||
/**
|
||||
* On a client, this value should be populated with the resource type that the operation applies to. If set to
|
||||
* This value may be populated with the resource type that the operation applies to. If set to
|
||||
* {@link IBaseResource} (which is the default) than the operation applies to the server and not to a specific
|
||||
* resource type.
|
||||
* <p>
|
||||
* This value has no effect when used on server implementations.
|
||||
* This attribute should not be used a resource provider implementing
|
||||
* <code>IResourceProvider</code> since the type can be inferred from the
|
||||
* resource provider type.
|
||||
* </p>
|
||||
* @see #typeName() may also be used to specify a value as a String
|
||||
*/
|
||||
Class<? extends IBaseResource> type() default IBaseResource.class;
|
||||
|
||||
/**
|
||||
* This value may be populated with the resource type that the operation applies to. If set to
|
||||
* {@link IBaseResource} (which is the default) than the operation applies to the server and not to a specific
|
||||
* resource type.
|
||||
* <p>
|
||||
* This attribute should not be used a resource provider implementing
|
||||
* <code>IResourceProvider</code> since the type can be inferred from the
|
||||
* resource provider type.
|
||||
* </p>
|
||||
* @see #type() may also be used to specify a value for this setting as a class type
|
||||
*/
|
||||
String typeName() default "";
|
||||
|
||||
/**
|
||||
* If a given operation method is <b><a href="http://en.wikipedia.org/wiki/Idempotence">idempotent</a></b>
|
||||
* (meaning roughly that it does not modify any data or state on the server)
|
||||
|
|
|
@ -37,31 +37,30 @@ public class AttachmentUtil {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static IPrimitiveType<byte[]> getOrCreateData(FhirContext theContext, ICompositeType theAttachment) {
|
||||
BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, "data");
|
||||
List<IBase> entries = entryChild.getAccessor().getValues(theAttachment);
|
||||
return entries
|
||||
.stream()
|
||||
.map(t -> (IPrimitiveType<byte[]>) t)
|
||||
.findFirst()
|
||||
.orElseGet(() -> {
|
||||
IPrimitiveType<byte[]> binary = newPrimitive(theContext, "base64Binary", null);
|
||||
entryChild.getMutator().setValue(theAttachment, binary);
|
||||
return binary;
|
||||
});
|
||||
return getOrCreateChild(theContext, theAttachment, "data", "base64Binary");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static IPrimitiveType<String> getOrCreateContentType(FhirContext theContext, ICompositeType theAttachment) {
|
||||
BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, "contentType");
|
||||
return getOrCreateChild(theContext, theAttachment, "contentType", "string");
|
||||
}
|
||||
|
||||
public static IPrimitiveType<String> getOrCreateUrl(FhirContext theContext, ICompositeType theAttachment) {
|
||||
return getOrCreateChild(theContext, theAttachment, "url", "uri");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> IPrimitiveType<T> getOrCreateChild(FhirContext theContext, ICompositeType theAttachment, String theChildName, String theChildDatatype) {
|
||||
BaseRuntimeChildDefinition entryChild = getChild(theContext, theAttachment, theChildName);
|
||||
List<IBase> entries = entryChild.getAccessor().getValues(theAttachment);
|
||||
return entries
|
||||
.stream()
|
||||
.map(t -> (IPrimitiveType<String>) t)
|
||||
.map(t -> (IPrimitiveType<T>) t)
|
||||
.findFirst()
|
||||
.orElseGet(() -> {
|
||||
IPrimitiveType<String> string = newPrimitive(theContext, "string", null);
|
||||
IPrimitiveType<String> string = newPrimitive(theContext, theChildDatatype, null);
|
||||
entryChild.getMutator().setValue(theAttachment, string);
|
||||
return string;
|
||||
return (IPrimitiveType<T>) string;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ public class ParametersUtil {
|
|||
List<IBase> valueValues = valueChild.getAccessor().getValues(nextParameter);
|
||||
valueValues
|
||||
.stream()
|
||||
.filter(t->t instanceof IPrimitiveType<?>)
|
||||
.map(t->((IPrimitiveType<?>)t).getValueAsString())
|
||||
.filter(t -> t instanceof IPrimitiveType<?>)
|
||||
.map(t -> ((IPrimitiveType<?>) t).getValueAsString())
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.forEach(retVal::add);
|
||||
|
||||
|
@ -107,11 +107,11 @@ public class ParametersUtil {
|
|||
/**
|
||||
* Add a paratemer value to a Parameters resource
|
||||
*
|
||||
* @param theContext The FhirContext
|
||||
* @param theParameters The Parameters resource
|
||||
* @param theName The parameter name
|
||||
* @param theContext The FhirContext
|
||||
* @param theParameters The Parameters resource
|
||||
* @param theName The parameter name
|
||||
* @param thePrimitiveDatatype The datatype, e.g. "string", or "uri"
|
||||
* @param theValue The value
|
||||
* @param theValue The value
|
||||
*/
|
||||
public static void addParameterToParameters(FhirContext theContext, IBaseParameters theParameters, String theName, String thePrimitiveDatatype, String theValue) {
|
||||
Validate.notBlank(thePrimitiveDatatype, "thePrimitiveDatatype must not be null or empty");
|
||||
|
@ -142,9 +142,99 @@ public class ParametersUtil {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static IPrimitiveType<?> createUri(FhirContext theContext, String theValue) {
|
||||
IPrimitiveType<?> value = (IPrimitiveType<?>) theContext.getElementDefinition("uri").newInstance(theValue);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static IPrimitiveType<?> createCode(FhirContext theContext, String theValue) {
|
||||
IPrimitiveType<?> value = (IPrimitiveType<?>) theContext.getElementDefinition("code").newInstance(theValue);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static IBaseParameters newInstance(FhirContext theContext) {
|
||||
Validate.notNull(theContext, "theContext must not be null");
|
||||
return (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addParameterToParametersBoolean(FhirContext theCtx, IBaseParameters theParameters, String theName, boolean theValue) {
|
||||
IPrimitiveType<Boolean> value = (IPrimitiveType<Boolean>) theCtx.getElementDefinition("boolean").newInstance();
|
||||
value.setValue(theValue);
|
||||
addParameterToParameters(theCtx, theParameters, theName, value);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addParameterToParametersInteger(FhirContext theCtx, IBaseParameters theParameters, String theName, int theValue) {
|
||||
IPrimitiveType<Integer> count = (IPrimitiveType<Integer>) theCtx.getElementDefinition("integer").newInstance();
|
||||
count.setValue(theValue);
|
||||
addParameterToParameters(theCtx, theParameters, theName, count);
|
||||
|
||||
}
|
||||
|
||||
public static void addParameterToParametersReference(FhirContext theCtx, IBaseParameters theParameters, String theName, String theReference) {
|
||||
IBaseReference target = (IBaseReference) theCtx.getElementDefinition("reference").newInstance();
|
||||
target.setReference(theReference);
|
||||
addParameterToParameters(theCtx, theParameters, theName, target);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addParameterToParametersString(FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) {
|
||||
IPrimitiveType<String> value = (IPrimitiveType<String>) theCtx.getElementDefinition("string").newInstance();
|
||||
value.setValue(theValue);
|
||||
addParameterToParameters(theCtx, theParameters, theName, value);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a parameter with no value (typically because we'll be adding sub-parameters)
|
||||
*/
|
||||
public static IBase addParameterToParameters(FhirContext theContext, IBaseParameters theParameters, String theName) {
|
||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theParameters);
|
||||
BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter");
|
||||
BaseRuntimeElementCompositeDefinition<?> paramChildElem = (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter");
|
||||
|
||||
return createParameterRepetition(theContext, theParameters, paramChild, paramChildElem, theName);
|
||||
}
|
||||
|
||||
public static void addPartCode(FhirContext theContext, IBase theParameter, String theName, String theCode) {
|
||||
IPrimitiveType<String> value = (IPrimitiveType<String>) theContext.getElementDefinition("code").newInstance();
|
||||
value.setValue(theCode);
|
||||
|
||||
addPart(theContext, theParameter, theName, value);
|
||||
}
|
||||
|
||||
public static void addPartString(FhirContext theContext, IBase theParameter, String theName, String theValue) {
|
||||
IPrimitiveType<String> value = (IPrimitiveType<String>) theContext.getElementDefinition("string").newInstance();
|
||||
value.setValue(theValue);
|
||||
|
||||
addPart(theContext, theParameter, theName, value);
|
||||
}
|
||||
|
||||
public static void addPartCoding(FhirContext theContext, IBase theParameter, String theName, String theSystem, String theCode, String theDisplay) {
|
||||
IBase coding = theContext.getElementDefinition("coding").newInstance();
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> codingDef = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(coding.getClass());
|
||||
codingDef.getChildByName("system").getMutator().addValue(coding, createUri(theContext, theSystem));
|
||||
codingDef.getChildByName("code").getMutator().addValue(coding, createCode(theContext, theCode));
|
||||
codingDef.getChildByName("display").getMutator().addValue(coding, createString(theContext, theDisplay));
|
||||
|
||||
addPart(theContext, theParameter, theName, coding);
|
||||
}
|
||||
|
||||
private static void addPart(FhirContext theContext, IBase theParameter, String theName, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theParameter.getClass());
|
||||
BaseRuntimeChildDefinition partChild = def.getChildByName("part");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> partChildElem = (BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part");
|
||||
IBase part = partChildElem.newInstance();
|
||||
partChild.getMutator().addValue(theParameter, part);
|
||||
|
||||
IPrimitiveType<String> name = (IPrimitiveType<String>) theContext.getElementDefinition("string").newInstance();
|
||||
name.setValue(theName);
|
||||
partChildElem.getChildByName("name").getMutator().addValue(part, name);
|
||||
|
||||
partChildElem.getChildByName("value[x]").getMutator().addValue(part, theValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,11 @@ public class LoadingValidationSupportDstu3 implements IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
return null;
|
||||
|
|
|
@ -102,4 +102,9 @@ public class LoadingValidationSupportR4 implements org.hl7.fhir.r4.hapi.ctx.IVal
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.apache.commons.cli.CommandLine;
|
|||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
|
@ -103,7 +104,7 @@ public class UploadTerminologyCommand extends BaseCommand {
|
|||
ourLog.info("Beginning upload - This may take a while...");
|
||||
IBaseParameters response = client
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named(UPLOAD_EXTERNAL_CODE_SYSTEM)
|
||||
.withParameters(inputParameters)
|
||||
.execute();
|
||||
|
|
|
@ -127,6 +127,11 @@ public class IgPackValidationSupportDstu3 implements IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
return null;
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.*;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import org.apache.commons.codec.binary.StringUtils;
|
||||
import org.hl7.fhir.instance.hapi.validation.CachingValidationSupport;
|
||||
|
@ -185,13 +186,13 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
return source;
|
||||
}
|
||||
|
||||
private LookupCodeResult lookup(List<ExpansionContains> theContains, String theSystem, String theCode) {
|
||||
private IContextValidationSupport.LookupCodeResult lookup(List<ExpansionContains> theContains, String theSystem, String theCode) {
|
||||
for (ExpansionContains nextCode : theContains) {
|
||||
|
||||
String system = nextCode.getSystem();
|
||||
String code = nextCode.getCode();
|
||||
if (theSystem.equals(system) && theCode.equals(code)) {
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
IContextValidationSupport.LookupCodeResult retVal = new IContextValidationSupport.LookupCodeResult();
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
retVal.setFound(true);
|
||||
|
@ -210,7 +211,7 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, CodingDt theCoding, RequestDetails theRequest) {
|
||||
public IContextValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, CodingDt theCoding, RequestDetails theRequest) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
|
@ -236,13 +237,13 @@ public class FhirResourceDaoValueSetDstu2 extends FhirResourceDaoDstu2<ValueSet>
|
|||
for (IIdType nextId : valueSetIds) {
|
||||
ValueSet expansion = expand(nextId, null, theRequest);
|
||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||
LookupCodeResult result = lookup(contains, system, code);
|
||||
IContextValidationSupport.LookupCodeResult result = lookup(contains, system, code);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
IContextValidationSupport.LookupCodeResult retVal = new IContextValidationSupport.LookupCodeResult();
|
||||
retVal.setFound(false);
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
|
|
|
@ -3,21 +3,15 @@ package ca.uhn.fhir.jpa.dao;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
|
||||
|
||||
import java.util.Collections;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -43,7 +37,8 @@ public interface IFhirResourceDaoCodeSystem<T extends IBaseResource, CD, CC> ext
|
|||
|
||||
List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest);
|
||||
|
||||
LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, CD theCoding, RequestDetails theRequestDetails);
|
||||
@Nonnull
|
||||
IContextValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, CD theCoding, RequestDetails theRequestDetails);
|
||||
|
||||
SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, CD theCodingA, CD theCodingB, RequestDetails theRequestDetails);
|
||||
|
||||
|
@ -72,147 +67,4 @@ public interface IFhirResourceDaoCodeSystem<T extends IBaseResource, CD, CC> ext
|
|||
}
|
||||
|
||||
|
||||
class LookupCodeResult {
|
||||
|
||||
private String myCodeDisplay;
|
||||
private boolean myCodeIsAbstract;
|
||||
private String myCodeSystemDisplayName;
|
||||
private String myCodeSystemVersion;
|
||||
private boolean myFound;
|
||||
private String mySearchedForCode;
|
||||
private String mySearchedForSystem;
|
||||
private List<IContextValidationSupport.BaseConceptProperty> myProperties;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public LookupCodeResult() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getCodeDisplay() {
|
||||
return myCodeDisplay;
|
||||
}
|
||||
|
||||
public void setCodeDisplay(String theCodeDisplay) {
|
||||
myCodeDisplay = theCodeDisplay;
|
||||
}
|
||||
|
||||
public String getCodeSystemDisplayName() {
|
||||
return myCodeSystemDisplayName;
|
||||
}
|
||||
|
||||
public void setCodeSystemDisplayName(String theCodeSystemDisplayName) {
|
||||
myCodeSystemDisplayName = theCodeSystemDisplayName;
|
||||
}
|
||||
|
||||
public String getCodeSystemVersion() {
|
||||
return myCodeSystemVersion;
|
||||
}
|
||||
|
||||
public void setCodeSystemVersion(String theCodeSystemVersion) {
|
||||
myCodeSystemVersion = theCodeSystemVersion;
|
||||
}
|
||||
|
||||
public String getSearchedForCode() {
|
||||
return mySearchedForCode;
|
||||
}
|
||||
|
||||
public void setSearchedForCode(String theSearchedForCode) {
|
||||
mySearchedForCode = theSearchedForCode;
|
||||
}
|
||||
|
||||
public String getSearchedForSystem() {
|
||||
return mySearchedForSystem;
|
||||
}
|
||||
|
||||
public void setSearchedForSystem(String theSearchedForSystem) {
|
||||
mySearchedForSystem = theSearchedForSystem;
|
||||
}
|
||||
|
||||
public boolean isCodeIsAbstract() {
|
||||
return myCodeIsAbstract;
|
||||
}
|
||||
|
||||
public void setCodeIsAbstract(boolean theCodeIsAbstract) {
|
||||
myCodeIsAbstract = theCodeIsAbstract;
|
||||
}
|
||||
|
||||
public boolean isFound() {
|
||||
return myFound;
|
||||
}
|
||||
|
||||
public void setFound(boolean theFound) {
|
||||
myFound = theFound;
|
||||
}
|
||||
|
||||
public void setProperties(List<IContextValidationSupport.BaseConceptProperty> theProperties) {
|
||||
myProperties = theProperties;
|
||||
}
|
||||
|
||||
public void throwNotFoundIfAppropriate() {
|
||||
if (isFound() == false) {
|
||||
throw new ResourceNotFoundException("Unable to find code[" + getSearchedForCode() + "] in system[" + getSearchedForSystem() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public Parameters toParameters(List<? extends IPrimitiveType<String>> theProperties) {
|
||||
Parameters retVal = new Parameters();
|
||||
|
||||
retVal.addParameter().setName("name").setValue(new StringType(getCodeSystemDisplayName()));
|
||||
if (isNotBlank(getCodeSystemVersion())) {
|
||||
retVal.addParameter().setName("version").setValue(new StringType(getCodeSystemVersion()));
|
||||
}
|
||||
retVal.addParameter().setName("display").setValue(new StringType(getCodeDisplay()));
|
||||
retVal.addParameter().setName("abstract").setValue(new BooleanType(isCodeIsAbstract()));
|
||||
|
||||
if (myProperties != null) {
|
||||
|
||||
Set<String> properties = Collections.emptySet();
|
||||
if (theProperties != null) {
|
||||
properties = theProperties
|
||||
.stream()
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
for (IContextValidationSupport.BaseConceptProperty next : myProperties) {
|
||||
|
||||
if (!properties.isEmpty()) {
|
||||
if (!properties.contains(next.getPropertyName())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Parameters.ParametersParameterComponent property = retVal.addParameter().setName("property");
|
||||
property
|
||||
.addPart()
|
||||
.setName("code")
|
||||
.setValue(new CodeType(next.getPropertyName()));
|
||||
|
||||
if (next instanceof IContextValidationSupport.StringConceptProperty) {
|
||||
IContextValidationSupport.StringConceptProperty prop = (IContextValidationSupport.StringConceptProperty) next;
|
||||
property
|
||||
.addPart()
|
||||
.setName("value")
|
||||
.setValue(new StringType(prop.getValue()));
|
||||
} else if (next instanceof IContextValidationSupport.CodingConceptProperty) {
|
||||
IContextValidationSupport.CodingConceptProperty prop = (IContextValidationSupport.CodingConceptProperty) next;
|
||||
property
|
||||
.addPart()
|
||||
.setName("value")
|
||||
.setValue(new Coding()
|
||||
.setSystem(prop.getCodeSystem())
|
||||
.setCode(prop.getCode())
|
||||
.setDisplay(prop.getDisplay()));
|
||||
} else {
|
||||
throw new IllegalStateException("Don't know how to handle " + next.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,8 +24,9 @@ import org.hl7.fhir.instance.model.api.IAnyResource;
|
|||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum.ResourceMetadataKeySupportingAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
final class MetadataKeyResourcePid extends ResourceMetadataKeySupportingAnyResource<Long, Long> {
|
||||
public final class MetadataKeyResourcePid extends ResourceMetadataKeySupportingAnyResource<Long, Long> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
MetadataKeyResourcePid(String theValue) {
|
||||
|
|
|
@ -20,25 +20,19 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
||||
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
|
@ -52,45 +46,18 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemDstu3.class);
|
||||
|
||||
@Autowired
|
||||
private ITermCodeSystemVersionDao myCsvDao;
|
||||
|
||||
@Autowired
|
||||
private ITermCodeSystemDao myCsDao;
|
||||
|
||||
@Autowired
|
||||
private ValidationSupportChain myValidationSupport;
|
||||
|
||||
// private LookupCodeResult lookup(List<ValueSetExpansionContainsComponent> theContains, String theSystem, String theCode) {
|
||||
// for (ValueSetExpansionContainsComponent nextCode : theContains) {
|
||||
//
|
||||
// String system = nextCode.getSystem();
|
||||
// String code = nextCode.getCode();
|
||||
// if (theSystem.equals(system) && theCode.equals(code)) {
|
||||
// LookupCodeResult retVal = new LookupCodeResult();
|
||||
// retVal.setSearchedForCode(code);
|
||||
// retVal.setSearchedForSystem(system);
|
||||
// retVal.setFound(true);
|
||||
// if (nextCode.getAbstractElement().getValue() != null) {
|
||||
// retVal.setCodeIsAbstract(nextCode.getAbstractElement().booleanValue());
|
||||
// }
|
||||
// retVal.setCodeDisplay(nextCode.getDisplay());
|
||||
// retVal.setCodeSystemVersion(nextCode.getVersion());
|
||||
// retVal.setCodeSystemDisplayName("Unknown"); // TODO: implement
|
||||
// return retVal;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
List<IIdType> valueSetIds;
|
||||
|
@ -103,7 +70,7 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
public IContextValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
|
@ -128,40 +95,15 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
ourLog.debug("Looking up {} / {}", system, code);
|
||||
|
||||
if (myValidationSupport.isCodeSystemSupported(getContext(), system)) {
|
||||
|
||||
ourLog.debug("Code system {} is supported", system);
|
||||
|
||||
CodeValidationResult result = myValidationSupport.validateCode(getContext(), system, code, null);
|
||||
IContextValidationSupport.LookupCodeResult result = myValidationSupport.lookupCode(getContext(), system, code);
|
||||
if (result != null) {
|
||||
if (result.isOk()) {
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
retVal.setFound(true);
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
retVal.setCodeDisplay(result.asConceptDefinition().getDisplay());
|
||||
|
||||
String codeSystemDisplayName = result.getCodeSystemName();
|
||||
if (isBlank(codeSystemDisplayName)) {
|
||||
codeSystemDisplayName = "Unknown";
|
||||
}
|
||||
|
||||
retVal.setCodeSystemDisplayName(codeSystemDisplayName);
|
||||
retVal.setCodeSystemVersion(result.getCodeSystemVersion());
|
||||
retVal.setProperties(result.getProperties());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
retVal.setFound(false);
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
return retVal;
|
||||
|
||||
return IContextValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -182,62 +124,17 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
}
|
||||
}
|
||||
|
||||
private List<TermConcept> toPersistedConcepts(List<ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ArrayList<TermConcept> retVal = new ArrayList<>();
|
||||
|
||||
for (ConceptDefinitionComponent next : theConcept) {
|
||||
if (isNotBlank(next.getCode())) {
|
||||
TermConcept termConcept = new TermConcept();
|
||||
termConcept.setCode(next.getCode());
|
||||
termConcept.setCodeSystemVersion(theCodeSystemVersion);
|
||||
termConcept.setDisplay(next.getDisplay());
|
||||
termConcept.addChildren(toPersistedConcepts(next.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA);
|
||||
retVal.add(termConcept);
|
||||
|
||||
for (CodeSystem.ConceptDefinitionDesignationComponent designationComponent : next.getDesignation()) {
|
||||
if (isNotBlank(designationComponent.getValue())) {
|
||||
TermConceptDesignation designation = termConcept.addDesignation();
|
||||
designation.setLanguage(designationComponent.hasLanguage() ? designationComponent.getLanguage() : null);
|
||||
if (designationComponent.hasUse()) {
|
||||
designation.setUseSystem(designationComponent.getUse().hasSystem() ? designationComponent.getUse().getSystem() : null);
|
||||
designation.setUseCode(designationComponent.getUse().hasCode() ? designationComponent.getUse().getCode() : null);
|
||||
designation.setUseDisplay(designationComponent.getUse().hasDisplay() ? designationComponent.getUse().getDisplay() : null);
|
||||
}
|
||||
designation.setValue(designationComponent.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: DM 2019-07-16 - We should also populate TermConceptProperty entities here.
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
CodeSystem csDstu3 = (CodeSystem) theResource;
|
||||
|
||||
if (cs != null && isNotBlank(cs.getUrl())) {
|
||||
String codeSystemUrl = cs.getUrl();
|
||||
Long codeSystemResourcePid = retVal.getId();
|
||||
org.hl7.fhir.r4.model.CodeSystem cs = VersionConvertor_30_40.convertCodeSystem(csDstu3);
|
||||
addPidToResource(theEntity, cs);
|
||||
|
||||
if (retVal.getDeleted() != null) {
|
||||
// deleting
|
||||
} else if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
|
||||
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", retVal.getIdDt().getValue(), cs.getContentElement().getValueAsString());
|
||||
|
||||
TermCodeSystemVersion persCs = new TermCodeSystemVersion();
|
||||
persCs.setResource(retVal);
|
||||
persCs.getConcepts().addAll(toPersistedConcepts(cs.getConcept(), persCs));
|
||||
ourLog.info("Code system has {} concepts", persCs.getConcepts().size());
|
||||
myTerminologySvc.storeNewCodeSystemVersion(codeSystemResourcePid, codeSystemUrl, cs.getName(), persCs);
|
||||
|
||||
}
|
||||
}
|
||||
myTerminologySvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
|
@ -238,8 +238,8 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
|||
}
|
||||
// String code = theCode.getValue();
|
||||
// String system = toStringOrNull(theSystem);
|
||||
LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
||||
if (result.isFound()) {
|
||||
IContextValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
||||
if (result != null && result.isFound()) {
|
||||
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult retVal = new ValidateCodeResult(true, "Found code", result.getCodeDisplay());
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3, Ap
|
|||
@Override
|
||||
@Transactional(value = TxType.SUPPORTS)
|
||||
public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) {
|
||||
return fetchCodeSystem(theCtx, theSystem) != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -193,6 +193,11 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3, Ap
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
return null;
|
||||
|
|
|
@ -20,14 +20,10 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
|
@ -37,29 +33,25 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.r4.hapi.validation.ValidationSupportChain;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4.class);
|
||||
|
||||
@Autowired
|
||||
private ITermCodeSystemVersionDao myCsvDao;
|
||||
@Autowired
|
||||
private ITermCodeSystemDao myCsDao;
|
||||
@Autowired
|
||||
|
@ -76,8 +68,9 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
|
|||
return valueSetIds;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
public IContextValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
|
@ -104,37 +97,15 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
|
|||
if (myValidationSupport.isCodeSystemSupported(getContext(), system)) {
|
||||
|
||||
ourLog.info("Code system {} is supported", system);
|
||||
|
||||
CodeValidationResult result = myValidationSupport.validateCode(getContext(), system, code, null);
|
||||
if (result != null) {
|
||||
if (result.isOk()) {
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
retVal.setFound(true);
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
retVal.setCodeDisplay(result.asConceptDefinition().getDisplay());
|
||||
|
||||
String codeSystemDisplayName = result.getCodeSystemName();
|
||||
if (isBlank(codeSystemDisplayName)) {
|
||||
codeSystemDisplayName = "Unknown";
|
||||
}
|
||||
|
||||
retVal.setCodeSystemDisplayName(codeSystemDisplayName);
|
||||
retVal.setCodeSystemVersion(result.getCodeSystemVersion());
|
||||
retVal.setProperties(result.getProperties());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
IContextValidationSupport.LookupCodeResult retVal = myValidationSupport.lookupCode(getContext(), system, code);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
LookupCodeResult retVal = new LookupCodeResult();
|
||||
retVal.setFound(false);
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
return retVal;
|
||||
return IContextValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
|
||||
}
|
||||
|
||||
|
@ -156,66 +127,15 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
|
|||
}
|
||||
}
|
||||
|
||||
private List<TermConcept> toPersistedConcepts(List<ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ArrayList<TermConcept> retVal = new ArrayList<>();
|
||||
|
||||
for (ConceptDefinitionComponent next : theConcept) {
|
||||
if (isNotBlank(next.getCode())) {
|
||||
TermConcept termConcept = new TermConcept();
|
||||
termConcept.setCode(next.getCode());
|
||||
termConcept.setCodeSystemVersion(theCodeSystemVersion);
|
||||
termConcept.setDisplay(next.getDisplay());
|
||||
termConcept.addChildren(toPersistedConcepts(next.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA);
|
||||
retVal.add(termConcept);
|
||||
|
||||
for (CodeSystem.ConceptDefinitionDesignationComponent designationComponent : next.getDesignation()) {
|
||||
if (isNotBlank(designationComponent.getValue())) {
|
||||
TermConceptDesignation designation = termConcept.addDesignation();
|
||||
designation.setLanguage(designationComponent.hasLanguage() ? designationComponent.getLanguage() : null);
|
||||
if (designationComponent.hasUse()) {
|
||||
designation.setUseSystem(designationComponent.getUse().hasSystem() ? designationComponent.getUse().getSystem() : null);
|
||||
designation.setUseCode(designationComponent.getUse().hasCode() ? designationComponent.getUse().getCode() : null);
|
||||
designation.setUseDisplay(designationComponent.getUse().hasDisplay() ? designationComponent.getUse().getDisplay() : null);
|
||||
}
|
||||
designation.setValue(designationComponent.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: DM 2019-07-16 - We should also populate TermConceptProperty entities here.
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
addPidToResource(theEntity, theResource);
|
||||
|
||||
if (cs != null && isNotBlank(cs.getUrl())) {
|
||||
String codeSystemUrl = cs.getUrl();
|
||||
if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
|
||||
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", retVal.getIdDt().getValue(), cs.getContentElement().getValueAsString());
|
||||
|
||||
Long codeSystemResourcePid = retVal.getId();
|
||||
TermCodeSystemVersion persCs = myCsvDao.findCurrentVersionForCodeSystemResourcePid(codeSystemResourcePid);
|
||||
if (persCs != null) {
|
||||
ourLog.info("Code system version already exists in database");
|
||||
} else {
|
||||
|
||||
persCs = new TermCodeSystemVersion();
|
||||
persCs.setResource(retVal);
|
||||
persCs.getConcepts().addAll(toPersistedConcepts(cs.getConcept(), persCs));
|
||||
ourLog.info("Code system has {} concepts", persCs.getConcepts().size());
|
||||
myTerminologySvc.storeNewCodeSystemVersion(codeSystemResourcePid, codeSystemUrl, cs.getName(), persCs);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
myTerminologySvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
|
@ -239,7 +239,7 @@ public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> imple
|
|||
}
|
||||
// String code = theCode.getValue();
|
||||
// String system = toStringOrNull(theSystem);
|
||||
LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
||||
IContextValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(theCode, theSystem, null, null);
|
||||
if (result.isFound()) {
|
||||
ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult retVal = new ValidateCodeResult(true, "Found code", result.getCodeDisplay());
|
||||
return retVal;
|
||||
|
|
|
@ -173,7 +173,7 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4, Applicat
|
|||
@Override
|
||||
@Transactional(value = TxType.SUPPORTS)
|
||||
public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) {
|
||||
return fetchCodeSystem(theCtx, theSystem) != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -195,6 +195,11 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4, Applicat
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theProfileName) {
|
||||
return null;
|
||||
|
|
|
@ -63,6 +63,13 @@ public class TermCodeSystem implements Serializable {
|
|||
@Column(name = "CS_NAME", nullable = true, length = MAX_NAME_LENGTH)
|
||||
private String myName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TermCodeSystem() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getCodeSystemUri() {
|
||||
return myCodeSystemUri;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,9 @@ public class TermCodeSystemVersion implements Serializable {
|
|||
@OneToOne(mappedBy = "myCurrentVersion", optional = true)
|
||||
private TermCodeSystem myCodeSystemHavingThisVersionAsCurrentVersionIfAny;
|
||||
|
||||
@Column(name = "CS_DISPLAY", nullable = true, updatable = false, length = MAX_VERSION_LENGTH)
|
||||
private String myCodeSystemDisplayName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -155,4 +158,14 @@ public class TermCodeSystemVersion implements Serializable {
|
|||
return result;
|
||||
}
|
||||
|
||||
public String getCodeSystemDisplayName() {
|
||||
return myCodeSystemDisplayName;
|
||||
}
|
||||
|
||||
public void setCodeSystemDisplayName(String theCodeSystemDisplayName) {
|
||||
ValidateUtil.isNotTooLongOrThrowIllegalArgument(
|
||||
theCodeSystemDisplayName, MAX_VERSION_LENGTH,
|
||||
"Version ID exceeds maximum length (" + MAX_VERSION_LENGTH + "): " + length(theCodeSystemDisplayName));
|
||||
myCodeSystemDisplayName = theCodeSystemDisplayName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ public class TermConcept implements Serializable {
|
|||
setCode(theCode);
|
||||
}
|
||||
|
||||
public TermConcept addChild(TermConcept theChild, RelationshipTypeEnum theRelationshipType) {
|
||||
public TermConceptParentChildLink addChild(TermConcept theChild, RelationshipTypeEnum theRelationshipType) {
|
||||
Validate.notNull(theRelationshipType, "theRelationshipType must not be null");
|
||||
TermConceptParentChildLink link = new TermConceptParentChildLink();
|
||||
link.setParent(this);
|
||||
|
@ -120,7 +120,7 @@ public class TermConcept implements Serializable {
|
|||
getChildren().add(link);
|
||||
|
||||
theChild.getParents().add(link);
|
||||
return this;
|
||||
return link;
|
||||
}
|
||||
|
||||
public void addChildren(List<TermConcept> theChildren, RelationshipTypeEnum theRelationshipType) {
|
||||
|
|
|
@ -66,6 +66,14 @@ public class TermConceptProperty implements Serializable {
|
|||
private String myValue;
|
||||
@Column(name = "PROP_TYPE", nullable = false, length = MAX_PROPTYPE_ENUM_LENGTH)
|
||||
private TermConceptPropertyTypeEnum myType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TermConceptProperty() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
|
||||
*/
|
||||
|
|
|
@ -20,12 +20,8 @@ package ca.uhn.fhir.jpa.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
|
@ -34,27 +30,33 @@ import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
|||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.primitive.*;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDstu2<ValueSet> {
|
||||
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_EXPAND, idempotent = true)
|
||||
public ValueSet expand(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional=true) IdDt theId,
|
||||
@OperationParam(name="valueSet", min=0, max=1) ValueSet theValueSet,
|
||||
@OperationParam(name="identifier", min=0, max=1) UriDt theIdentifier,
|
||||
@OperationParam(name = "filter", min=0, max=1) StringDt theFilter,
|
||||
RequestDetails theRequestDetails) {
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional = true) IdDt theId,
|
||||
@OperationParam(name = "valueSet", min = 0, max = 1) ValueSet theValueSet,
|
||||
@OperationParam(name = "identifier", min = 0, max = 1) UriDt theIdentifier,
|
||||
@OperationParam(name = "filter", min = 0, max = 1) StringDt theFilter,
|
||||
RequestDetails theRequestDetails) {
|
||||
|
||||
boolean haveId = theId != null && theId.hasIdPart();
|
||||
boolean haveIdentifier = theIdentifier != null && isNotBlank(theIdentifier.getValue());
|
||||
boolean haveValueSet = theValueSet != null && theValueSet.isEmpty() == false;
|
||||
|
||||
|
||||
if (!haveId && !haveIdentifier && !haveValueSet) {
|
||||
throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request");
|
||||
}
|
||||
|
@ -62,7 +64,7 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
if (moreThanOneTrue(haveId, haveIdentifier, haveValueSet)) {
|
||||
throw new InvalidRequestException("$expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.");
|
||||
}
|
||||
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
|
@ -73,51 +75,35 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
} else {
|
||||
return dao.expand(theValueSet, toFilterString(theFilter));
|
||||
}
|
||||
|
||||
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean moreThanOneTrue(boolean... theBooleans) {
|
||||
boolean haveOne = false;
|
||||
for (boolean next : theBooleans) {
|
||||
if (next) {
|
||||
if (haveOne) {
|
||||
return true;
|
||||
} else {
|
||||
haveOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private String toFilterString(StringDt theFilter) {
|
||||
return theFilter != null ? theFilter.getValue() : null;
|
||||
}
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters= {
|
||||
@OperationParam(name="name", type=StringDt.class, min=1),
|
||||
@OperationParam(name="version", type=StringDt.class, min=0),
|
||||
@OperationParam(name="display", type=StringDt.class, min=1),
|
||||
@OperationParam(name="abstract", type=BooleanDt.class, min=1),
|
||||
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "name", type = StringDt.class, min = 1),
|
||||
@OperationParam(name = "version", type = StringDt.class, min = 0),
|
||||
@OperationParam(name = "display", type = StringDt.class, min = 1),
|
||||
@OperationParam(name = "abstract", type = BooleanDt.class, min = 1),
|
||||
})
|
||||
public Parameters lookup(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name="code", min=0, max=1) CodeDt theCode,
|
||||
@OperationParam(name="system", min=0, max=1) UriDt theSystem,
|
||||
@OperationParam(name="coding", min=0, max=1) CodingDt theCoding,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "code", min = 0, max = 1) CodeDt theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1) UriDt theSystem,
|
||||
@OperationParam(name = "coding", min = 0, max = 1) CodingDt theCoding,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoCodeSystem<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoCodeSystem<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
|
||||
if (result.isFound()==false) {
|
||||
IContextValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
|
||||
if (result.isFound() == false) {
|
||||
throw new ResourceNotFoundException("Unable to find code[" + result.getSearchedForCode() + "] in system[" + result.getSearchedForSystem() + "]");
|
||||
}
|
||||
Parameters retVal = new Parameters();
|
||||
|
@ -126,30 +112,29 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
retVal.addParameter().setName("version").setValue(new StringDt(result.getCodeSystemVersion()));
|
||||
}
|
||||
retVal.addParameter().setName("display").setValue(new StringDt(result.getCodeDisplay()));
|
||||
retVal.addParameter().setName("abstract").setValue(new BooleanDt(result.isCodeIsAbstract()));
|
||||
retVal.addParameter().setName("abstract").setValue(new BooleanDt(result.isCodeIsAbstract()));
|
||||
return retVal;
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters= {
|
||||
@OperationParam(name="result", type=BooleanDt.class, min=1),
|
||||
@OperationParam(name="message", type=StringDt.class),
|
||||
@OperationParam(name="display", type=StringDt.class)
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "result", type = BooleanDt.class, min = 1),
|
||||
@OperationParam(name = "message", type = StringDt.class),
|
||||
@OperationParam(name = "display", type = StringDt.class)
|
||||
})
|
||||
public Parameters validateCode(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional=true) IdDt theId,
|
||||
@OperationParam(name="identifier", min=0, max=1) UriDt theValueSetIdentifier,
|
||||
@OperationParam(name="code", min=0, max=1) CodeDt theCode,
|
||||
@OperationParam(name="system", min=0, max=1) UriDt theSystem,
|
||||
@OperationParam(name="display", min=0, max=1) StringDt theDisplay,
|
||||
@OperationParam(name="coding", min=0, max=1) CodingDt theCoding,
|
||||
@OperationParam(name="codeableConcept", min=0, max=1) CodeableConceptDt theCodeableConcept,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional = true) IdDt theId,
|
||||
@OperationParam(name = "identifier", min = 0, max = 1) UriDt theValueSetIdentifier,
|
||||
@OperationParam(name = "code", min = 0, max = 1) CodeDt theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1) UriDt theSystem,
|
||||
@OperationParam(name = "display", min = 0, max = 1) StringDt theDisplay,
|
||||
@OperationParam(name = "coding", min = 0, max = 1) CodingDt theCoding,
|
||||
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConceptDt theCodeableConcept,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
|
@ -169,5 +154,19 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean moreThanOneTrue(boolean... theBooleans) {
|
||||
boolean haveOne = false;
|
||||
for (boolean next : theBooleans) {
|
||||
if (next) {
|
||||
if (haveOne) {
|
||||
return true;
|
||||
} else {
|
||||
haveOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,142 +1,19 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2019 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
|
||||
/**
|
||||
* @deprecated TerminologyUploaderProvider
|
||||
*/
|
||||
@Deprecated
|
||||
public class BaseTerminologyUploaderProvider {
|
||||
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc.UploadStatistics;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
public abstract class BaseTerminologyUploaderProvider extends BaseJpaProvider {
|
||||
public static final String UPLOAD_EXTERNAL_CODE_SYSTEM = "$upload-external-code-system";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseTerminologyUploaderProvider.class);
|
||||
// FIXME: remove these before 4.0.0
|
||||
public static final String UPLOAD_EXTERNAL_CODE_SYSTEM = JpaConstants.OPERATION_UPLOAD_EXTERNAL_CODE_SYSTEM;
|
||||
public static final String CONCEPT_COUNT = "conceptCount";
|
||||
public static final String TARGET = "target";
|
||||
|
||||
@Autowired
|
||||
private IHapiTerminologyLoaderSvc myTerminologyLoaderSvc;
|
||||
|
||||
protected Parameters handleUploadExternalCodeSystem(
|
||||
HttpServletRequest theServletRequest,
|
||||
StringParam theCodeSystemUrl,
|
||||
List<StringType> theLocalFile,
|
||||
List<Attachment> thePackage, RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
|
||||
if (theLocalFile == null || theLocalFile.size() == 0) {
|
||||
if (thePackage == null || thePackage.size() == 0) {
|
||||
throw new InvalidRequestException("No 'localfile' or 'package' parameter, or package had no data");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
List<IHapiTerminologyLoaderSvc.FileDescriptor> localFiles = new ArrayList<>();
|
||||
if (theLocalFile != null && theLocalFile.size() > 0) {
|
||||
for (StringType nextLocalFile : theLocalFile) {
|
||||
if (isNotBlank(nextLocalFile.getValue())) {
|
||||
ourLog.info("Reading in local file: {}", nextLocalFile.getValue());
|
||||
File nextFile = new File(nextLocalFile.getValue());
|
||||
if (!nextFile.exists() || !nextFile.isFile()) {
|
||||
throw new InvalidRequestException("Unknown file: " + nextFile.getName());
|
||||
}
|
||||
localFiles.add(new IHapiTerminologyLoaderSvc.FileDescriptor() {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return nextFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return new FileInputStream(nextFile);
|
||||
} catch (FileNotFoundException theE) {
|
||||
throw new InternalErrorException(theE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thePackage != null) {
|
||||
for (Attachment nextPackage : thePackage) {
|
||||
if (isBlank(nextPackage.getUrl())) {
|
||||
throw new UnprocessableEntityException("Package is missing mandatory url element");
|
||||
}
|
||||
|
||||
localFiles.add(new IHapiTerminologyLoaderSvc.FileDescriptor() {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return nextPackage.getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return new ByteArrayInputStream(nextPackage.getData());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String url = theCodeSystemUrl != null ? theCodeSystemUrl.getValue() : null;
|
||||
url = defaultString(url);
|
||||
|
||||
UploadStatistics stats;
|
||||
switch(url) {
|
||||
case IHapiTerminologyLoaderSvc.SCT_URI:
|
||||
stats = myTerminologyLoaderSvc.loadSnomedCt(localFiles, theRequestDetails);
|
||||
break;
|
||||
case IHapiTerminologyLoaderSvc.LOINC_URI:
|
||||
stats = myTerminologyLoaderSvc.loadLoinc(localFiles, theRequestDetails);
|
||||
break;
|
||||
case IHapiTerminologyLoaderSvc.IMGTHLA_URI:
|
||||
stats = myTerminologyLoaderSvc.loadImgthla(localFiles, theRequestDetails);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidRequestException("Unknown URL: " + url);
|
||||
}
|
||||
|
||||
Parameters retVal = new Parameters();
|
||||
retVal.addParameter().setName(CONCEPT_COUNT).setValue(new IntegerType(stats.getConceptCount()));
|
||||
retVal.addParameter().setName(TARGET).setValue(new Reference(stats.getTarget().getValue()));
|
||||
return retVal;
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String SYSTEM = "system";
|
||||
public static final String PARENT_CODE = "parentCode";
|
||||
public static final String VALUE = "value";
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2019 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc.UploadStatistics;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.AttachmentUtil;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.ICompositeType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
public abstract class TerminologyUploaderProvider extends BaseJpaProvider {
|
||||
|
||||
public static final String CONCEPT_COUNT = "conceptCount";
|
||||
public static final String TARGET = "target";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TerminologyUploaderProvider.class);
|
||||
public static final String PARENT_CODE = "parentCode";
|
||||
public static final String VALUE = "value";
|
||||
|
||||
@Autowired
|
||||
private FhirContext myCtx;
|
||||
@Autowired
|
||||
private IHapiTerminologyLoaderSvc myTerminologyLoaderSvc;
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myTerminologySvc;
|
||||
|
||||
/**
|
||||
* <code>
|
||||
* $apply-codesystem-delta-add
|
||||
* </code>
|
||||
*/
|
||||
@Operation(typeName="CodeSystem", name = JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_ADD, idempotent = false, returnParameters = {
|
||||
})
|
||||
public IBaseParameters applyCodeSystemDeltaAdd(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = PARENT_CODE, min = 0, max = 1) IPrimitiveType<String> theParentCode,
|
||||
@OperationParam(name = VALUE, min = 1, max = 1) IBaseResource theValue,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
|
||||
CodeSystem value;
|
||||
if (theValue instanceof CodeSystem) {
|
||||
value = (CodeSystem) theValue;
|
||||
} else if (theValue instanceof org.hl7.fhir.dstu3.model.CodeSystem) {
|
||||
value = VersionConvertor_30_40.convertCodeSystem((org.hl7.fhir.dstu3.model.CodeSystem) theValue);
|
||||
} else {
|
||||
throw new InvalidRequestException("Value must be present and be a CodeSystem");
|
||||
}
|
||||
|
||||
String system = value.getUrl();
|
||||
String parentCode = theParentCode != null ? theParentCode.getValue() : null;
|
||||
|
||||
AtomicInteger counter = myTerminologySvc.applyDeltaCodesystemsAdd(system, parentCode, value);
|
||||
|
||||
IBaseParameters retVal = ParametersUtil.newInstance(myCtx);
|
||||
ParametersUtil.addParameterToParametersBoolean(myCtx, retVal, "success", true);
|
||||
ParametersUtil.addParameterToParametersInteger(myCtx, retVal, "addedConcepts", counter.get());
|
||||
return retVal;
|
||||
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <code>
|
||||
* $apply-codesystem-delta-remove
|
||||
* </code>
|
||||
*/
|
||||
@Operation(typeName="CodeSystem", name = JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_REMOVE, idempotent = false, returnParameters = {
|
||||
})
|
||||
public IBaseParameters applyCodeSystemDeltaRemove(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = VALUE, min = 1, max = 1) IBaseResource theValue,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
|
||||
CodeSystem value;
|
||||
if (theValue instanceof CodeSystem) {
|
||||
value = (CodeSystem) theValue;
|
||||
} else if (theValue instanceof org.hl7.fhir.dstu3.model.CodeSystem) {
|
||||
value = VersionConvertor_30_40.convertCodeSystem((org.hl7.fhir.dstu3.model.CodeSystem) theValue);
|
||||
} else {
|
||||
throw new InvalidRequestException("Value must be present and be a CodeSystem");
|
||||
}
|
||||
|
||||
String system = value.getUrl();
|
||||
|
||||
AtomicInteger counter = myTerminologySvc.applyDeltaCodesystemsRemove(system, value);
|
||||
|
||||
IBaseParameters retVal = ParametersUtil.newInstance(myCtx);
|
||||
ParametersUtil.addParameterToParametersBoolean(myCtx, retVal, "success", true);
|
||||
ParametersUtil.addParameterToParametersInteger(myCtx, retVal, "removedConcepts", counter.get());
|
||||
return retVal;
|
||||
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <code>
|
||||
* $upload-external-codesystem
|
||||
* </code>
|
||||
*/
|
||||
@Operation(typeName="CodeSystem", name = JpaConstants.OPERATION_UPLOAD_EXTERNAL_CODE_SYSTEM, idempotent = false, returnParameters = {
|
||||
// @OperationParam(name = "conceptCount", type = IntegerType.class, min = 1)
|
||||
})
|
||||
public IBaseParameters uploadExternalCodeSystem(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "url", min = 1, typeName = "uri") IPrimitiveType<String> theCodeSystemUrl,
|
||||
@OperationParam(name = "localfile", min = 1, max = OperationParam.MAX_UNLIMITED, typeName = "string") List<IPrimitiveType<String>> theLocalFile,
|
||||
@OperationParam(name = "package", min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "attachment") List<ICompositeType> thePackage,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
|
||||
if (theLocalFile == null || theLocalFile.size() == 0) {
|
||||
if (thePackage == null || thePackage.size() == 0) {
|
||||
throw new InvalidRequestException("No 'localfile' or 'package' parameter, or package had no data");
|
||||
}
|
||||
for (ICompositeType next : thePackage) {
|
||||
ValidateUtil.isTrueOrThrowInvalidRequest(myCtx.getElementDefinition(next.getClass()).getName().equals("Attachment"), "Package must be of type Attachment");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
List<IHapiTerminologyLoaderSvc.FileDescriptor> localFiles = new ArrayList<>();
|
||||
if (theLocalFile != null && theLocalFile.size() > 0) {
|
||||
for (IPrimitiveType<String> nextLocalFile : theLocalFile) {
|
||||
if (isNotBlank(nextLocalFile.getValue())) {
|
||||
ourLog.info("Reading in local file: {}", nextLocalFile.getValue());
|
||||
File nextFile = new File(nextLocalFile.getValue());
|
||||
if (!nextFile.exists() || !nextFile.isFile()) {
|
||||
throw new InvalidRequestException("Unknown file: " + nextFile.getName());
|
||||
}
|
||||
localFiles.add(new IHapiTerminologyLoaderSvc.FileDescriptor() {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return nextFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return new FileInputStream(nextFile);
|
||||
} catch (FileNotFoundException theE) {
|
||||
throw new InternalErrorException(theE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thePackage != null) {
|
||||
for (ICompositeType nextPackage : thePackage) {
|
||||
final String url = AttachmentUtil.getOrCreateUrl(myCtx, nextPackage).getValueAsString();
|
||||
|
||||
if (isBlank(url)) {
|
||||
throw new UnprocessableEntityException("Package is missing mandatory url element");
|
||||
}
|
||||
|
||||
localFiles.add(new IHapiTerminologyLoaderSvc.FileDescriptor() {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
byte[] data = AttachmentUtil.getOrCreateData(myCtx, nextPackage).getValue();
|
||||
return new ByteArrayInputStream(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String url = theCodeSystemUrl != null ? theCodeSystemUrl.getValue() : null;
|
||||
url = defaultString(url);
|
||||
|
||||
UploadStatistics stats;
|
||||
switch (url) {
|
||||
case IHapiTerminologyLoaderSvc.SCT_URI:
|
||||
stats = myTerminologyLoaderSvc.loadSnomedCt(localFiles, theRequestDetails);
|
||||
break;
|
||||
case IHapiTerminologyLoaderSvc.LOINC_URI:
|
||||
stats = myTerminologyLoaderSvc.loadLoinc(localFiles, theRequestDetails);
|
||||
break;
|
||||
case IHapiTerminologyLoaderSvc.IMGTHLA_URI:
|
||||
stats = myTerminologyLoaderSvc.loadImgthla(localFiles, theRequestDetails);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidRequestException("Unknown URL: " + url);
|
||||
}
|
||||
|
||||
IBaseParameters retVal = ParametersUtil.newInstance(myCtx);
|
||||
ParametersUtil.addParameterToParametersBoolean(myCtx, retVal, "success", true);
|
||||
ParametersUtil.addParameterToParametersInteger(myCtx, retVal, CONCEPT_COUNT, stats.getConceptCount());
|
||||
ParametersUtil.addParameterToParametersReference(myCtx, retVal, TARGET, stats.getTarget().getValue());
|
||||
|
||||
return retVal;
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -20,14 +20,13 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
||||
|
@ -36,29 +35,27 @@ import java.util.List;
|
|||
|
||||
public class BaseJpaResourceProviderCodeSystemDstu3 extends JpaResourceProviderDstu3<CodeSystem> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters= {
|
||||
@OperationParam(name="name", type=StringType.class, min=1),
|
||||
@OperationParam(name="version", type=StringType.class, min=0),
|
||||
@OperationParam(name="display", type=StringType.class, min=1),
|
||||
@OperationParam(name="abstract", type=BooleanType.class, min=1),
|
||||
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "name", type = StringType.class, min = 1),
|
||||
@OperationParam(name = "version", type = StringType.class, min = 0),
|
||||
@OperationParam(name = "display", type = StringType.class, min = 1),
|
||||
@OperationParam(name = "abstract", type = BooleanType.class, min = 1),
|
||||
})
|
||||
public Parameters lookup(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name="code", min=0, max=1) CodeType theCode,
|
||||
@OperationParam(name="system", min=0, max=1) UriType theSystem,
|
||||
@OperationParam(name="coding", min=0, max=1) Coding theCoding,
|
||||
@OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
|
||||
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
|
||||
@OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
|
||||
LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
|
||||
IContextValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
|
||||
result.throwNotFoundIfAppropriate();
|
||||
org.hl7.fhir.r4.model.Parameters parametersR4 = result.toParameters(theProperties);
|
||||
return VersionConvertor_30_40.convertParameters(parametersR4);
|
||||
return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties);
|
||||
} catch (FHIRException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} finally {
|
||||
|
@ -70,16 +67,16 @@ public class BaseJpaResourceProviderCodeSystemDstu3 extends JpaResourceProviderD
|
|||
/**
|
||||
* $subsumes operation
|
||||
*/
|
||||
@Operation(name = JpaConstants.OPERATION_SUBSUMES, idempotent = true, returnParameters= {
|
||||
@OperationParam(name="outcome", type= CodeType.class, min=1),
|
||||
@Operation(name = JpaConstants.OPERATION_SUBSUMES, idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "outcome", type = CodeType.class, min = 1),
|
||||
})
|
||||
public Parameters subsumes(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name="codeA", min=0, max=1) CodeType theCodeA,
|
||||
@OperationParam(name="codeB", min=0, max=1) CodeType theCodeB,
|
||||
@OperationParam(name="system", min=0, max=1) UriType theSystem,
|
||||
@OperationParam(name="codingA", min=0, max=1) Coding theCodingA,
|
||||
@OperationParam(name="codingB", min=0, max=1) Coding theCodingB,
|
||||
@OperationParam(name = "codeA", min = 0, max = 1) CodeType theCodeA,
|
||||
@OperationParam(name = "codeB", min = 0, max = 1) CodeType theCodeB,
|
||||
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
|
||||
@OperationParam(name = "codingA", min = 0, max = 1) Coding theCodingA,
|
||||
@OperationParam(name = "codingB", min = 0, max = 1) Coding theCodingB,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseTerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
@ -37,37 +38,10 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TerminologyUploaderProviderDstu3 extends BaseTerminologyUploaderProvider {
|
||||
|
||||
@Operation(name = UPLOAD_EXTERNAL_CODE_SYSTEM, idempotent = false, returnParameters = {
|
||||
@OperationParam(name = "conceptCount", type = IntegerType.class, min = 1)
|
||||
})
|
||||
public Parameters uploadExternalCodeSystem(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "url", min = 1) StringParam theCodeSystemUrl,
|
||||
@OperationParam(name = "localfile", min = 1, max = OperationParam.MAX_UNLIMITED) List<StringType> theLocalFile,
|
||||
@OperationParam(name = "package", min = 0, max = OperationParam.MAX_UNLIMITED) List<Attachment> thePackage,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
try {
|
||||
List<org.hl7.fhir.r4.model.StringType> localFile = null;
|
||||
if (theLocalFile != null) {
|
||||
localFile = new ArrayList<>();
|
||||
for (StringType next : theLocalFile) {
|
||||
localFile.add(VersionConvertor_30_40.convertString(next));
|
||||
}
|
||||
}
|
||||
List<org.hl7.fhir.r4.model.Attachment> pkg = null;
|
||||
if (thePackage!=null){
|
||||
pkg = new ArrayList<>();
|
||||
for (Attachment next : thePackage) {
|
||||
pkg.add(VersionConvertor_30_40.convertAttachment(next));
|
||||
}
|
||||
}
|
||||
org.hl7.fhir.r4.model.Parameters retValR4 = handleUploadExternalCodeSystem(theServletRequest, theCodeSystemUrl, localFile, pkg, theRequestDetails);
|
||||
return VersionConvertor_30_40.convertParameters(retValR4);
|
||||
} catch (FHIRException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link TerminologyUploaderProvider} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class TerminologyUploaderProviderDstu3 extends TerminologyUploaderProvider {
|
||||
// nothing
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
@ -55,9 +55,9 @@ public class BaseJpaResourceProviderCodeSystemR4 extends JpaResourceProviderR4<C
|
|||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
|
||||
LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
|
||||
IContextValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
|
||||
result.throwNotFoundIfAppropriate();
|
||||
return result.toParameters(theProperties);
|
||||
return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseTerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
@ -33,18 +34,9 @@ import org.hl7.fhir.r4.model.StringType;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
public class TerminologyUploaderProviderR4 extends BaseTerminologyUploaderProvider {
|
||||
|
||||
@Operation(name = UPLOAD_EXTERNAL_CODE_SYSTEM, idempotent = false, returnParameters = {
|
||||
@OperationParam(name = "conceptCount", type = IntegerType.class, min = 1)
|
||||
})
|
||||
public Parameters uploadExternalCodeSystem(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "url", min = 1) StringParam theCodeSystemUrl,
|
||||
@OperationParam(name = "localfile", min = 1, max = OperationParam.MAX_UNLIMITED) List<StringType> theLocalFile,
|
||||
@OperationParam(name = "package", min = 0, max = OperationParam.MAX_UNLIMITED) List<Attachment> thePackage,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
return handleUploadExternalCodeSystem(theServletRequest, theCodeSystemUrl, theLocalFile, thePackage, theRequestDetails);
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link TerminologyUploaderProvider} instead
|
||||
*/
|
||||
public class TerminologyUploaderProviderR4 extends TerminologyUploaderProvider {
|
||||
// nothing
|
||||
}
|
||||
|
|
|
@ -21,10 +21,8 @@ package ca.uhn.fhir.jpa.term;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.*;
|
||||
import ca.uhn.fhir.jpa.dao.data.*;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
|
@ -78,6 +76,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -261,6 +260,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
|
||||
protected abstract IIdType createOrUpdateCodeSystem(CodeSystem theCodeSystemResource);
|
||||
|
||||
protected void validateCodeSystemForStorage(CodeSystem theCodeSystemResource) {
|
||||
ValidateUtil.isNotBlankOrThrowUnprocessableEntity(theCodeSystemResource.getUrl(), "Can not store a CodeSystem without a valid URL");
|
||||
}
|
||||
|
||||
protected abstract void createOrUpdateConceptMap(ConceptMap theNextConceptMap);
|
||||
|
||||
abstract void createOrUpdateValueSet(ValueSet theValueSet);
|
||||
|
@ -767,9 +770,17 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
|
||||
@Override
|
||||
public Optional<TermConcept> findCode(String theCodeSystem, String theCode) {
|
||||
TermCodeSystemVersion csv = findCurrentCodeSystemVersionForSystem(theCodeSystem);
|
||||
|
||||
return myConceptDao.findByCodeSystemAndCode(csv, theCode);
|
||||
/*
|
||||
* Loading concepts without a transaction causes issues later on some
|
||||
* platforms (e.g. PSQL) so this transactiontemplate is here to make
|
||||
* sure that we always call this with an open transaction
|
||||
*/
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
return txTemplate.execute(t->{
|
||||
TermCodeSystemVersion csv = findCurrentCodeSystemVersionForSystem(theCodeSystem);
|
||||
return myConceptDao.findByCodeSystemAndCode(csv, theCode);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1036,6 +1047,37 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of saved concepts
|
||||
*/
|
||||
private int saveOrUpdateConcept(TermConcept theConcept) {
|
||||
|
||||
TermCodeSystemVersion csv = theConcept.getCodeSystemVersion();
|
||||
Optional<TermConcept> existing = myConceptDao.findByCodeSystemAndCode(csv, theConcept.getCode());
|
||||
if (existing.isPresent()) {
|
||||
TermConcept existingConcept = existing.get();
|
||||
boolean haveChanges = false;
|
||||
if (!StringUtils.equals(existingConcept.getDisplay(), theConcept.getDisplay())) {
|
||||
existingConcept.setDisplay(theConcept.getDisplay());
|
||||
haveChanges = true;
|
||||
}
|
||||
|
||||
if (!haveChanges) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
myConceptDao.save(existingConcept);
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
return saveConcept(theConcept);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of saved concepts
|
||||
*/
|
||||
private int saveConcept(TermConcept theConcept) {
|
||||
int retVal = 0;
|
||||
|
||||
|
@ -1124,7 +1166,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
public void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ourLog.info("Storing code system");
|
||||
|
||||
ValidateUtil.isTrueOrThrowInvalidRequest(theCodeSystemVersion.getResource() != null, "No resource supplied");
|
||||
|
@ -1170,6 +1212,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
}
|
||||
theCodeSystemVersion.setCodeSystem(codeSystem);
|
||||
|
||||
theCodeSystemVersion.setCodeSystemDisplayName(theSystemName);
|
||||
theCodeSystemVersion.setCodeSystemVersionId(theSystemVersionId);
|
||||
|
||||
ourLog.info("Validating all codes in CodeSystem for storage (this can take some time for large sets)");
|
||||
|
||||
// Validate the code system
|
||||
|
@ -1226,8 +1271,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
|
||||
ourLog.info("CodeSystem resource has ID: {}", csId.getValue());
|
||||
|
||||
theCodeSystemVersion.setResource(resource);
|
||||
storeNewCodeSystemVersion(codeSystemResourcePid, theCodeSystemResource.getUrl(), theCodeSystemResource.getName(), theCodeSystemVersion);
|
||||
populateCodeSystemVersionProperties(theCodeSystemVersion, theCodeSystemResource, resource);
|
||||
|
||||
storeNewCodeSystemVersion(codeSystemResourcePid, theCodeSystemResource.getUrl(), theCodeSystemResource.getName(), theCodeSystemResource.getVersion(), theCodeSystemVersion);
|
||||
|
||||
myDeferredConceptMaps.addAll(theConceptMaps);
|
||||
myDeferredValueSets.addAll(theValueSets);
|
||||
|
@ -1235,6 +1281,99 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
return csId;
|
||||
}
|
||||
|
||||
private void populateCodeSystemVersionProperties(TermCodeSystemVersion theCodeSystemVersion, CodeSystem theCodeSystemResource, ResourceTable theResourceTable) {
|
||||
theCodeSystemVersion.setResource(theResourceTable);
|
||||
theCodeSystemVersion.setCodeSystemDisplayName(theCodeSystemResource.getName());
|
||||
theCodeSystemVersion.setCodeSystemVersionId(theCodeSystemResource.getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeNewCodeSystemVersionIfNeeded(CodeSystem theCodeSystem, ResourceTable theResourceEntity) {
|
||||
if (theCodeSystem != null && isNotBlank(theCodeSystem.getUrl())) {
|
||||
String codeSystemUrl = theCodeSystem.getUrl();
|
||||
if (theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.COMPLETE || theCodeSystem.getContent() == null || theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.NOTPRESENT) {
|
||||
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", theResourceEntity.getIdDt().getValue(), theCodeSystem.getContentElement().getValueAsString());
|
||||
|
||||
Long codeSystemResourcePid = IDao.RESOURCE_PID.get(theCodeSystem);
|
||||
TermCodeSystemVersion persCs = myCodeSystemVersionDao.findCurrentVersionForCodeSystemResourcePid(codeSystemResourcePid);
|
||||
if (persCs != null) {
|
||||
ourLog.info("Code system version already exists in database");
|
||||
} else {
|
||||
|
||||
persCs = new TermCodeSystemVersion();
|
||||
populateCodeSystemVersionProperties(persCs, theCodeSystem, theResourceEntity);
|
||||
|
||||
persCs.getConcepts().addAll(toPersistedConcepts(theCodeSystem.getConcept(), persCs));
|
||||
ourLog.info("Code system has {} concepts", persCs.getConcepts().size());
|
||||
storeNewCodeSystemVersion(codeSystemResourcePid, codeSystemUrl, theCodeSystem.getName(), theCodeSystem.getVersion(), persCs);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<TermConcept> toPersistedConcepts(List<CodeSystem.ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ArrayList<TermConcept> retVal = new ArrayList<>();
|
||||
|
||||
for (CodeSystem.ConceptDefinitionComponent next : theConcept) {
|
||||
if (isNotBlank(next.getCode())) {
|
||||
TermConcept termConcept = toTermConcept(next, theCodeSystemVersion);
|
||||
retVal.add(termConcept);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private TermConcept toTermConcept(CodeSystem.ConceptDefinitionComponent theConceptDefinition, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
TermConcept termConcept = new TermConcept();
|
||||
termConcept.setCode(theConceptDefinition.getCode());
|
||||
termConcept.setCodeSystemVersion(theCodeSystemVersion);
|
||||
termConcept.setDisplay(theConceptDefinition.getDisplay());
|
||||
termConcept.addChildren(toPersistedConcepts(theConceptDefinition.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA);
|
||||
|
||||
for (CodeSystem.ConceptDefinitionDesignationComponent designationComponent : theConceptDefinition.getDesignation()) {
|
||||
if (isNotBlank(designationComponent.getValue())) {
|
||||
TermConceptDesignation designation = termConcept.addDesignation();
|
||||
designation.setLanguage(designationComponent.hasLanguage() ? designationComponent.getLanguage() : null);
|
||||
if (designationComponent.hasUse()) {
|
||||
designation.setUseSystem(designationComponent.getUse().hasSystem() ? designationComponent.getUse().getSystem() : null);
|
||||
designation.setUseCode(designationComponent.getUse().hasCode() ? designationComponent.getUse().getCode() : null);
|
||||
designation.setUseDisplay(designationComponent.getUse().hasDisplay() ? designationComponent.getUse().getDisplay() : null);
|
||||
}
|
||||
designation.setValue(designationComponent.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (CodeSystem.ConceptPropertyComponent next : theConceptDefinition.getProperty()) {
|
||||
TermConceptProperty property = new TermConceptProperty();
|
||||
|
||||
property.setKey(next.getCode());
|
||||
property.setConcept(termConcept);
|
||||
property.setCodeSystemVersion(theCodeSystemVersion);
|
||||
|
||||
if (next.getValue() instanceof StringType) {
|
||||
property.setType(TermConceptPropertyTypeEnum.STRING);
|
||||
property.setValue(next.getValueStringType().getValue());
|
||||
} else if (next.getValue() instanceof Coding) {
|
||||
Coding nextCoding = next.getValueCoding();
|
||||
property.setType(TermConceptPropertyTypeEnum.CODING);
|
||||
property.setCodeSystem(nextCoding.getSystem());
|
||||
property.setValue(nextCoding.getCode());
|
||||
property.setDisplay(nextCoding.getDisplay());
|
||||
} else if (next.getValue() != null) {
|
||||
// TODO: LOINC has properties of type BOOLEAN that we should handle
|
||||
ourLog.warn("Don't know how to handle properties of type: " + next.getValue().getClass());
|
||||
continue;
|
||||
}
|
||||
|
||||
termConcept.getProperties().add(property);
|
||||
}
|
||||
return termConcept;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void storeTermConceptMapAndChildren(ResourceTable theResourceTable, ConceptMap theConceptMap) {
|
||||
|
@ -1443,6 +1582,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
|
||||
VersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA);
|
||||
VersionIndependentConcept conceptB = toConcept(theCodeB, theSystem, theCodingB);
|
||||
|
@ -1471,6 +1611,136 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
return new IFhirResourceDaoCodeSystem.SubsumesResult(subsumes);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public AtomicInteger applyDeltaCodesystemsAdd(String theSystem, @Nullable String theParent, CodeSystem theValue) {
|
||||
TermCodeSystem cs = getCodeSystem(theSystem);
|
||||
if (cs == null) {
|
||||
List<CodeSystem.ConceptDefinitionComponent> codes = theValue.getConcept();
|
||||
theValue.setConcept(null);
|
||||
createOrUpdateCodeSystem(theValue);
|
||||
cs = getCodeSystem(theSystem);
|
||||
theValue.setConcept(codes);
|
||||
}
|
||||
|
||||
TermCodeSystemVersion csv = cs.getCurrentVersion();
|
||||
|
||||
AtomicInteger addedCodeCounter = new AtomicInteger(0);
|
||||
|
||||
TermConcept parentCode = null;
|
||||
if (isNotBlank(theParent)) {
|
||||
parentCode = myConceptDao
|
||||
.findByCodeSystemAndCode(csv, theParent)
|
||||
.orElseThrow(() -> new InvalidRequestException("Unknown code [" + theSystem + "|" + theParent + "]"));
|
||||
}
|
||||
|
||||
List<TermConcept> concepts = new ArrayList<>();
|
||||
for (CodeSystem.ConceptDefinitionComponent next : theValue.getConcept()) {
|
||||
TermConcept concept = toTermConcept(next, csv);
|
||||
if (parentCode != null) {
|
||||
parentCode.addChild(concept, RelationshipTypeEnum.ISA);
|
||||
}
|
||||
concepts.add(concept);
|
||||
}
|
||||
|
||||
// The first pass just saves any concepts that were added to the
|
||||
// root of the CodeSystem
|
||||
List<TermConceptParentChildLink> links = new ArrayList<>();
|
||||
for (TermConcept next : concepts) {
|
||||
int addedCount = saveOrUpdateConcept(next);
|
||||
addedCodeCounter.addAndGet(addedCount);
|
||||
extractLinksFromConceptAndChildren(next, links);
|
||||
}
|
||||
|
||||
// This second pass saves any child concepts
|
||||
for (TermConceptParentChildLink next : links) {
|
||||
next.setCodeSystem(csv);
|
||||
int addedCount = saveOrUpdateConcept(next.getChild());
|
||||
addedCodeCounter.addAndGet(addedCount);
|
||||
myConceptParentChildLinkDao.save(next);
|
||||
}
|
||||
|
||||
return addedCodeCounter;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public AtomicInteger applyDeltaCodesystemsRemove(String theSystem, CodeSystem theValue) {
|
||||
TermCodeSystem cs = getCodeSystem(theSystem);
|
||||
if (cs == null) {
|
||||
throw new InvalidRequestException("Unknown code system: " + theSystem);
|
||||
}
|
||||
|
||||
AtomicInteger removeCounter = new AtomicInteger(0);
|
||||
|
||||
for (CodeSystem.ConceptDefinitionComponent next : theValue.getConcept()) {
|
||||
Optional<TermConcept> conceptOpt = findCode(theSystem, next.getCode());
|
||||
if (conceptOpt.isPresent()) {
|
||||
TermConcept concept = conceptOpt.get();
|
||||
deleteConceptChildrenAndConcept(concept, removeCounter);
|
||||
}
|
||||
}
|
||||
|
||||
return removeCounter;
|
||||
}
|
||||
|
||||
private void deleteConceptChildrenAndConcept(TermConcept theConcept, AtomicInteger theRemoveCounter) {
|
||||
for (TermConceptParentChildLink nextChildLink : theConcept.getChildren()) {
|
||||
deleteConceptChildrenAndConcept(nextChildLink.getChild(), theRemoveCounter);
|
||||
myConceptParentChildLinkDao.delete(nextChildLink);
|
||||
}
|
||||
|
||||
myConceptDesignationDao.deleteAll(theConcept.getDesignations());
|
||||
myConceptPropertyDao.deleteAll(theConcept.getProperties());
|
||||
myConceptDao.delete(theConcept);
|
||||
theRemoveCounter.incrementAndGet();
|
||||
}
|
||||
|
||||
protected IContextValidationSupport.LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
return txTemplate.execute(t -> {
|
||||
Optional<TermConcept> codeOpt = findCode(theSystem, theCode);
|
||||
if (codeOpt.isPresent()) {
|
||||
TermConcept code = codeOpt.get();
|
||||
|
||||
IContextValidationSupport.LookupCodeResult result = new IContextValidationSupport.LookupCodeResult();
|
||||
result.setCodeSystemDisplayName(code.getCodeSystemVersion().getCodeSystemDisplayName());
|
||||
result.setCodeSystemVersion(code.getCodeSystemVersion().getCodeSystemVersionId());
|
||||
result.setSearchedForSystem(theSystem);
|
||||
result.setSearchedForCode(theCode);
|
||||
result.setFound(true);
|
||||
result.setCodeDisplay(code.getDisplay());
|
||||
|
||||
for (TermConceptDesignation next : code.getDesignations()) {
|
||||
IContextValidationSupport.ConceptDesignation designation = new IContextValidationSupport.ConceptDesignation();
|
||||
designation.setLanguage(next.getLanguage());
|
||||
designation.setUseSystem(next.getUseSystem());
|
||||
designation.setUseCode(next.getUseCode());
|
||||
designation.setUseDisplay(next.getUseDisplay());
|
||||
designation.setValue(next.getValue());
|
||||
result.getDesignations().add(designation);
|
||||
}
|
||||
|
||||
for (TermConceptProperty next : code.getProperties()) {
|
||||
if (next.getType() == TermConceptPropertyTypeEnum.CODING) {
|
||||
IContextValidationSupport.CodingConceptProperty property = new IContextValidationSupport.CodingConceptProperty(next.getKey(), next.getCodeSystem(), next.getValue(), next.getDisplay());
|
||||
result.getProperties().add(property);
|
||||
} else if (next.getType() == TermConceptPropertyTypeEnum.STRING) {
|
||||
IContextValidationSupport.StringConceptProperty property = new IContextValidationSupport.StringConceptProperty(next.getKey(), next.getValue());
|
||||
result.getProperties().add(property);
|
||||
} else {
|
||||
throw new InternalErrorException("Unknown type: " + next.getType());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private @Nullable
|
||||
ConceptSubsumptionOutcome testForSubsumption(FullTextEntityManager theEntityManager, TermConcept theLeft, TermConcept theRight, ConceptSubsumptionOutcome theOutput) {
|
||||
QueryBuilder qb = theEntityManager.getSearchFactory().buildQueryBuilder().forEntity(TermConcept.class).get();
|
||||
|
@ -1608,7 +1878,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
predicates = new ArrayList<>();
|
||||
|
||||
coding = translationQuery.getCoding();
|
||||
String targetCode = null;
|
||||
String targetCode;
|
||||
String targetCodeSystem = null;
|
||||
if (coding.hasCode()) {
|
||||
predicates.add(criteriaBuilder.equal(targetJoin.get("myCode"), coding.getCode()));
|
||||
|
@ -1716,12 +1986,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private void verifyNoDuplicates(Collection<TermConcept> theConcepts, Set<String> theCodes) {
|
||||
for (TermConcept next : theConcepts) {
|
||||
if (!theCodes.add(next.getCode())) {
|
||||
throw new InvalidRequestException("Duplicate code " + next.getCode() + " found in codesystem after checking " + theCodes.size() + " codes");
|
||||
}
|
||||
verifyNoDuplicates(next.getChildren().stream().map(TermConceptParentChildLink::getChild).collect(Collectors.toList()), theCodes);
|
||||
private static void extractLinksFromConceptAndChildren(TermConcept theConcept, List<TermConceptParentChildLink> theLinks) {
|
||||
theLinks.addAll(theConcept.getParents());
|
||||
for (TermConceptParentChildLink child : theConcept.getChildren()) {
|
||||
extractLinksFromConceptAndChildren(child.getChild(), theLinks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1775,4 +2043,6 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
public static void setForceSaveDeferredAlwaysForUnitTest(boolean theForceSaveDeferredAlwaysForUnitTest) {
|
||||
ourForceSaveDeferredAlwaysForUnitTest = theForceSaveDeferredAlwaysForUnitTest;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -61,6 +64,8 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen
|
|||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myTerminologySvc;
|
||||
@Autowired
|
||||
private PlatformTransactionManager myTransactionManager;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -100,6 +105,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen
|
|||
} catch (FHIRException e) {
|
||||
throw new InternalErrorException(e);
|
||||
}
|
||||
validateCodeSystemForStorage(theCodeSystemResource);
|
||||
if (isBlank(resourceToStore.getIdElement().getIdPart())) {
|
||||
String matchUrl = "CodeSystem?url=" + UrlUtil.escapeUrlParam(theCodeSystemResource.getUrl());
|
||||
return myCodeSystemResourceDao.update(resourceToStore, matchUrl).getId();
|
||||
|
@ -217,14 +223,14 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen
|
|||
return null;
|
||||
}
|
||||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public ValueSet fetchValueSet(FhirContext theContext, String theSystem) {
|
||||
public IBaseResource fetchResource(FhirContext theContext, Class theClass, String theUri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
public ValueSet fetchValueSet(FhirContext theContext, String theSystem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -293,20 +299,30 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen
|
|||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
Optional<TermConcept> codeOpt = myTerminologySvc.findCode(theCodeSystem, theCode);
|
||||
if (codeOpt.isPresent()) {
|
||||
ConceptDefinitionComponent def = new ConceptDefinitionComponent();
|
||||
TermConcept code = codeOpt.get();
|
||||
def.setCode(code.getCode());
|
||||
def.setDisplay(code.getDisplay());
|
||||
CodeValidationResult retVal = new CodeValidationResult(def);
|
||||
retVal.setProperties(code.toValidationProperties());
|
||||
retVal.setCodeSystemName(code.getCodeSystemVersion().getCodeSystem().getName());
|
||||
return retVal;
|
||||
}
|
||||
public IValidationSupport.CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
return txTemplate.execute(t->{
|
||||
Optional<TermConcept> codeOpt = myTerminologySvc.findCode(theCodeSystem, theCode);
|
||||
if (codeOpt.isPresent()) {
|
||||
ConceptDefinitionComponent def = new ConceptDefinitionComponent();
|
||||
TermConcept code = codeOpt.get();
|
||||
def.setCode(code.getCode());
|
||||
def.setDisplay(code.getDisplay());
|
||||
IValidationSupport.CodeValidationResult retVal = new IValidationSupport.CodeValidationResult(def);
|
||||
retVal.setProperties(code.toValidationProperties());
|
||||
retVal.setCodeSystemName(code.getCodeSystemVersion().getCodeSystem().getName());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
return new CodeValidationResult(IssueSeverity.ERROR, "Unknown code {" + theCodeSystem + "}" + theCode);
|
||||
return new IValidationSupport.CodeValidationResult(IssueSeverity.ERROR, "Unknown code {" + theCodeSystem + "}" + theCode);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return super.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
|||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
||||
|
@ -18,6 +19,9 @@ import org.hl7.fhir.r4.terminologies.ValueSetExpander;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -48,6 +52,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
*/
|
||||
|
||||
public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements IHapiTerminologySvcR4 {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("myConceptMapDaoR4")
|
||||
private IFhirResourceDao<ConceptMap> myConceptMapResourceDao;
|
||||
|
@ -60,7 +65,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements
|
|||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myTerminologySvc;
|
||||
private PlatformTransactionManager myTransactionManager;
|
||||
|
||||
private void addAllChildren(String theSystemString, ConceptDefinitionComponent theCode, List<VersionIndependentConcept> theListToPopulate) {
|
||||
if (isNotBlank(theCode.getCode())) {
|
||||
|
@ -87,6 +92,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements
|
|||
|
||||
@Override
|
||||
protected IIdType createOrUpdateCodeSystem(org.hl7.fhir.r4.model.CodeSystem theCodeSystemResource) {
|
||||
validateCodeSystemForStorage(theCodeSystemResource);
|
||||
if (isBlank(theCodeSystemResource.getIdElement().getIdPart())) {
|
||||
String matchUrl = "CodeSystem?url=" + UrlUtil.escapeUrlParam(theCodeSystemResource.getUrl());
|
||||
return myCodeSystemResourceDao.update(theCodeSystemResource, matchUrl).getId();
|
||||
|
@ -227,7 +233,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements
|
|||
|
||||
@Override
|
||||
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) {
|
||||
return myTerminologySvc.supportsSystem(theSystem);
|
||||
return supportsSystem(theSystem);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -237,19 +243,28 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements
|
|||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
Optional<TermConcept> codeOpt = myTerminologySvc.findCode(theCodeSystem, theCode);
|
||||
if (codeOpt.isPresent()) {
|
||||
TermConcept code = codeOpt.get();
|
||||
ConceptDefinitionComponent def = new ConceptDefinitionComponent();
|
||||
def.setCode(code.getCode());
|
||||
def.setDisplay(code.getDisplay());
|
||||
CodeValidationResult retVal = new CodeValidationResult(def);
|
||||
retVal.setProperties(code.toValidationProperties());
|
||||
return retVal;
|
||||
}
|
||||
public IValidationSupport.CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
return txTemplate.execute(t-> {
|
||||
Optional<TermConcept> codeOpt = findCode(theCodeSystem, theCode);
|
||||
if (codeOpt.isPresent()) {
|
||||
TermConcept code = codeOpt.get();
|
||||
ConceptDefinitionComponent def = new ConceptDefinitionComponent();
|
||||
def.setCode(code.getCode());
|
||||
def.setDisplay(code.getDisplay());
|
||||
IValidationSupport.CodeValidationResult retVal = new IValidationSupport.CodeValidationResult(def);
|
||||
retVal.setProperties(code.toValidationProperties());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
return new CodeValidationResult(IssueSeverity.ERROR, "Unknown code {" + theCodeSystem + "}" + theCode);
|
||||
return new IValidationSupport.CodeValidationResult(IssueSeverity.ERROR, "Unknown code {" + theCodeSystem + "}" + theCode);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return super.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,12 +8,15 @@ import org.hl7.fhir.instance.model.api.IBaseCoding;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.ConceptMap;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -76,13 +79,15 @@ public interface IHapiTerminologySvc {
|
|||
*/
|
||||
void setProcessDeferred(boolean theProcessDeferred);
|
||||
|
||||
void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, TermCodeSystemVersion theCodeSytemVersion);
|
||||
void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, TermCodeSystemVersion theCodeSystemVersion);
|
||||
|
||||
/**
|
||||
* @return Returns the ID of the created/updated code system
|
||||
*/
|
||||
IIdType storeNewCodeSystemVersion(org.hl7.fhir.r4.model.CodeSystem theCodeSystemResource, TermCodeSystemVersion theCodeSystemVersion, RequestDetails theRequestDetails, List<org.hl7.fhir.r4.model.ValueSet> theValueSets, List<org.hl7.fhir.r4.model.ConceptMap> theConceptMaps);
|
||||
|
||||
void storeNewCodeSystemVersionIfNeeded(CodeSystem theCodeSystem, ResourceTable theResourceEntity);
|
||||
|
||||
void deleteConceptMapAndChildren(ResourceTable theResourceTable);
|
||||
|
||||
void deleteValueSetAndChildren(ResourceTable theResourceTable);
|
||||
|
@ -98,4 +103,8 @@ public interface IHapiTerminologySvc {
|
|||
List<TermConceptMapGroupElement> translateWithReverse(TranslationRequest theTranslationRequest);
|
||||
|
||||
IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB);
|
||||
|
||||
AtomicInteger applyDeltaCodesystemsAdd(String theSystem, @Nullable String theParent, CodeSystem theValue);
|
||||
|
||||
AtomicInteger applyDeltaCodesystemsRemove(String theSystem, CodeSystem theDelta);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
|
@ -63,6 +63,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
codeSystem.setName("ACME Codes");
|
||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);
|
||||
|
@ -98,7 +99,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
|
||||
parentC.addChild(childCA, RelationshipTypeEnum.ISA);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
@ -129,7 +130,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
parentB.addChild(childI, RelationshipTypeEnum.ISA);
|
||||
}
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
@ -165,7 +166,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
|
||||
dogs.addChild(beagle, RelationshipTypeEnum.ISA);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM,"SYSTEM NAME" , cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM,"SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
@ -489,14 +490,18 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
|
||||
createExternalCsAndLocalVs();
|
||||
|
||||
// We're making sure that a reindex doesn't wipe out all of the
|
||||
// stored codes in the terminology service
|
||||
myResourceReindexingSvc.markAllResourcesForReindexing();
|
||||
myResourceReindexingSvc.forceReindexingPass();
|
||||
myResourceReindexingSvc.forceReindexingPass();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
|
||||
IContextValidationSupport.LookupCodeResult lookupResults = myCodeSystemDao.lookupCode(new StringType("childAA"), new StringType(URL_MY_CODE_SYSTEM),null, mySrd);
|
||||
assertEquals(true, lookupResults.isFound());
|
||||
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
myHapiTerminologySvc.saveDeferred();
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||
|
@ -680,11 +685,11 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
cs.setResource(table);
|
||||
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||
cs.getConcepts().add(parentA);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", "Snomed CT", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs);
|
||||
|
||||
StringType code = new StringType("ParentA");
|
||||
StringType system = new StringType("http://snomed.info/sct");
|
||||
LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||
IContextValidationSupport.LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||
assertEquals(true, outcome.isFound());
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import ca.uhn.fhir.jpa.searchparam.registry.BaseSearchParamRegistry;
|
|||
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
|
||||
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcR4;
|
||||
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
||||
import ca.uhn.fhir.jpa.util.ResourceProviderFactory;
|
||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
|
||||
|
@ -127,6 +128,8 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
|||
@Autowired
|
||||
protected ITermCodeSystemDao myTermCodeSystemDao;
|
||||
@Autowired
|
||||
protected ITermConceptParentChildLinkDao myTermConceptParentChildLinkDao;
|
||||
@Autowired
|
||||
protected ITermCodeSystemVersionDao myTermCodeSystemVersionDao;
|
||||
@Autowired
|
||||
@Qualifier("myCompartmentDefinitionDaoR4")
|
||||
|
@ -288,7 +291,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
|||
@Qualifier("myTaskDaoR4")
|
||||
protected IFhirResourceDao<Task> myTaskDao;
|
||||
@Autowired
|
||||
protected IHapiTerminologySvc myTermSvc;
|
||||
protected IHapiTerminologySvcR4 myTermSvc;
|
||||
@Autowired
|
||||
protected PlatformTransactionManager myTransactionMgr;
|
||||
@Autowired
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
|
@ -96,7 +96,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
|||
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
|
||||
parentC.addChild(childCA, RelationshipTypeEnum.ISA);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
|||
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
|
||||
dogs.addChild(beagle, RelationshipTypeEnum.ISA);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
|||
parentB.addChild(childI, RelationshipTypeEnum.ISA);
|
||||
}
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
@ -476,7 +476,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
|||
concept = new TermConcept(cs, "LA9999-7");
|
||||
cs.getConcepts().add(concept);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
|
||||
ValueSet valueSet = new ValueSet();
|
||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||
|
@ -803,11 +803,11 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
|||
cs.setResource(table);
|
||||
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||
cs.getConcepts().add(parentA);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", "Snomed CT", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs);
|
||||
|
||||
StringType code = new StringType("ParentA");
|
||||
StringType system = new StringType("http://snomed.info/sct");
|
||||
LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||
IContextValidationSupport.LookupCodeResult outcome = myCodeSystemDao.lookupCode(code, system, null, mySrd);
|
||||
assertEquals(true, outcome.isFound());
|
||||
}
|
||||
|
||||
|
|
|
@ -55,10 +55,12 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue().booleanValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("SYSTEM VERSION"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
|
||||
// With HTTP GET
|
||||
respParam = ourClient
|
||||
|
@ -75,10 +77,12 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue().booleanValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("SYSTEM VERSION", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
|
||||
}
|
||||
|
||||
|
@ -96,11 +100,13 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue().booleanValue());
|
||||
assertEquals(("v2 Identifier Type"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("2.8.2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -123,7 +129,6 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
|
||||
@Test
|
||||
public void testLookupOperationByCodeAndSystemUserDefinedCode() {
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
|
@ -131,13 +136,12 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||
.andParameter("system", new UriType("http://acme.org"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("ACME Codes", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
|
@ -164,20 +168,18 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
|
||||
@Test
|
||||
public void testLookupOperationByCoding() {
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named("lookup")
|
||||
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
|
@ -239,9 +241,7 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
}
|
||||
|
||||
@Test
|
||||
// @Ignore
|
||||
public void testLookupOperationForBuiltInCode() {
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
|
@ -249,17 +249,18 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
|
|||
.withParameter(Parameters.class, "code", new CodeType("M"))
|
||||
.andParameter("system", new UriType("http://hl7.org/fhir/v3/MaritalStatus"))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals("Unknown", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Married", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).booleanValue());
|
||||
assertEquals("v3 Code System MaritalStatus", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("2016-11-11", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Married", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).booleanValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -126,7 +126,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
code.addPropertyString("HELLO", "12345-2");
|
||||
cs.getConcepts().add(code);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
|
||||
|
||||
@Test
|
||||
public void testExpandById() throws IOException {
|
||||
public void testExpandById() {
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
|
@ -263,7 +263,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandByIdWithFilter() throws IOException {
|
||||
public void testExpandByIdWithFilter() {
|
||||
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
|
@ -350,7 +350,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandInlineVsAgainstBuiltInCs() throws IOException {
|
||||
public void testExpandInlineVsAgainstBuiltInCs() {
|
||||
createLocalVsPointingAtBuiltInCodeSystem();
|
||||
assertNotNull(myLocalValueSetId);
|
||||
|
||||
|
@ -371,7 +371,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandInlineVsAgainstExternalCs() throws IOException {
|
||||
public void testExpandInlineVsAgainstExternalCs() {
|
||||
createExternalCsAndLocalVs();
|
||||
assertNotNull(myLocalVs);
|
||||
myLocalVs.setId("");
|
||||
|
@ -446,7 +446,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandLocalVsAgainstBuiltInCs() throws IOException {
|
||||
public void testExpandLocalVsAgainstBuiltInCs() {
|
||||
createLocalVsPointingAtBuiltInCodeSystem();
|
||||
assertNotNull(myLocalValueSetId);
|
||||
|
||||
|
@ -467,7 +467,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandLocalVsAgainstExternalCs() throws IOException {
|
||||
public void testExpandLocalVsAgainstExternalCs() {
|
||||
createExternalCsAndLocalVs();
|
||||
assertNotNull(myLocalValueSetId);
|
||||
|
||||
|
@ -491,7 +491,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandLocalVsCanonicalAgainstExternalCs() throws IOException {
|
||||
public void testExpandLocalVsCanonicalAgainstExternalCs() {
|
||||
createExternalCsAndLocalVs();
|
||||
assertNotNull(myLocalValueSetId);
|
||||
|
||||
|
@ -515,7 +515,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExpandLocalVsWithUnknownCode() throws IOException {
|
||||
public void testExpandLocalVsWithUnknownCode() {
|
||||
createExternalCsAndLocalVsWithUnknownCode();
|
||||
assertNotNull(myLocalValueSetId);
|
||||
|
||||
|
@ -636,7 +636,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue().booleanValue());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), Matchers.containsStringIgnoringCase("succeeded"));
|
||||
|
@ -664,7 +664,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue().booleanValue());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), Matchers.containsStringIgnoringCase("succeeded"));
|
||||
|
@ -682,6 +682,8 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
codeSystem.setName("ACME Codes");
|
||||
codeSystem.setVersion("1.2.3.4");
|
||||
IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = theResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);
|
||||
|
@ -707,7 +709,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
|||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||
cs.getConcepts().add(parentB);
|
||||
|
||||
theTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
theTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI + "FOO"))
|
||||
.andParameter("package", new Attachment().setUrl("foo").setData(packageBytes))
|
||||
|
@ -102,7 +102,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.LOINC_URI))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
|
@ -111,7 +111,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(((IntegerType) respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
|
||||
|
||||
/*
|
||||
* Try uploading a second time
|
||||
|
@ -119,7 +119,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
|
||||
respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.LOINC_URI))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
|
@ -136,7 +136,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.andParameter("package", new Attachment().setData(packageBytes))
|
||||
|
@ -154,7 +154,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "package", new Attachment().setUrl("foo").setData(packageBytes))
|
||||
.execute();
|
||||
|
@ -170,7 +170,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.execute();
|
||||
|
@ -186,7 +186,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
|
@ -195,7 +195,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(((IntegerType) respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -212,7 +212,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.andParameter("localfile", new StringType(tempFile.getAbsolutePath()))
|
||||
|
@ -221,7 +221,7 @@ public class TerminologyUploaderProviderDstu3Test extends BaseResourceProviderDs
|
|||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(((IntegerType) respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
|
|
@ -2,6 +2,8 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
|
||||
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
@ -14,8 +16,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test {
|
||||
|
||||
|
@ -45,6 +47,93 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyDeltaAdd() {
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta.setUrl("http://example.com/labCodes");
|
||||
delta.setName("Example Hospital Lab Codes");
|
||||
delta.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
delta.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
delta.setUrl("http://foo");
|
||||
CodeSystem.ConceptDefinitionComponent chem = delta
|
||||
.addConcept()
|
||||
.setCode("CHEM")
|
||||
.setDisplay("Chemistry Tests");
|
||||
chem
|
||||
.addConcept()
|
||||
.setCode("HB")
|
||||
.setDisplay("Hemoglobin");
|
||||
chem
|
||||
.addConcept()
|
||||
.setCode("NEUT")
|
||||
.setDisplay("Neutrophil");
|
||||
CodeSystem.ConceptDefinitionComponent micro = delta
|
||||
.addConcept()
|
||||
.setCode("MICRO")
|
||||
.setDisplay("Microbiology Tests");
|
||||
micro
|
||||
.addConcept()
|
||||
.setCode("C&S")
|
||||
.setDisplay("Culture & Sensitivity");
|
||||
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor(true);
|
||||
ourClient.registerInterceptor(interceptor);
|
||||
Parameters outcome = ourClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_ADD)
|
||||
.withParameter(Parameters.class, TerminologyUploaderProvider.VALUE, delta)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
ourClient.unregisterInterceptor(interceptor);
|
||||
|
||||
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("\"valueInteger\": 5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyDeltaRemove() {
|
||||
// Create not-present
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://foo");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
ourClient.create().resource(cs).execute();
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta.setUrl("http://foo");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeA")
|
||||
.setDisplay("displayA");
|
||||
|
||||
// Add
|
||||
ourClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_ADD)
|
||||
.withParameter(Parameters.class, TerminologyUploaderProvider.VALUE, delta)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
|
||||
// Remove
|
||||
LoggingInterceptor interceptor = new LoggingInterceptor(true);
|
||||
ourClient.registerInterceptor(interceptor);
|
||||
Parameters outcome = ourClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named(JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_REMOVE)
|
||||
.withParameter(Parameters.class, TerminologyUploaderProvider.VALUE, delta)
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
ourClient.unregisterInterceptor(interceptor);
|
||||
|
||||
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome);
|
||||
ourLog.info(encoded);
|
||||
assertThat(encoded, containsString("\"valueInteger\": 1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupOnExternalCode() {
|
||||
ResourceProviderR4ValueSetTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermSvc, mySrd);
|
||||
|
@ -61,11 +150,13 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("SYSTEM VERSION", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
|
||||
// With HTTP GET
|
||||
respParam = ourClient
|
||||
|
@ -81,11 +172,13 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("SYSTEM VERSION"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Parent A", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
|
||||
}
|
||||
|
||||
|
@ -103,11 +196,13 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -140,7 +235,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
|
@ -176,7 +271,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals(("Unknown"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
|
@ -245,11 +340,13 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals("Unknown", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(1).getName());
|
||||
assertEquals("Married", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(2).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).booleanValue());
|
||||
assertEquals("v3.MaritalStatus", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("2018-08-12", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Married", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).booleanValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.apache.commons.io.IOUtils;
|
|||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -514,7 +513,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
ourLog.info(resp);
|
||||
|
||||
assertEquals("result", respParam.getParameter().get(0).getName());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue().booleanValue());
|
||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
|
||||
assertEquals("message", respParam.getParameter().get(1).getName());
|
||||
assertThat(((StringType) respParam.getParameter().get(1).getValue()).getValue(), containsStringIgnoringCase("succeeded"));
|
||||
|
@ -603,7 +602,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
|||
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
|
||||
cs.getConcepts().add(parentB);
|
||||
|
||||
theTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||
theTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
return codeSystem;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
|
|||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI + "FOO"))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
|
@ -65,35 +65,31 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
|
|||
public void testUploadLoinc() throws Exception {
|
||||
byte[] packageBytes = TerminologyUploaderProviderDstu3Test.createLoincZip();
|
||||
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.LOINC_URI))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(((IntegerType) respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((Reference) respParam.getParameter().get(1).getValue()).getReference(), matchesPattern("CodeSystem\\/[a-zA-Z0-9]+"));
|
||||
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((Reference) respParam.getParameter().get(2).getValue()).getReference(), matchesPattern("CodeSystem\\/[a-zA-Z0-9]+"));
|
||||
|
||||
/*
|
||||
* Try uploading a second time
|
||||
*/
|
||||
|
||||
//@formatter:off
|
||||
respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.LOINC_URI))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
@ -106,7 +102,7 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
|
|||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.execute();
|
||||
|
@ -114,18 +110,16 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
|
|||
} catch (InvalidRequestException e) {
|
||||
assertEquals("HTTP 400 Bad Request: No 'localfile' or 'package' parameter, or package had no data", e.getMessage());
|
||||
}
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUploadMissingUrl() throws Exception {
|
||||
byte[] packageBytes = createSctZip();
|
||||
|
||||
//@formatter:off
|
||||
try {
|
||||
ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
.execute();
|
||||
|
@ -133,27 +127,25 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
|
|||
} catch (InvalidRequestException e) {
|
||||
assertEquals("HTTP 400 Bad Request: Unknown URL: ", e.getMessage());
|
||||
}
|
||||
//@formatter:on
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUploadSct() throws Exception {
|
||||
byte[] packageBytes = createSctZip();
|
||||
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.andParameter("package", new Attachment().setUrl("file.zip").setData(packageBytes))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(((IntegerType) respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -166,20 +158,18 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
|
|||
fos.write(packageBytes);
|
||||
fos.close();
|
||||
|
||||
//@formatter:off
|
||||
Parameters respParam = ourClient
|
||||
.operation()
|
||||
.onServer()
|
||||
.onType(CodeSystem.class)
|
||||
.named("upload-external-code-system")
|
||||
.withParameter(Parameters.class, "url", new UriType(IHapiTerminologyLoaderSvc.SCT_URI))
|
||||
.andParameter("localfile", new StringType(tempFile.getAbsolutePath()))
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertThat(((IntegerType) respParam.getParameter().get(0).getValue()).getValue(), greaterThan(1));
|
||||
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
|
|
@ -52,6 +52,7 @@ public class WebsocketWithSubscriptionIdDstu3Test extends BaseResourceProviderDs
|
|||
@Autowired
|
||||
private SubscriptionTestUtil mySubscriptionTestUtil;
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
super.after();
|
||||
|
@ -65,6 +66,7 @@ public class WebsocketWithSubscriptionIdDstu3Test extends BaseResourceProviderDs
|
|||
myWebSocketClient.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
|
@ -117,7 +119,7 @@ public class WebsocketWithSubscriptionIdDstu3Test extends BaseResourceProviderDs
|
|||
}
|
||||
|
||||
@Test
|
||||
public void createObservation() throws Exception {
|
||||
public void createObservation() {
|
||||
Observation observation = new Observation();
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
observation.setCode(codeableConcept);
|
||||
|
@ -141,7 +143,7 @@ public class WebsocketWithSubscriptionIdDstu3Test extends BaseResourceProviderDs
|
|||
}
|
||||
|
||||
@Test
|
||||
public void createObservationThatDoesNotMatch() throws Exception {
|
||||
public void createObservationThatDoesNotMatch() {
|
||||
Observation observation = new Observation();
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
observation.setCode(codeableConcept);
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.ConceptMap;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TerminologyLoaderSvcImgthlaTest {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
@ -134,9 +134,8 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
|||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||
|
||||
IFhirResourceDaoCodeSystem.LookupCodeResult result = myCodeSystemDao.lookupCode(new StringType("10013-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, mySrd);
|
||||
org.hl7.fhir.r4.model.Parameters parametersR4 = result.toParameters(null);
|
||||
Parameters parameters = VersionConvertor_30_40.convertParameters(parametersR4);
|
||||
IContextValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(new StringType("10013-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, mySrd);
|
||||
Parameters parameters = (Parameters) result.toParameters(myFhirCtx, null);
|
||||
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parameters));
|
||||
|
||||
|
@ -165,9 +164,8 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
|||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||
|
||||
IFhirResourceDaoCodeSystem.LookupCodeResult result = myCodeSystemDao.lookupCode(new StringType("17788-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, mySrd);
|
||||
org.hl7.fhir.r4.model.Parameters parametersR4 = result.toParameters(null);
|
||||
Parameters parameters = VersionConvertor_30_40.convertParameters(parametersR4);
|
||||
IContextValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(new StringType("17788-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, mySrd);
|
||||
Parameters parameters = (Parameters) result.toParameters(myFhirCtx, null);
|
||||
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parameters));
|
||||
|
||||
|
@ -184,10 +182,9 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
|||
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||
|
||||
IFhirResourceDaoCodeSystem.LookupCodeResult result = myCodeSystemDao.lookupCode(new StringType("10013-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, mySrd);
|
||||
IContextValidationSupport.LookupCodeResult result = myCodeSystemDao.lookupCode(new StringType("10013-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, mySrd);
|
||||
List<? extends IPrimitiveType<String>> properties = Lists.newArrayList(new CodeType("SCALE_TYP"));
|
||||
org.hl7.fhir.r4.model.Parameters parametersR4 = result.toParameters(properties);
|
||||
Parameters parameters = VersionConvertor_30_40.convertParameters(parametersR4);
|
||||
Parameters parameters = (Parameters) result.toParameters(myFhirCtx, properties);
|
||||
|
||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parameters));
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(CS_URL);
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
codeSystem.setName("SYSTEM NAME");
|
||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalArgumentException::new);
|
||||
|
@ -95,7 +96,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
TermConcept parentB = new TermConcept(cs, "ParentB");
|
||||
cs.getConcepts().add(parentB);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -114,7 +115,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
TermConcept parentA = new TermConcept(cs, "CS2");
|
||||
cs.getConcepts().add(parentA);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL_2, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL_2, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -146,7 +147,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
code.addPropertyString("HELLO", "12345-2");
|
||||
cs.getConcepts().add(code);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -162,7 +163,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||
cs.setResource(table);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
|
||||
// Update
|
||||
cs = new TermCodeSystemVersion();
|
||||
|
@ -171,17 +172,14 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
id = myCodeSystemDao.update(codeSystem, null, true, true, mySrd).getId().toUnqualified();
|
||||
table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalArgumentException::new);
|
||||
cs.setResource(table);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
|
||||
// Try to update to a different resource
|
||||
codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(CS_URL);
|
||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||
id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalArgumentException::new);
|
||||
cs.setResource(table);
|
||||
try {
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/"));
|
||||
|
@ -585,7 +583,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
child.addChild(parent, RelationshipTypeEnum.ISA);
|
||||
|
||||
try {
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://foo", "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), "http://foo", "SYSTEM NAME", "SYSTEM VERSION" , cs);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("CodeSystem contains circular reference around code parent", e.getMessage());
|
||||
|
@ -708,7 +706,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
|
|||
runInTransaction(()->{
|
||||
ResourceTable resTable = myEntityManager.find(ResourceTable.class, csId.getIdPartAsLong());
|
||||
version.setResource(resTable);
|
||||
myTermSvc.storeNewCodeSystemVersion(csId.getIdPartAsLong(), cs.getUrl(), "My System", version);
|
||||
myTermSvc.storeNewCodeSystemVersion(csId.getIdPartAsLong(), cs.getUrl(), "My System", "SYSTEM VERSION" , version);
|
||||
});
|
||||
|
||||
org.hl7.fhir.dstu3.model.ValueSet vs = new org.hl7.fhir.dstu3.model.ValueSet();
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
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 ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
|
||||
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mock;
|
||||
|
@ -18,9 +26,12 @@ import org.springframework.transaction.TransactionStatus;
|
|||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
@ -31,13 +42,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
private static final Logger ourLog = LoggerFactory.getLogger(TerminologySvcImplR4Test.class);
|
||||
@Rule
|
||||
public final ExpectedException expectedException = ExpectedException.none();
|
||||
@Mock
|
||||
IValueSetCodeAccumulator myValueSetCodeAccumulator;
|
||||
private IIdType myConceptMapId;
|
||||
private IIdType myExtensionalCsId;
|
||||
private IIdType myExtensionalVsId;
|
||||
|
||||
@Mock
|
||||
IValueSetCodeAccumulator myValueSetCodeAccumulator;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myDaoConfig.setAllowExternalReferences(true);
|
||||
|
@ -53,6 +63,8 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(CS_URL);
|
||||
codeSystem.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
codeSystem.setName("SYSTEM NAME");
|
||||
codeSystem.setVersion("SYSTEM VERSION");
|
||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||
|
||||
ResourceTable table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalArgumentException::new);
|
||||
|
@ -95,11 +107,11 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
TermConcept parentB = new TermConcept(cs, "ParentB");
|
||||
cs.getConcepts().add(parentB);
|
||||
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
|
||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
private void createAndPersistConceptMap() {
|
||||
ConceptMap conceptMap = createConceptMap();
|
||||
persistConceptMap(conceptMap);
|
||||
|
@ -157,6 +169,304 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyCodeSystemDeltaAdd() {
|
||||
|
||||
// Create not-present
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://foo");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeA")
|
||||
.setDisplay("displayA");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeB")
|
||||
.setDisplay("displayB");
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
|
||||
assertEquals(true, myTermSvc.findCode("http://foo", "codeA").isPresent());
|
||||
assertEquals(false, myTermSvc.findCode("http://foo", "codeZZZ").isPresent());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This would be a good check, but there is no easy eay to do it...
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testApplyCodeSystemDeltaAddNotPermittedForNonExternalCodeSystem() {
|
||||
|
||||
// Create not-present
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://foo");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeA")
|
||||
.setDisplay("displayA");
|
||||
try {
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyCodeSystemDeltaAddWithoutPreExistingCodeSystem() {
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
delta.setUrl("http://foo");
|
||||
delta.setName("Acme Lab Codes");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("CBC")
|
||||
.setDisplay("Complete Blood Count");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("URNL")
|
||||
.setDisplay("Routine Urinalysis");
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronous(true);
|
||||
params.add(CodeSystem.SP_URL, new UriParam("http://foo"));
|
||||
IBundleProvider searchResult = myCodeSystemDao.search(params, mySrd);
|
||||
assertEquals(1, searchResult.size().intValue());
|
||||
CodeSystem outcome = (CodeSystem) searchResult.getResources(0,1).get(0);
|
||||
|
||||
assertEquals("http://foo", outcome.getUrl());
|
||||
assertEquals("Acme Lab Codes", outcome.getName());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testApplyCodeSystemDeltaAddDuplicatesIgnored() {
|
||||
|
||||
// Add codes
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
delta.setUrl("http://foo");
|
||||
delta.setName("Acme Lab Codes");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codea")
|
||||
.setDisplay("CODEA0");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeb")
|
||||
.setDisplay("CODEB0");
|
||||
AtomicInteger outcome = myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
assertEquals(2, outcome.get());
|
||||
|
||||
// Add codes again with different display
|
||||
delta = new CodeSystem();
|
||||
delta.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
delta.setUrl("http://foo");
|
||||
delta.setName("Acme Lab Codes");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codea")
|
||||
.setDisplay("CODEA1");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeb")
|
||||
.setDisplay("CODEB1");
|
||||
outcome = myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
assertEquals(2, outcome.get());
|
||||
|
||||
// Add codes again with no changes
|
||||
outcome = myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
assertEquals(0, outcome.get());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testApplyCodeSystemDeltaAddAsChild() {
|
||||
|
||||
// Create not-present
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://foo");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeA")
|
||||
.setDisplay("displayA");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeB")
|
||||
.setDisplay("displayB");
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
|
||||
delta = new CodeSystem();
|
||||
CodeSystem.ConceptDefinitionComponent codeAA = delta
|
||||
.addConcept()
|
||||
.setCode("codeAA")
|
||||
.setDisplay("displayAA");
|
||||
codeAA
|
||||
.addConcept()
|
||||
.setCode("codeAAA")
|
||||
.setDisplay("displayAAA");
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", "codeA", delta);
|
||||
|
||||
assertEquals(true, myTermSvc.findCode("http://foo", "codeAA").isPresent());
|
||||
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY, myTermSvc.subsumes(toString("codeA"), toString("codeAA"), toString("http://foo"), null, null).getOutcome());
|
||||
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY, myTermSvc.subsumes(toString("codeA"), toString("codeAAA"), toString("http://foo"), null, null).getOutcome());
|
||||
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY, myTermSvc.subsumes(toString("codeAA"), toString("codeAAA"), toString("http://foo"), null, null).getOutcome());
|
||||
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED, myTermSvc.subsumes(toString("codeB"), toString("codeAA"), toString("http://foo"), null, null).getOutcome());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<TermConceptParentChildLink> allChildren = myTermConceptParentChildLinkDao.findAll();
|
||||
assertEquals(2, allChildren.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyCodeSystemDeltaAddWithPropertiesAndDesignations() {
|
||||
|
||||
// Create not-present
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setName("Description of my life");
|
||||
cs.setUrl("http://foo");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
cs.setVersion("1.2.3");
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
CodeSystem.ConceptDefinitionComponent concept = delta
|
||||
.addConcept()
|
||||
.setCode("lunch")
|
||||
.setDisplay("I'm having dog food");
|
||||
concept
|
||||
.addDesignation()
|
||||
.setLanguage("fr")
|
||||
.setUse(new Coding("http://sys", "code", "display"))
|
||||
.setValue("Je mange une pomme");
|
||||
concept
|
||||
.addDesignation()
|
||||
.setLanguage("es")
|
||||
.setUse(new Coding("http://sys", "code", "display"))
|
||||
.setValue("Como una pera");
|
||||
concept.addProperty()
|
||||
.setCode("flavour")
|
||||
.setValue(new StringType("Hints of lime"));
|
||||
concept.addProperty()
|
||||
.setCode("useless_sct_code")
|
||||
.setValue(new Coding("http://snomed.info", "1234567", "Choked on large meal (finding)"));
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
|
||||
IContextValidationSupport.LookupCodeResult result = myTermSvc.lookupCode(myFhirCtx, "http://foo", "lunch");
|
||||
assertEquals(true, result.isFound());
|
||||
assertEquals("lunch", result.getSearchedForCode());
|
||||
assertEquals("http://foo", result.getSearchedForSystem());
|
||||
|
||||
Parameters output = (Parameters) result.toParameters(myFhirCtx, null);
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
|
||||
assertEquals("Description of my life", ((StringType) output.getParameter("name")).getValue());
|
||||
assertEquals("1.2.3", ((StringType) output.getParameter("version")).getValue());
|
||||
assertEquals(false, output.getParameterBool("abstract"));
|
||||
|
||||
List<Parameters.ParametersParameterComponent> designations = output.getParameter().stream().filter(t -> t.getName().equals("designation")).collect(Collectors.toList());
|
||||
assertEquals("language", designations.get(0).getPart().get(0).getName());
|
||||
assertEquals("fr", ((CodeType) designations.get(0).getPart().get(0).getValue()).getValueAsString());
|
||||
assertEquals("use", designations.get(0).getPart().get(1).getName());
|
||||
assertEquals("http://sys", ((Coding) designations.get(0).getPart().get(1).getValue()).getSystem());
|
||||
assertEquals("code", ((Coding) designations.get(0).getPart().get(1).getValue()).getCode());
|
||||
assertEquals("display", ((Coding) designations.get(0).getPart().get(1).getValue()).getDisplay());
|
||||
assertEquals("value", designations.get(0).getPart().get(2).getName());
|
||||
assertEquals("Je mange une pomme", ((StringType) designations.get(0).getPart().get(2).getValue()).getValueAsString());
|
||||
|
||||
List<Parameters.ParametersParameterComponent> properties = output.getParameter().stream().filter(t -> t.getName().equals("property")).collect(Collectors.toList());
|
||||
assertEquals("code", properties.get(0).getPart().get(0).getName());
|
||||
assertEquals("flavour", ((CodeType) properties.get(0).getPart().get(0).getValue()).getValueAsString());
|
||||
assertEquals("value", properties.get(0).getPart().get(1).getName());
|
||||
assertEquals("Hints of lime", ((StringType) properties.get(0).getPart().get(1).getValue()).getValueAsString());
|
||||
|
||||
assertEquals("code", properties.get(1).getPart().get(0).getName());
|
||||
assertEquals("useless_sct_code", ((CodeType) properties.get(1).getPart().get(0).getValue()).getValueAsString());
|
||||
assertEquals("value", properties.get(1).getPart().get(1).getName());
|
||||
assertEquals("http://snomed.info", ((Coding) properties.get(1).getPart().get(1).getValue()).getSystem());
|
||||
assertEquals("1234567", ((Coding) properties.get(1).getPart().get(1).getValue()).getCode());
|
||||
assertEquals("Choked on large meal (finding)", ((Coding) properties.get(1).getPart().get(1).getValue()).getDisplay());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyCodeSystemDeltaRemove() {
|
||||
|
||||
// Create not-present
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://foo");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
CodeSystem delta = new CodeSystem();
|
||||
CodeSystem.ConceptDefinitionComponent codeA = delta
|
||||
.addConcept()
|
||||
.setCode("codeA")
|
||||
.setDisplay("displayA");
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeB")
|
||||
.setDisplay("displayB");
|
||||
CodeSystem.ConceptDefinitionComponent codeAA = codeA
|
||||
.addConcept()
|
||||
.setCode("codeAA")
|
||||
.setDisplay("displayAA");
|
||||
codeAA
|
||||
.addConcept()
|
||||
.setCode("codeAAA")
|
||||
.setDisplay("displayAAA");
|
||||
myTermSvc.applyDeltaCodesystemsAdd("http://foo", null, delta);
|
||||
|
||||
// Remove CodeB
|
||||
delta = new CodeSystem();
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeB")
|
||||
.setDisplay("displayB");
|
||||
myTermSvc.applyDeltaCodesystemsRemove("http://foo", delta);
|
||||
|
||||
assertEquals(false, myTermSvc.findCode("http://foo", "codeB").isPresent());
|
||||
assertEquals(true, myTermSvc.findCode("http://foo", "codeA").isPresent());
|
||||
assertEquals(true, myTermSvc.findCode("http://foo", "codeAA").isPresent());
|
||||
assertEquals(true, myTermSvc.findCode("http://foo", "codeAAA").isPresent());
|
||||
|
||||
// Remove CodeA
|
||||
delta = new CodeSystem();
|
||||
delta
|
||||
.addConcept()
|
||||
.setCode("codeA");
|
||||
myTermSvc.applyDeltaCodesystemsRemove("http://foo", delta);
|
||||
|
||||
assertEquals(false, myTermSvc.findCode("http://foo", "codeB").isPresent());
|
||||
assertEquals(false, myTermSvc.findCode("http://foo", "codeA").isPresent());
|
||||
assertEquals(false, myTermSvc.findCode("http://foo", "codeAA").isPresent());
|
||||
assertEquals(false, myTermSvc.findCode("http://foo", "codeAAA").isPresent());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
private StringType toString(String theString) {
|
||||
return new StringType(theString);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateConceptMapWithMissingSourceSystem() {
|
||||
ConceptMap conceptMap = new ConceptMap();
|
||||
|
@ -183,7 +493,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testCreateConceptMapWithVirtualSourceSystem() {
|
||||
ConceptMap conceptMap = createConceptMap();
|
||||
conceptMap.getGroup().forEach(t->t.setSource(null));
|
||||
conceptMap.getGroup().forEach(t -> t.setSource(null));
|
||||
conceptMap.setSource(new CanonicalType("http://hl7.org/fhir/uv/livd/StructureDefinition/loinc-livd"));
|
||||
|
||||
persistConceptMap(conceptMap);
|
||||
|
@ -283,6 +593,17 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
|
|||
verify(myValueSetCodeAccumulator, times(9)).includeCodeWithDesignations(anyString(), anyString(), nullable(String.class), anyCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCode() {
|
||||
createCodeSystem();
|
||||
|
||||
IValidationSupport.CodeValidationResult validation = myTermSvc.validateCode(myFhirCtx, CS_URL, "ParentWithNoChildrenA", null);
|
||||
assertEquals(true, validation.isOk());
|
||||
|
||||
validation = myTermSvc.validateCode(myFhirCtx, CS_URL, "ZZZZZZZ", null);
|
||||
assertEquals(false, validation.isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreTermCodeSystemAndChildren() throws Exception {
|
||||
loadAndPersistCodeSystemWithDesignations();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<CodeSystem xmlns="http://hl7.org/fhir">
|
||||
<url value="http://acme.org" />
|
||||
<name value="ACME Codes" />
|
||||
<concept>
|
||||
<code value="8450-9" />
|
||||
<display value="Systolic blood pressure--expiration" />
|
||||
|
@ -96,4 +97,4 @@
|
|||
<code value="8492-1" />
|
||||
<display value="Systolic blood pressure 8 hour minimum" />
|
||||
</concept>
|
||||
</CodeSystem>
|
||||
</CodeSystem>
|
||||
|
|
|
@ -23,6 +23,17 @@ package ca.uhn.fhir.jpa.model.util;
|
|||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
||||
public class JpaConstants {
|
||||
|
||||
/**
|
||||
* Operation name for the $apply-codesystem-delta-add operation
|
||||
*/
|
||||
public static final String OPERATION_APPLY_CODESYSTEM_DELTA_ADD = "$apply-codesystem-delta-add";
|
||||
|
||||
/**
|
||||
* Operation name for the $apply-codesystem-delta-remove operation
|
||||
*/
|
||||
public static final String OPERATION_APPLY_CODESYSTEM_DELTA_REMOVE = "$apply-codesystem-delta-remove";
|
||||
|
||||
/**
|
||||
* Operation name for the $expunge operation
|
||||
*/
|
||||
|
@ -158,6 +169,11 @@ public class JpaConstants {
|
|||
*/
|
||||
public static final String OPERATION_BINARY_ACCESS_WRITE = "$binary-access-write";
|
||||
|
||||
/**
|
||||
* Operation name for the "$upload-external-code-system" operation
|
||||
*/
|
||||
public static final String OPERATION_UPLOAD_EXTERNAL_CODE_SYSTEM = "$upload-external-code-system";
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This extension should be of type <code>string</code> and should be
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ca.uhn.fhirtest.interceptor;
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
|
||||
import ca.uhn.fhir.jpa.provider.BaseTerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
|
@ -35,7 +34,9 @@ public class PublicSecurityInterceptor extends AuthorizationInterceptor {
|
|||
if (isBlank(authHeader)) {
|
||||
return new RuleBuilder()
|
||||
.deny().operation().named(BaseJpaSystemProvider.MARK_ALL_RESOURCES_FOR_REINDEXING).onServer().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(BaseTerminologyUploaderProvider.UPLOAD_EXTERNAL_CODE_SYSTEM).onServer().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(JpaConstants.OPERATION_UPLOAD_EXTERNAL_CODE_SYSTEM).onServer().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_ADD).atAnyLevel().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(JpaConstants.OPERATION_APPLY_CODESYSTEM_DELTA_REMOVE).atAnyLevel().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(JpaConstants.OPERATION_EXPUNGE).onServer().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(JpaConstants.OPERATION_EXPUNGE).onAnyType().andAllowAllResponses().andThen()
|
||||
.deny().operation().named(JpaConstants.OPERATION_EXPUNGE).onAnyInstance().andAllowAllResponses().andThen()
|
||||
|
|
|
@ -445,15 +445,6 @@ public abstract class BaseMethodBinding<T> {
|
|||
return theReturnTypeFromMethod.equals(IBaseResource.class) || theReturnTypeFromMethod.equals(IResource.class) || theReturnTypeFromMethod.equals(IAnyResource.class);
|
||||
}
|
||||
|
||||
private static void populateException(BaseServerResponseException theEx, Reader theResponseReader) {
|
||||
try {
|
||||
String responseText = IOUtils.toString(theResponseReader);
|
||||
theEx.setResponseBody(responseText);
|
||||
} catch (IOException e) {
|
||||
ourLog.debug("Failed to read response", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toLogString(Class<?> theType) {
|
||||
if (theType == null) {
|
||||
return null;
|
||||
|
|
|
@ -68,14 +68,15 @@ public class MethodUtil {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<IParameter> getResourceParameters(final FhirContext theContext, Method theMethod, Object theProvider, RestOperationTypeEnum theRestfulOperationTypeEnum) {
|
||||
List<IParameter> parameters = new ArrayList<IParameter>();
|
||||
List<IParameter> parameters = new ArrayList<>();
|
||||
|
||||
Class<?>[] parameterTypes = theMethod.getParameterTypes();
|
||||
int paramIndex = 0;
|
||||
for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
|
||||
|
||||
IParameter param = null;
|
||||
Class<?> parameterType = parameterTypes[paramIndex];
|
||||
Class<?> declaredParameterType = parameterTypes[paramIndex];
|
||||
Class<?> parameterType = declaredParameterType;
|
||||
Class<? extends java.util.Collection<?>> outerCollectionType = null;
|
||||
Class<? extends java.util.Collection<?>> innerCollectionType = null;
|
||||
if (TagList.class.isAssignableFrom(parameterType)) {
|
||||
|
@ -85,11 +86,13 @@ public class MethodUtil {
|
|||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
|
||||
declaredParameterType = parameterType;
|
||||
}
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
outerCollectionType = innerCollectionType;
|
||||
innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
|
||||
parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
|
||||
declaredParameterType = parameterType;
|
||||
}
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
throw new ConfigurationException("Argument #" + paramIndex + " of Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName()
|
||||
|
@ -223,7 +226,7 @@ public class MethodUtil {
|
|||
param = new OperationParameter(theContext, op.name(), operationParam);
|
||||
if (isNotBlank(operationParam.typeName())) {
|
||||
Class<?> newParameterType = theContext.getElementDefinition(operationParam.typeName()).getImplementingClass();
|
||||
if (!parameterType.isAssignableFrom(newParameterType)) {
|
||||
if (!declaredParameterType.isAssignableFrom(newParameterType)) {
|
||||
throw new ConfigurationException("Non assignable parameter typeName=\"" + operationParam.typeName() + "\" specified on method " + theMethod);
|
||||
}
|
||||
parameterType = newParameterType;
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
|
@ -72,7 +73,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
private boolean myManualResponseMode;
|
||||
|
||||
protected OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
boolean theIdempotent, String theOperationName, Class<? extends IBaseResource> theOperationType,
|
||||
boolean theIdempotent, String theOperationName, Class<? extends IBaseResource> theOperationType, String theOperationTypeName,
|
||||
OperationParam[] theReturnParams, BundleTypeEnum theBundleType) {
|
||||
super(theReturnResourceType, theMethod, theContext, theProvider);
|
||||
|
||||
|
@ -99,12 +100,18 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
}
|
||||
myName = theOperationName;
|
||||
|
||||
if (theReturnTypeFromRp != null) {
|
||||
setResourceName(theContext.getResourceDefinition(theReturnTypeFromRp).getName());
|
||||
} else if (Modifier.isAbstract(theOperationType.getModifiers()) == false) {
|
||||
setResourceName(theContext.getResourceDefinition(theOperationType).getName());
|
||||
} else {
|
||||
setResourceName(null);
|
||||
try {
|
||||
if (theReturnTypeFromRp != null) {
|
||||
setResourceName(theContext.getResourceDefinition(theReturnTypeFromRp).getName());
|
||||
} else if (Modifier.isAbstract(theOperationType.getModifiers()) == false) {
|
||||
setResourceName(theContext.getResourceDefinition(theOperationType).getName());
|
||||
} else if (isNotBlank(theOperationTypeName)) {
|
||||
setResourceName(theContext.getResourceDefinition(theOperationTypeName).getName());
|
||||
} else {
|
||||
setResourceName(null);
|
||||
}
|
||||
} catch (DataFormatException e) {
|
||||
throw new ConfigurationException("Failed to bind method " + theMethod + " - " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (theMethod.getReturnType().equals(IBundleProvider.class)) {
|
||||
|
@ -160,7 +167,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
*/
|
||||
public OperationMethodBinding(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
Operation theAnnotation) {
|
||||
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type(), theAnnotation.returnParameters(),
|
||||
this(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, theAnnotation.idempotent(), theAnnotation.name(), theAnnotation.type(), theAnnotation.typeName(), theAnnotation.returnParameters(),
|
||||
theAnnotation.bundleType());
|
||||
|
||||
myManualRequestMode = theAnnotation.manualRequest();
|
||||
|
|
|
@ -187,7 +187,7 @@ public class OperationParameter implements IParameter {
|
|||
mySearchParameterBinding.setType(myContext, theParameterType, theInnerCollectionType, theOuterCollectionType);
|
||||
myConverter = new OperationParamConverter();
|
||||
} else {
|
||||
throw new ConfigurationException("Invalid type for @OperationParam: " + myParameterType.getName());
|
||||
throw new ConfigurationException("Invalid type for @OperationParam on method " + theMethod + ": " + myParameterType.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ValidateMethodBindingDstu2Plus extends OperationMethodBinding {
|
|||
|
||||
public ValidateMethodBindingDstu2Plus(Class<?> theReturnResourceType, Class<? extends IBaseResource> theReturnTypeFromRp, Method theMethod, FhirContext theContext, Object theProvider,
|
||||
Validate theAnnotation) {
|
||||
super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), new OperationParam[0], BundleTypeEnum.COLLECTION);
|
||||
super(theReturnResourceType, theReturnTypeFromRp, theMethod, theContext, theProvider, true, Constants.EXTOP_VALIDATE, theAnnotation.type(), null, new OperationParam[0], BundleTypeEnum.COLLECTION);
|
||||
|
||||
List<IParameter> newParams = new ArrayList<IParameter>();
|
||||
int idx = 0;
|
||||
|
|
|
@ -276,4 +276,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
return new CodeValidationResult(OperationOutcome.IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return validateCode(theContext, theSystem, theCode, null).asLookupCodeResult(theSystem, theCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ public interface IValidationSupport
|
|||
@Override
|
||||
CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay);
|
||||
|
||||
public class CodeValidationResult extends IContextValidationSupport.CodeValidationResult<ConceptDefinitionComponent, OperationOutcome.IssueSeverity> {
|
||||
class CodeValidationResult extends IContextValidationSupport.CodeValidationResult<ConceptDefinitionComponent, OperationOutcome.IssueSeverity> {
|
||||
|
||||
public CodeValidationResult(ConceptDefinitionComponent theNext) {
|
||||
super(theNext);
|
||||
|
@ -114,6 +114,15 @@ public interface IValidationSupport
|
|||
super(severity, message, definition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDisplay() {
|
||||
String retVal = null;
|
||||
if (isOk()) {
|
||||
retVal = asConceptDefinition().getDisplay();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,4 +138,9 @@ public class PrePopulatedValidationSupport implements IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,4 +143,15 @@ public class ValidationSupportChain implements IValidationSupport {
|
|||
return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
for (IValidationSupport next : myChain) {
|
||||
if (next.isCodeSystemSupported(theContext, theSystem)) {
|
||||
return next.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,274 +24,284 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
|
||||
public class DefaultProfileValidationSupport implements IValidationSupport {
|
||||
|
||||
private static final String URL_PREFIX_VALUE_SET = "http://hl7.org/fhir/ValueSet/";
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/";
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/";
|
||||
private static final String URL_PREFIX_VALUE_SET = "http://hl7.org/fhir/ValueSet/";
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/";
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class);
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class);
|
||||
|
||||
private Map<String, CodeSystem> myCodeSystems;
|
||||
private Map<String, StructureDefinition> myStructureDefinitions;
|
||||
private Map<String, ValueSet> myValueSets;
|
||||
private Map<String, CodeSystem> myCodeSystems;
|
||||
private Map<String, StructureDefinition> myStructureDefinitions;
|
||||
private Map<String, ValueSet> myValueSets;
|
||||
|
||||
@Override
|
||||
public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
||||
ValueSetExpansionComponent retVal = new ValueSetExpansionComponent();
|
||||
@Override
|
||||
public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
||||
ValueSetExpansionComponent retVal = new ValueSetExpansionComponent();
|
||||
|
||||
Set<String> wantCodes = new HashSet<>();
|
||||
for (ConceptReferenceComponent next : theInclude.getConcept()) {
|
||||
wantCodes.add(next.getCode());
|
||||
}
|
||||
Set<String> wantCodes = new HashSet<>();
|
||||
for (ConceptReferenceComponent next : theInclude.getConcept()) {
|
||||
wantCodes.add(next.getCode());
|
||||
}
|
||||
|
||||
CodeSystem system = fetchCodeSystem(theContext, theInclude.getSystem());
|
||||
if (system != null) {
|
||||
List<ConceptDefinitionComponent> concepts = system.getConcept();
|
||||
addConcepts(theInclude, retVal, wantCodes, concepts);
|
||||
}
|
||||
CodeSystem system = fetchCodeSystem(theContext, theInclude.getSystem());
|
||||
if (system != null) {
|
||||
List<ConceptDefinitionComponent> concepts = system.getConcept();
|
||||
addConcepts(theInclude, retVal, wantCodes, concepts);
|
||||
}
|
||||
|
||||
for (UriType next: theInclude.getValueSet()) {
|
||||
ValueSet vs = myValueSets.get(defaultString(next.getValueAsString()));
|
||||
if (vs != null) {
|
||||
for (ConceptSetComponent nextInclude : vs.getCompose().getInclude()) {
|
||||
ValueSetExpansionComponent contents = expandValueSet(theContext, nextInclude);
|
||||
retVal.getContains().addAll(contents.getContains());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (UriType next : theInclude.getValueSet()) {
|
||||
ValueSet vs = myValueSets.get(defaultString(next.getValueAsString()));
|
||||
if (vs != null) {
|
||||
for (ConceptSetComponent nextInclude : vs.getCompose().getInclude()) {
|
||||
ValueSetExpansionComponent contents = expandValueSet(theContext, nextInclude);
|
||||
retVal.getContains().addAll(contents.getContains());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void addConcepts(ConceptSetComponent theInclude, ValueSetExpansionComponent theRetVal, Set<String> theWantCodes, List<ConceptDefinitionComponent> theConcepts) {
|
||||
for (ConceptDefinitionComponent next : theConcepts) {
|
||||
if (theWantCodes.isEmpty() || theWantCodes.contains(next.getCode())) {
|
||||
theRetVal
|
||||
.addContains()
|
||||
.setSystem(theInclude.getSystem())
|
||||
.setCode(next.getCode())
|
||||
.setDisplay(next.getDisplay());
|
||||
}
|
||||
addConcepts(theInclude, theRetVal, theWantCodes, next.getConcept());
|
||||
}
|
||||
}
|
||||
private void addConcepts(ConceptSetComponent theInclude, ValueSetExpansionComponent theRetVal, Set<String> theWantCodes, List<ConceptDefinitionComponent> theConcepts) {
|
||||
for (ConceptDefinitionComponent next : theConcepts) {
|
||||
if (theWantCodes.isEmpty() || theWantCodes.contains(next.getCode())) {
|
||||
theRetVal
|
||||
.addContains()
|
||||
.setSystem(theInclude.getSystem())
|
||||
.setCode(next.getCode())
|
||||
.setDisplay(next.getDisplay());
|
||||
}
|
||||
addConcepts(theInclude, theRetVal, theWantCodes, next.getConcept());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources(FhirContext theContext) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
retVal.addAll(myCodeSystems.values());
|
||||
retVal.addAll(myStructureDefinitions.values());
|
||||
retVal.addAll(myValueSets.values());
|
||||
return retVal;
|
||||
}
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources(FhirContext theContext) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
retVal.addAll(myCodeSystems.values());
|
||||
retVal.addAll(myStructureDefinitions.values());
|
||||
retVal.addAll(myValueSets.values());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
|
||||
return new ArrayList<StructureDefinition>(provideStructureDefinitionMap(theContext).values());
|
||||
}
|
||||
@Override
|
||||
public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
|
||||
return new ArrayList<StructureDefinition>(provideStructureDefinitionMap(theContext).values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) {
|
||||
return (CodeSystem) fetchCodeSystemOrValueSet(theContext, theSystem, true);
|
||||
}
|
||||
@Override
|
||||
public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) {
|
||||
return (CodeSystem) fetchCodeSystemOrValueSet(theContext, theSystem, true);
|
||||
}
|
||||
|
||||
private DomainResource fetchCodeSystemOrValueSet(FhirContext theContext, String theSystem, boolean codeSystem) {
|
||||
synchronized (this) {
|
||||
Map<String, CodeSystem> codeSystems = myCodeSystems;
|
||||
Map<String, ValueSet> valueSets = myValueSets;
|
||||
if (codeSystems == null || valueSets == null) {
|
||||
codeSystems = new HashMap<String, CodeSystem>();
|
||||
valueSets = new HashMap<String, ValueSet>();
|
||||
private DomainResource fetchCodeSystemOrValueSet(FhirContext theContext, String theSystem, boolean codeSystem) {
|
||||
synchronized (this) {
|
||||
Map<String, CodeSystem> codeSystems = myCodeSystems;
|
||||
Map<String, ValueSet> valueSets = myValueSets;
|
||||
if (codeSystems == null || valueSets == null) {
|
||||
codeSystems = new HashMap<String, CodeSystem>();
|
||||
valueSets = new HashMap<String, ValueSet>();
|
||||
|
||||
loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/valuesets.xml");
|
||||
loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v2-tables.xml");
|
||||
loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v3-codesystems.xml");
|
||||
loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/valuesets.xml");
|
||||
loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v2-tables.xml");
|
||||
loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu3/model/valueset/v3-codesystems.xml");
|
||||
|
||||
myCodeSystems = codeSystems;
|
||||
myValueSets = valueSets;
|
||||
}
|
||||
myCodeSystems = codeSystems;
|
||||
myValueSets = valueSets;
|
||||
}
|
||||
|
||||
if (codeSystem) {
|
||||
return codeSystems.get(theSystem);
|
||||
} else {
|
||||
return valueSets.get(theSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (codeSystem) {
|
||||
return codeSystems.get(theSystem);
|
||||
} else {
|
||||
return valueSets.get(theSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
Validate.notBlank(theUri, "theUri must not be null or blank");
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
Validate.notBlank(theUri, "theUri must not be null or blank");
|
||||
|
||||
if (theClass.equals(StructureDefinition.class)) {
|
||||
return (T) fetchStructureDefinition(theContext, theUri);
|
||||
}
|
||||
if (theClass.equals(StructureDefinition.class)) {
|
||||
return (T) fetchStructureDefinition(theContext, theUri);
|
||||
}
|
||||
|
||||
if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) {
|
||||
return (T) fetchValueSet(theContext, theUri);
|
||||
}
|
||||
if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) {
|
||||
return (T) fetchValueSet(theContext, theUri);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theContext, String theUrl) {
|
||||
String url = theUrl;
|
||||
if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
// no change
|
||||
} else if (url.indexOf('/') == -1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION + url;
|
||||
} else if (StringUtils.countMatches(url, '/') == 1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url;
|
||||
}
|
||||
Map<String, StructureDefinition> map = provideStructureDefinitionMap(theContext);
|
||||
StructureDefinition retVal = map.get(url);
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theContext, String theUrl) {
|
||||
String url = theUrl;
|
||||
if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
// no change
|
||||
} else if (url.indexOf('/') == -1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION + url;
|
||||
} else if (StringUtils.countMatches(url, '/') == 1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url;
|
||||
}
|
||||
Map<String, StructureDefinition> map = provideStructureDefinitionMap(theContext);
|
||||
StructureDefinition retVal = map.get(url);
|
||||
|
||||
if (retVal == null && url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
String tryUrl = URL_PREFIX_STRUCTURE_DEFINITION + StringUtils.capitalize(url.substring(URL_PREFIX_STRUCTURE_DEFINITION.length()));
|
||||
retVal = map.get(tryUrl);
|
||||
}
|
||||
if (retVal == null && url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
String tryUrl = URL_PREFIX_STRUCTURE_DEFINITION + StringUtils.capitalize(url.substring(URL_PREFIX_STRUCTURE_DEFINITION.length()));
|
||||
retVal = map.get(tryUrl);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet fetchValueSet(FhirContext theContext, String uri) {
|
||||
return (ValueSet) fetchCodeSystemOrValueSet(theContext, uri, false);
|
||||
}
|
||||
@Override
|
||||
public ValueSet fetchValueSet(FhirContext theContext, String uri) {
|
||||
return (ValueSet) fetchCodeSystemOrValueSet(theContext, uri, false);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
myCodeSystems = null;
|
||||
myStructureDefinitions = null;
|
||||
}
|
||||
public void flush() {
|
||||
myCodeSystems = null;
|
||||
myStructureDefinitions = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) {
|
||||
CodeSystem cs = fetchCodeSystem(theContext, theSystem);
|
||||
return cs != null && cs.getContent() != CodeSystemContentMode.NOTPRESENT;
|
||||
}
|
||||
@Override
|
||||
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) {
|
||||
CodeSystem cs = fetchCodeSystem(theContext, theSystem);
|
||||
return cs != null && cs.getContent() != CodeSystemContentMode.NOTPRESENT;
|
||||
}
|
||||
|
||||
private void loadCodeSystems(FhirContext theContext, Map<String, CodeSystem> theCodeSystems, Map<String, ValueSet> theValueSets, String theClasspath) {
|
||||
ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath);
|
||||
InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath);
|
||||
InputStreamReader reader = null;
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
reader = new InputStreamReader(inputStream, Charsets.UTF_8);
|
||||
private void loadCodeSystems(FhirContext theContext, Map<String, CodeSystem> theCodeSystems, Map<String, ValueSet> theValueSets, String theClasspath) {
|
||||
ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath);
|
||||
InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath);
|
||||
InputStreamReader reader = null;
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
reader = new InputStreamReader(inputStream, Charsets.UTF_8);
|
||||
|
||||
Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
|
||||
for (BundleEntryComponent next : bundle.getEntry()) {
|
||||
if (next.getResource() instanceof CodeSystem) {
|
||||
CodeSystem nextValueSet = (CodeSystem) next.getResource();
|
||||
nextValueSet.getText().setDivAsString("");
|
||||
String system = nextValueSet.getUrl();
|
||||
if (isNotBlank(system)) {
|
||||
theCodeSystems.put(system, nextValueSet);
|
||||
}
|
||||
} else if (next.getResource() instanceof ValueSet) {
|
||||
ValueSet nextValueSet = (ValueSet) next.getResource();
|
||||
nextValueSet.getText().setDivAsString("");
|
||||
String system = nextValueSet.getUrl();
|
||||
if (isNotBlank(system)) {
|
||||
theValueSets.put(system, nextValueSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
}
|
||||
Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
|
||||
for (BundleEntryComponent next : bundle.getEntry()) {
|
||||
if (next.getResource() instanceof CodeSystem) {
|
||||
CodeSystem nextValueSet = (CodeSystem) next.getResource();
|
||||
nextValueSet.getText().setDivAsString("");
|
||||
String system = nextValueSet.getUrl();
|
||||
if (isNotBlank(system)) {
|
||||
theCodeSystems.put(system, nextValueSet);
|
||||
}
|
||||
} else if (next.getResource() instanceof ValueSet) {
|
||||
ValueSet nextValueSet = (ValueSet) next.getResource();
|
||||
nextValueSet.getText().setDivAsString("");
|
||||
String system = nextValueSet.getUrl();
|
||||
if (isNotBlank(system)) {
|
||||
theValueSets.put(system, nextValueSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadStructureDefinitions(FhirContext theContext, Map<String, StructureDefinition> theCodeSystems, String theClasspath) {
|
||||
ourLog.info("Loading structure definitions from classpath: {}", theClasspath);
|
||||
InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath);
|
||||
if (valuesetText != null) {
|
||||
InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8);
|
||||
private void loadStructureDefinitions(FhirContext theContext, Map<String, StructureDefinition> theCodeSystems, String theClasspath) {
|
||||
ourLog.info("Loading structure definitions from classpath: {}", theClasspath);
|
||||
InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath);
|
||||
if (valuesetText != null) {
|
||||
InputStreamReader reader = new InputStreamReader(valuesetText, Charsets.UTF_8);
|
||||
|
||||
Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
|
||||
for (BundleEntryComponent next : bundle.getEntry()) {
|
||||
if (next.getResource() instanceof StructureDefinition) {
|
||||
StructureDefinition nextSd = (StructureDefinition) next.getResource();
|
||||
nextSd.getText().setDivAsString("");
|
||||
String system = nextSd.getUrl();
|
||||
if (isNotBlank(system)) {
|
||||
theCodeSystems.put(system, nextSd);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
}
|
||||
Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
|
||||
for (BundleEntryComponent next : bundle.getEntry()) {
|
||||
if (next.getResource() instanceof StructureDefinition) {
|
||||
StructureDefinition nextSd = (StructureDefinition) next.getResource();
|
||||
nextSd.getText().setDivAsString("");
|
||||
String system = nextSd.getUrl();
|
||||
if (isNotBlank(system)) {
|
||||
theCodeSystems.put(system, nextSd);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, StructureDefinition> provideStructureDefinitionMap(FhirContext theContext) {
|
||||
Map<String, StructureDefinition> structureDefinitions = myStructureDefinitions;
|
||||
if (structureDefinitions == null) {
|
||||
structureDefinitions = new HashMap<String, StructureDefinition>();
|
||||
private Map<String, StructureDefinition> provideStructureDefinitionMap(FhirContext theContext) {
|
||||
Map<String, StructureDefinition> structureDefinitions = myStructureDefinitions;
|
||||
if (structureDefinitions == null) {
|
||||
structureDefinitions = new HashMap<String, StructureDefinition>();
|
||||
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-resources.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-types.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-others.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/extension/extension-definitions.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-resources.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-types.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/profile/profiles-others.xml");
|
||||
loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu3/model/extension/extension-definitions.xml");
|
||||
|
||||
myStructureDefinitions = structureDefinitions;
|
||||
}
|
||||
return structureDefinitions;
|
||||
}
|
||||
myStructureDefinitions = structureDefinitions;
|
||||
}
|
||||
return structureDefinitions;
|
||||
}
|
||||
|
||||
private CodeValidationResult testIfConceptIsInList(String theCode, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive) {
|
||||
String code = theCode;
|
||||
if (theCaseSensitive == false) {
|
||||
code = code.toUpperCase();
|
||||
}
|
||||
private CodeValidationResult testIfConceptIsInList(CodeSystem theCodeSystem, String theCode, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive) {
|
||||
String code = theCode;
|
||||
if (theCaseSensitive == false) {
|
||||
code = code.toUpperCase();
|
||||
}
|
||||
|
||||
return testIfConceptIsInListInner(conceptList, theCaseSensitive, code);
|
||||
}
|
||||
return testIfConceptIsInListInner(theCodeSystem, conceptList, theCaseSensitive, code);
|
||||
}
|
||||
|
||||
private CodeValidationResult testIfConceptIsInListInner(List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive, String code) {
|
||||
CodeValidationResult retVal = null;
|
||||
for (ConceptDefinitionComponent next : conceptList) {
|
||||
String nextCandidate = next.getCode();
|
||||
if (theCaseSensitive == false) {
|
||||
nextCandidate = nextCandidate.toUpperCase();
|
||||
}
|
||||
if (nextCandidate.equals(code)) {
|
||||
retVal = new CodeValidationResult(next);
|
||||
break;
|
||||
}
|
||||
private CodeValidationResult testIfConceptIsInListInner(CodeSystem theCodeSystem, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive, String code) {
|
||||
CodeValidationResult retVal = null;
|
||||
for (ConceptDefinitionComponent next : conceptList) {
|
||||
String nextCandidate = next.getCode();
|
||||
if (theCaseSensitive == false) {
|
||||
nextCandidate = nextCandidate.toUpperCase();
|
||||
}
|
||||
if (nextCandidate.equals(code)) {
|
||||
retVal = new CodeValidationResult(next);
|
||||
break;
|
||||
}
|
||||
|
||||
// recurse
|
||||
retVal = testIfConceptIsInList(code, next.getConcept(), theCaseSensitive);
|
||||
if (retVal != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// recurse
|
||||
retVal = testIfConceptIsInList(theCodeSystem, code, next.getConcept(), theCaseSensitive);
|
||||
if (retVal != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
if (retVal != null) {
|
||||
retVal.setCodeSystemName(theCodeSystem.getName());
|
||||
retVal.setCodeSystemVersion(theCodeSystem.getVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem);
|
||||
if (cs != null) {
|
||||
boolean caseSensitive = true;
|
||||
if (cs.hasCaseSensitive()) {
|
||||
caseSensitive = cs.getCaseSensitive();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive);
|
||||
@Override
|
||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem);
|
||||
if (cs != null) {
|
||||
boolean caseSensitive = true;
|
||||
if (cs.hasCaseSensitive()) {
|
||||
caseSensitive = cs.getCaseSensitive();
|
||||
}
|
||||
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
CodeValidationResult retVal = testIfConceptIsInList(cs, theCode, cs.getConcept(), caseSensitive);
|
||||
|
||||
return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode);
|
||||
}
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return validateCode(theContext, theSystem, theCode, null).asLookupCodeResult(theSystem, theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
|
|
|
@ -1,43 +1,39 @@
|
|||
package org.hl7.fhir.dstu3.hapi.ctx;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||
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.IBaseResource;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||
import java.util.List;
|
||||
|
||||
public interface IValidationSupport
|
||||
extends ca.uhn.fhir.context.support.IContextValidationSupport<ConceptSetComponent, ValueSetExpansionComponent, StructureDefinition, CodeSystem, ConceptDefinitionComponent, IssueSeverity> {
|
||||
extends ca.uhn.fhir.context.support.IContextValidationSupport<ConceptSetComponent, ValueSetExpansionComponent, StructureDefinition, CodeSystem, ConceptDefinitionComponent, IssueSeverity> {
|
||||
|
||||
/**
|
||||
* Expands the given portion of a ValueSet
|
||||
*
|
||||
* @param theInclude
|
||||
* The portion to include
|
||||
* @return The expansion
|
||||
*/
|
||||
@Override
|
||||
ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude);
|
||||
/**
|
||||
* Expands the given portion of a ValueSet
|
||||
*
|
||||
* @param theInclude The portion to include
|
||||
* @return The expansion
|
||||
*/
|
||||
@Override
|
||||
ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude);
|
||||
|
||||
/**
|
||||
* Load and return all possible structure definitions
|
||||
*/
|
||||
@Override
|
||||
List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext);
|
||||
/**
|
||||
* Load and return all possible structure definitions
|
||||
*/
|
||||
@Override
|
||||
List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext);
|
||||
|
||||
/**
|
||||
* Fetch a code system by Uri
|
||||
*
|
||||
* @param uri
|
||||
* Canonical Uri of the code system
|
||||
* @param uri Canonical Uri of the code system
|
||||
* @return The valueset (must not be null, but can be an empty ValueSet)
|
||||
*/
|
||||
@Override
|
||||
|
@ -46,82 +42,68 @@ public interface IValidationSupport
|
|||
/**
|
||||
* Fetch a valueset by Uri
|
||||
*
|
||||
* @param uri
|
||||
* Canonical Uri of the ValueSet
|
||||
* @param uri Canonical Uri of the ValueSet
|
||||
* @return The valueset (must not be null, but can be an empty ValueSet)
|
||||
*/
|
||||
ValueSet fetchValueSet(FhirContext theContext, String uri);
|
||||
|
||||
/**
|
||||
* Loads a resource needed by the validation (a StructureDefinition, or a
|
||||
* ValueSet)
|
||||
*
|
||||
* @param theContext
|
||||
* The HAPI FHIR Context object current in use by the validator
|
||||
* @param theClass
|
||||
* The type of the resource to load
|
||||
* @param theUri
|
||||
* The resource URI
|
||||
* @return Returns the resource, or <code>null</code> if no resource with the
|
||||
* given URI can be found
|
||||
*/
|
||||
@Override
|
||||
<T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri);
|
||||
@Override
|
||||
StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl);
|
||||
|
||||
@Override
|
||||
StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl);
|
||||
/**
|
||||
* Returns <code>true</code> if codes in the given code system can be expanded
|
||||
* or validated
|
||||
*
|
||||
* @param theSystem The URI for the code system, e.g. <code>"http://loinc.org"</code>
|
||||
* @return Returns <code>true</code> if codes in the given code system can be
|
||||
* validated
|
||||
*/
|
||||
@Override
|
||||
boolean isCodeSystemSupported(FhirContext theContext, String theSystem);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if codes in the given code system can be expanded
|
||||
* or validated
|
||||
*
|
||||
* @param theSystem
|
||||
* The URI for the code system, e.g. <code>"http://loinc.org"</code>
|
||||
* @return Returns <code>true</code> if codes in the given code system can be
|
||||
* validated
|
||||
*/
|
||||
@Override
|
||||
boolean isCodeSystemSupported(FhirContext theContext, String theSystem);
|
||||
|
||||
/**
|
||||
* Validates that the given code exists and if possible returns a display
|
||||
* name. This method is called to check codes which are found in "example"
|
||||
* binding fields (e.g. <code>Observation.code</code> in the default profile.
|
||||
*
|
||||
* @param theCodeSystem
|
||||
* The code system, e.g. "<code>http://loinc.org</code>"
|
||||
* @param theCode
|
||||
* The code, e.g. "<code>1234-5</code>"
|
||||
* @param theDisplay
|
||||
* The display name, if it should also be validated
|
||||
* @return Returns a validation result object
|
||||
*/
|
||||
@Override
|
||||
CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay);
|
||||
/**
|
||||
* Validates that the given code exists and if possible returns a display
|
||||
* name. This method is called to check codes which are found in "example"
|
||||
* binding fields (e.g. <code>Observation.code</code> in the default profile.
|
||||
*
|
||||
* @param theCodeSystem The code system, e.g. "<code>http://loinc.org</code>"
|
||||
* @param theCode The code, e.g. "<code>1234-5</code>"
|
||||
* @param theDisplay The display name, if it should also be validated
|
||||
* @return Returns a validation result object
|
||||
*/
|
||||
@Override
|
||||
CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay);
|
||||
|
||||
/**
|
||||
* Generate a snapshot from the given differential profile.
|
||||
*
|
||||
* @param theInput
|
||||
* @param theUrl
|
||||
* @return Returns null if this module does not know how to handle this request
|
||||
*/
|
||||
StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName);
|
||||
|
||||
class CodeValidationResult extends IContextValidationSupport.CodeValidationResult<ConceptDefinitionComponent, IssueSeverity> {
|
||||
|
||||
public CodeValidationResult(ConceptDefinitionComponent theNext) {
|
||||
super(theNext);
|
||||
}
|
||||
public CodeValidationResult(ConceptDefinitionComponent theNext) {
|
||||
super(theNext);
|
||||
}
|
||||
|
||||
public CodeValidationResult(IssueSeverity theSeverity, String theMessage) {
|
||||
super(theSeverity, theMessage);
|
||||
}
|
||||
public CodeValidationResult(IssueSeverity theSeverity, String theMessage) {
|
||||
super(theSeverity, theMessage);
|
||||
}
|
||||
|
||||
public CodeValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
|
||||
super(severity, message, definition);
|
||||
}
|
||||
public CodeValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
|
||||
super(severity, message, definition);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
protected String getDisplay() {
|
||||
String retVal = null;
|
||||
if (isOk()) {
|
||||
retVal = asConceptDefinition().getDisplay();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -257,16 +257,16 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
return structureDefinitions;
|
||||
}
|
||||
|
||||
private CodeValidationResult testIfConceptIsInList(String theCode, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive) {
|
||||
private CodeValidationResult testIfConceptIsInList(CodeSystem theCodeSystem, String theCode, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive) {
|
||||
String code = theCode;
|
||||
if (theCaseSensitive == false) {
|
||||
code = code.toUpperCase();
|
||||
}
|
||||
|
||||
return testIfConceptIsInListInner(conceptList, theCaseSensitive, code);
|
||||
return testIfConceptIsInListInner(theCodeSystem, conceptList, theCaseSensitive, code);
|
||||
}
|
||||
|
||||
private CodeValidationResult testIfConceptIsInListInner(List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive, String code) {
|
||||
private CodeValidationResult testIfConceptIsInListInner(CodeSystem theCodeSystem, List<ConceptDefinitionComponent> conceptList, boolean theCaseSensitive, String code) {
|
||||
CodeValidationResult retVal = null;
|
||||
for (ConceptDefinitionComponent next : conceptList) {
|
||||
String nextCandidate = next.getCode();
|
||||
|
@ -279,12 +279,17 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
}
|
||||
|
||||
// recurse
|
||||
retVal = testIfConceptIsInList(code, next.getConcept(), theCaseSensitive);
|
||||
retVal = testIfConceptIsInList(theCodeSystem, code, next.getConcept(), theCaseSensitive);
|
||||
if (retVal != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retVal != null) {
|
||||
retVal.setCodeSystemName(theCodeSystem.getName());
|
||||
retVal.setCodeSystemVersion(theCodeSystem.getVersion());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -297,7 +302,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
caseSensitive = cs.getCaseSensitive();
|
||||
}
|
||||
|
||||
CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive);
|
||||
CodeValidationResult retVal = testIfConceptIsInList(cs, theCode, cs.getConcept(), caseSensitive);
|
||||
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
|
@ -307,4 +312,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return validateCode(theContext, theSystem, theCode, null).asLookupCodeResult(theSystem, theCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -112,6 +112,15 @@ public interface IValidationSupport
|
|||
super(severity, message, definition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDisplay() {
|
||||
String retVal = null;
|
||||
if (isOk()) {
|
||||
retVal = asConceptDefinition().getDisplay();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import ca.uhn.fhir.test.utilities.JettyUtil;
|
|||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
|
@ -29,10 +30,11 @@ import org.junit.*;
|
|||
|
||||
import javax.servlet.ServletException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class OperationGenericServer2R4Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(OperationGenericServer2R4Test.class);
|
||||
|
@ -41,6 +43,7 @@ public class OperationGenericServer2R4Test {
|
|||
private static IdType ourLastId;
|
||||
private static Object ourLastParam1;
|
||||
private static Object ourLastParam2;
|
||||
private static Object ourLastParam3;
|
||||
private static Parameters ourLastResourceParam;
|
||||
private int myPort;
|
||||
private Server myServer;
|
||||
|
@ -49,6 +52,7 @@ public class OperationGenericServer2R4Test {
|
|||
public void before() {
|
||||
ourLastParam1 = null;
|
||||
ourLastParam2 = null;
|
||||
ourLastParam3=null;
|
||||
ourLastId = null;
|
||||
ourLastResourceParam = null;
|
||||
}
|
||||
|
@ -112,6 +116,65 @@ public class OperationGenericServer2R4Test {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testDeclarativeStringTypedParameters() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class PatientProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
public Class<Patient> getResourceType() {
|
||||
return Patient.class;
|
||||
}
|
||||
|
||||
@Operation(name = "$OP_INSTANCE")
|
||||
public Parameters opInstance(
|
||||
@ResourceParam() IBaseResource theResourceParam,
|
||||
@IdParam IdType theId,
|
||||
@OperationParam(name = "PARAM1", min = 1, typeName = "uri") IPrimitiveType<String> theParam1,
|
||||
@OperationParam(name = "PARAM2", min = 1, max = OperationParam.MAX_UNLIMITED, typeName = "string") List<IPrimitiveType<String>> theParam2,
|
||||
@OperationParam(name = "PARAM3", min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "attachment") List<ICompositeType> theParam3
|
||||
) {
|
||||
|
||||
ourLastId = theId;
|
||||
ourLastParam1 = theParam1;
|
||||
ourLastParam2 = theParam2;
|
||||
ourLastParam3 = theParam2;
|
||||
ourLastResourceParam = (Parameters) theResourceParam;
|
||||
|
||||
Parameters retVal = new Parameters();
|
||||
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PatientProvider provider = new PatientProvider();
|
||||
startServer(provider);
|
||||
|
||||
Parameters p = new Parameters();
|
||||
p.addParameter().setName("PARAM1").setValue(new UriType("PARAM1val"));
|
||||
p.addParameter().setName("PARAM2").setValue(new StringType("PARAM2val"));
|
||||
String inParamsStr = ourCtx.newXmlParser().encodeResourceToString(p);
|
||||
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + myPort + "/Patient/123/$OP_INSTANCE");
|
||||
httpPost.setEntity(new StringEntity(inParamsStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
try (CloseableHttpResponse status = ourClient.execute(httpPost)) {
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(response);
|
||||
status.getEntity().getContent().close();
|
||||
|
||||
UriType param1 = (UriType) ourLastParam1;
|
||||
assertEquals("PARAM1val", param1.getValue());
|
||||
|
||||
List<StringType> param2 = (List<StringType>) ourLastParam2;
|
||||
assertEquals("PARAM2val", param2.get(0).getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclarativeTypedParametersInvalid() throws Exception {
|
||||
|
||||
|
@ -138,10 +201,71 @@ public class OperationGenericServer2R4Test {
|
|||
fail();
|
||||
} catch (ServletException e) {
|
||||
ConfigurationException ce = (ConfigurationException) e.getCause();
|
||||
assertEquals("Failure scanning class PatientProvider: Non assignable parameter typeName=\"code\" specified on method public org.hl7.fhir.r4.model.Parameters ca.uhn.fhir.rest.server.OperationGenericServer2R4Test$2PatientProvider.opInstance(org.hl7.fhir.instance.model.api.ICompositeType)", ce.getMessage());
|
||||
assertThat(ce.getMessage(), containsString("Failure scanning class PatientProvider: Non assignable parameter typeName=\"code\" specified on method public org.hl7.fhir.r4.model.Parameters ca.uhn.fhir.rest.server.OperationGenericServer2R4Test"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTypeOperationWithTypeDeclaredByName() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class PlainProvider {
|
||||
|
||||
@Operation(name = "$OP_INSTANCE", typeName = "Patient", idempotent = true)
|
||||
public Parameters opInstance(
|
||||
@ResourceParam() IBaseResource theResourceParam,
|
||||
@IdParam IdType theId
|
||||
) {
|
||||
|
||||
ourLastId = theId;
|
||||
|
||||
Parameters retVal = new Parameters();
|
||||
retVal.addParameter().setName("RET1").setValue(new StringType("RETVAL1"));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PlainProvider provider = new PlainProvider();
|
||||
startServer(provider);
|
||||
|
||||
HttpGet httpPost = new HttpGet("http://localhost:" + myPort + "/Patient/123/$OP_INSTANCE");
|
||||
try (CloseableHttpResponse status = ourClient.execute(httpPost)) {
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(response);
|
||||
status.getEntity().getContent().close();
|
||||
|
||||
assertEquals("123", ourLastId.getIdPart());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeOperationWithInvalidType() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class PlainProvider {
|
||||
|
||||
@Operation(name = "$OP_INSTANCE", typeName = "FOO", idempotent = true)
|
||||
public Parameters opInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PlainProvider provider = new PlainProvider();
|
||||
try {
|
||||
startServer(provider);
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
Throwable cause = e.getRootCause();
|
||||
assertEquals("Failure scanning class PlainProvider: Failed to bind method public org.hl7.fhir.r4.model.Parameters ca.uhn.fhir.rest.server.OperationGenericServer2R4Test$2PlainProvider.opInstance() - Unknown resource name \"FOO\" (this name is not known in FHIR version \"R4\")", cause.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void startServer(Object theProvider) throws Exception {
|
||||
myServer = new Server(0);
|
||||
|
||||
|
|
|
@ -915,7 +915,7 @@ public class OperationServerR4Test {
|
|||
}
|
||||
|
||||
@Operation(name= "$manualResponseWithPrimitiveParam", idempotent = true, global = true, manualResponse = true)
|
||||
public void binaryAccess(
|
||||
public void manualResponseWithPrimitiveParam(
|
||||
@IdParam IIdType theResourceId,
|
||||
@OperationParam(name="path", min = 1, max = 1) IPrimitiveType<String> thePath,
|
||||
ServletRequestDetails theRequestDetails,
|
||||
|
|
|
@ -70,6 +70,11 @@ public class CachingValidationSupport implements IValidationSupport {
|
|||
return myWrap.validateCode(theContext, theCodeSystem, theCode, theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return myWrap.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
return myWrap.generateSnapshot(theInput, theUrl, theName);
|
||||
|
|
|
@ -185,6 +185,11 @@ public class PrePopulatedValidationSupport implements IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theName) {
|
||||
return null;
|
||||
|
|
|
@ -3,8 +3,6 @@ package org.hl7.fhir.dstu3.hapi.validation;
|
|||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
|
||||
import org.hl7.fhir.dstu3.context.IWorkerContext;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
||||
|
@ -13,6 +11,8 @@ import org.hl7.fhir.dstu3.model.CodeSystem;
|
|||
import org.hl7.fhir.dstu3.model.ElementDefinition;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -95,6 +95,11 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private class MyProfileKnowledgeWorker implements ProfileUtilities.ProfileKnowledgeProvider {
|
||||
@Override
|
||||
public boolean isDatatype(String typeSimple) {
|
||||
|
|
|
@ -170,6 +170,16 @@ public class ValidationSupportChain implements IValidationSupport {
|
|||
return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
for (IValidationSupport next : myChain) {
|
||||
if (next.isCodeSystemSupported(theContext, theSystem)) {
|
||||
return next.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theProfileName) {
|
||||
StructureDefinition outcome = null;
|
||||
|
|
|
@ -75,4 +75,9 @@ public class CachingValidationSupport implements IValidationSupport {
|
|||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
return myWrap.validateCode(theContext, theCodeSystem, theCode, theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return myWrap.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,129 +24,129 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
*/
|
||||
public class PrePopulatedValidationSupport implements IValidationSupport {
|
||||
|
||||
private Map<String, CodeSystem> myCodeSystems;
|
||||
private Map<String, StructureDefinition> myStructureDefinitions;
|
||||
private Map<String, ValueSet> myValueSets;
|
||||
private Map<String, CodeSystem> myCodeSystems;
|
||||
private Map<String, StructureDefinition> myStructureDefinitions;
|
||||
private Map<String, ValueSet> myValueSets;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public PrePopulatedValidationSupport() {
|
||||
myStructureDefinitions = new HashMap<>();
|
||||
myValueSets = new HashMap<>();
|
||||
myCodeSystems = new HashMap<>();
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public PrePopulatedValidationSupport() {
|
||||
myStructureDefinitions = new HashMap<>();
|
||||
myValueSets = new HashMap<>();
|
||||
myCodeSystems = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theStructureDefinitions The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and
|
||||
* values are the resource itself.
|
||||
* @param theValueSets The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are
|
||||
* the resource itself.
|
||||
* @param theCodeSystems The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are
|
||||
* the resource itself.
|
||||
*/
|
||||
public PrePopulatedValidationSupport(Map<String, StructureDefinition> theStructureDefinitions, Map<String, ValueSet> theValueSets, Map<String, CodeSystem> theCodeSystems) {
|
||||
myStructureDefinitions = theStructureDefinitions;
|
||||
myValueSets = theValueSets;
|
||||
myCodeSystems = theCodeSystems;
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theStructureDefinitions The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and
|
||||
* values are the resource itself.
|
||||
* @param theValueSets The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are
|
||||
* the resource itself.
|
||||
* @param theCodeSystems The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are
|
||||
* the resource itself.
|
||||
*/
|
||||
public PrePopulatedValidationSupport(Map<String, StructureDefinition> theStructureDefinitions, Map<String, ValueSet> theValueSets, Map<String, CodeSystem> theCodeSystems) {
|
||||
myStructureDefinitions = theStructureDefinitions;
|
||||
myValueSets = theValueSets;
|
||||
myCodeSystems = theCodeSystems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new CodeSystem resource which will be available to the validator. Note that
|
||||
* {@link CodeSystem#getUrl() the URL field) in this resource must contain a value as this
|
||||
* value will be used as the logical URL.
|
||||
* <p>
|
||||
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
|
||||
* it will be stored in three ways:
|
||||
* <ul>
|
||||
* <li>Extension</li>
|
||||
* <li>StructureDefinition/Extension</li>
|
||||
* <li>http://hl7.org/StructureDefinition/Extension</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addCodeSystem(CodeSystem theCodeSystem) {
|
||||
Validate.notBlank(theCodeSystem.getUrl(), "theCodeSystem.getUrl() must not return a value");
|
||||
addToMap(theCodeSystem, myCodeSystems, theCodeSystem.getUrl());
|
||||
}
|
||||
/**
|
||||
* Add a new CodeSystem resource which will be available to the validator. Note that
|
||||
* {@link CodeSystem#getUrl() the URL field) in this resource must contain a value as this
|
||||
* value will be used as the logical URL.
|
||||
* <p>
|
||||
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
|
||||
* it will be stored in three ways:
|
||||
* <ul>
|
||||
* <li>Extension</li>
|
||||
* <li>StructureDefinition/Extension</li>
|
||||
* <li>http://hl7.org/StructureDefinition/Extension</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addCodeSystem(CodeSystem theCodeSystem) {
|
||||
Validate.notBlank(theCodeSystem.getUrl(), "theCodeSystem.getUrl() must not return a value");
|
||||
addToMap(theCodeSystem, myCodeSystems, theCodeSystem.getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new StructureDefinition resource which will be available to the validator. Note that
|
||||
* {@link StructureDefinition#getUrl() the URL field) in this resource must contain a value as this
|
||||
* value will be used as the logical URL.
|
||||
* <p>
|
||||
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
|
||||
* it will be stored in three ways:
|
||||
* <ul>
|
||||
* <li>Extension</li>
|
||||
* <li>StructureDefinition/Extension</li>
|
||||
* <li>http://hl7.org/StructureDefinition/Extension</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addStructureDefinition(StructureDefinition theStructureDefinition) {
|
||||
Validate.notBlank(theStructureDefinition.getUrl(), "theStructureDefinition.getUrl() must not return a value");
|
||||
addToMap(theStructureDefinition, myStructureDefinitions, theStructureDefinition.getUrl());
|
||||
}
|
||||
/**
|
||||
* Add a new StructureDefinition resource which will be available to the validator. Note that
|
||||
* {@link StructureDefinition#getUrl() the URL field) in this resource must contain a value as this
|
||||
* value will be used as the logical URL.
|
||||
* <p>
|
||||
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
|
||||
* it will be stored in three ways:
|
||||
* <ul>
|
||||
* <li>Extension</li>
|
||||
* <li>StructureDefinition/Extension</li>
|
||||
* <li>http://hl7.org/StructureDefinition/Extension</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addStructureDefinition(StructureDefinition theStructureDefinition) {
|
||||
Validate.notBlank(theStructureDefinition.getUrl(), "theStructureDefinition.getUrl() must not return a value");
|
||||
addToMap(theStructureDefinition, myStructureDefinitions, theStructureDefinition.getUrl());
|
||||
}
|
||||
|
||||
private <T extends MetadataResource> void addToMap(T theStructureDefinition, Map<String, T> map, String theUrl) {
|
||||
if (isNotBlank(theUrl)) {
|
||||
map.put(theUrl, theStructureDefinition);
|
||||
private <T extends MetadataResource> void addToMap(T theStructureDefinition, Map<String, T> map, String theUrl) {
|
||||
if (isNotBlank(theUrl)) {
|
||||
map.put(theUrl, theStructureDefinition);
|
||||
|
||||
int lastSlashIdx = theUrl.lastIndexOf('/');
|
||||
if (lastSlashIdx != -1) {
|
||||
map.put(theUrl.substring(lastSlashIdx + 1), theStructureDefinition);
|
||||
int previousSlashIdx = theUrl.lastIndexOf('/', lastSlashIdx - 1);
|
||||
if (previousSlashIdx != -1) {
|
||||
map.put(theUrl.substring(previousSlashIdx + 1), theStructureDefinition);
|
||||
}
|
||||
}
|
||||
int lastSlashIdx = theUrl.lastIndexOf('/');
|
||||
if (lastSlashIdx != -1) {
|
||||
map.put(theUrl.substring(lastSlashIdx + 1), theStructureDefinition);
|
||||
int previousSlashIdx = theUrl.lastIndexOf('/', lastSlashIdx - 1);
|
||||
if (previousSlashIdx != -1) {
|
||||
map.put(theUrl.substring(previousSlashIdx + 1), theStructureDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new ValueSet resource which will be available to the validator. Note that
|
||||
* {@link ValueSet#getUrl() the URL field) in this resource must contain a value as this
|
||||
* value will be used as the logical URL.
|
||||
* <p>
|
||||
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
|
||||
* it will be stored in three ways:
|
||||
* <ul>
|
||||
* <li>Extension</li>
|
||||
* <li>StructureDefinition/Extension</li>
|
||||
* <li>http://hl7.org/StructureDefinition/Extension</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addValueSet(ValueSet theValueSet) {
|
||||
Validate.notBlank(theValueSet.getUrl(), "theValueSet.getUrl() must not return a value");
|
||||
addToMap(theValueSet, myValueSets, theValueSet.getUrl());
|
||||
}
|
||||
/**
|
||||
* Add a new ValueSet resource which will be available to the validator. Note that
|
||||
* {@link ValueSet#getUrl() the URL field) in this resource must contain a value as this
|
||||
* value will be used as the logical URL.
|
||||
* <p>
|
||||
* Note that if the URL is a canonical FHIR URL (e.g. http://hl7.org/StructureDefinition/Extension),
|
||||
* it will be stored in three ways:
|
||||
* <ul>
|
||||
* <li>Extension</li>
|
||||
* <li>StructureDefinition/Extension</li>
|
||||
* <li>http://hl7.org/StructureDefinition/Extension</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addValueSet(ValueSet theValueSet) {
|
||||
Validate.notBlank(theValueSet.getUrl(), "theValueSet.getUrl() must not return a value");
|
||||
addToMap(theValueSet, myValueSets, theValueSet.getUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSetExpander.ValueSetExpansionOutcome expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public ValueSetExpander.ValueSetExpansionOutcome expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources(FhirContext theContext) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
retVal.addAll(myCodeSystems.values());
|
||||
retVal.addAll(myStructureDefinitions.values());
|
||||
retVal.addAll(myValueSets.values());
|
||||
return retVal;
|
||||
}
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources(FhirContext theContext) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
retVal.addAll(myCodeSystems.values());
|
||||
retVal.addAll(myStructureDefinitions.values());
|
||||
retVal.addAll(myValueSets.values());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
|
||||
return new ArrayList<StructureDefinition>(myStructureDefinitions.values());
|
||||
}
|
||||
@Override
|
||||
public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
|
||||
return new ArrayList<StructureDefinition>(myStructureDefinitions.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public CodeSystem fetchCodeSystem(FhirContext theContext, String uri) {
|
||||
return myCodeSystems.get(uri);
|
||||
}
|
||||
|
@ -158,29 +158,29 @@ public class PrePopulatedValidationSupport implements IValidationSupport {
|
|||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
if (theClass.equals(StructureDefinition.class)) {
|
||||
return (T) myStructureDefinitions.get(theUri);
|
||||
}
|
||||
if (theClass.equals(ValueSet.class)) {
|
||||
return (T) myValueSets.get(theUri);
|
||||
}
|
||||
if (theClass.equals(CodeSystem.class)) {
|
||||
return (T) myCodeSystems.get(theUri);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
|
||||
if (theClass.equals(StructureDefinition.class)) {
|
||||
return (T) myStructureDefinitions.get(theUri);
|
||||
}
|
||||
if (theClass.equals(ValueSet.class)) {
|
||||
return (T) myValueSets.get(theUri);
|
||||
}
|
||||
if (theClass.equals(CodeSystem.class)) {
|
||||
return (T) myCodeSystems.get(theUri);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
|
||||
return myStructureDefinitions.get(theUrl);
|
||||
}
|
||||
@Override
|
||||
public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) {
|
||||
return myStructureDefinitions.get(theUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureDefinition generateSnapshot(StructureDefinition theInput, String theUrl, String theProfileName) {
|
||||
|
@ -188,8 +188,13 @@ public class PrePopulatedValidationSupport implements IValidationSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
return null;
|
||||
}
|
||||
public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,6 +96,11 @@ public class SnapshotGeneratingValidationSupport implements IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private class MyProfileKnowledgeWorker implements ProfileUtilities.ProfileKnowledgeProvider {
|
||||
@Override
|
||||
public boolean isDatatype(String typeSimple) {
|
||||
|
|
|
@ -159,6 +159,16 @@ public class ValidationSupportChain implements IValidationSupport {
|
|||
return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookupCodeResult lookupCode(FhirContext theContext, String theSystem, String theCode) {
|
||||
for (IValidationSupport next : myChain) {
|
||||
if (next.isCodeSystemSupported(theContext, theSystem)) {
|
||||
return next.lookupCode(theContext, theSystem, theCode);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureDefinition> fetchAllStructureDefinitions(FhirContext theContext) {
|
||||
ArrayList<StructureDefinition> retVal = new ArrayList<>();
|
||||
|
|
|
@ -52,7 +52,15 @@
|
|||
the user has not explicitly configured a preference.
|
||||
]]>
|
||||
</action>
|
||||
<action type="add">
|
||||
<action type="change">
|
||||
<![CDATA[
|
||||
<b>Breaking Change</b>:
|
||||
The JPA $upload-external-code-system operation has been moved from being a
|
||||
server level operation (i.e. called on the root of the server) to being
|
||||
a type level operation (i.e. called on the CodeSystem type).
|
||||
]]>
|
||||
</action>
|
||||
<action type="add">
|
||||
A new interceptor called
|
||||
<![CDATA[<code>ConsentInterceptor</code>]]> has been added. This interceptor allows
|
||||
JPA based servers to make appropriate consent decisions related to resources that
|
||||
|
@ -340,6 +348,12 @@
|
|||
a narrative on an untitled DiagnosticReport were fixed. Thanks to GitHub
|
||||
user @navyflower for reporting!
|
||||
</action>
|
||||
<action type="add">
|
||||
A new attribute has been added to the @Operation annotation called
|
||||
<![CDATA[<code>typeName</code>]]>. This annotation can be used to specify a
|
||||
type for an operation declared on a plain provider without needing to use
|
||||
a specific version of the FHIR structures.
|
||||
</action>
|
||||
</release>
|
||||
<release version="3.8.0" date="2019-05-30" description="Hippo">
|
||||
<action type="fix">
|
||||
|
|
Loading…
Reference in New Issue