Merge branch 'master' into documentOperation
This commit is contained in:
commit
8f2d3998f6
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
NOTE: Before filing a ticket, please see the following URL:
|
||||||
|
https://github.com/jamesagnew/hapi-fhir/wiki/Getting-Help
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Environment (please complete the following information):**
|
||||||
|
- HAPI FHIR Version
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
|
@ -17,3 +17,5 @@ A demonstration of this project is available here:
|
||||||
http://hapi.fhir.org/
|
http://hapi.fhir.org/
|
||||||
|
|
||||||
This project is Open Source, licensed under the Apache Software License 2.0.
|
This project is Open Source, licensed under the Apache Software License 2.0.
|
||||||
|
|
||||||
|
Please see [this wiki page](https://github.com/jamesagnew/hapi-fhir/wiki/Getting-Help) for information on where to get help with HAPI FHIR. Please see [Smile CDR](https://smilecdr.com) for information on commercial support.
|
||||||
|
|
|
@ -1,7 +1,34 @@
|
||||||
package ca.uhn.fhir.context;
|
package ca.uhn.fhir.context;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.api.AddProfileTagEnum;
|
||||||
|
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
||||||
|
import ca.uhn.fhir.fluentpath.IFluentPath;
|
||||||
|
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||||
|
import ca.uhn.fhir.model.api.IElement;
|
||||||
|
import ca.uhn.fhir.model.api.IFhirVersion;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.view.ViewGenerator;
|
||||||
|
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
|
import ca.uhn.fhir.parser.*;
|
||||||
|
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
|
||||||
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
|
import ca.uhn.fhir.util.VersionUtil;
|
||||||
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
|
@ -23,26 +50,6 @@ import java.lang.reflect.Method;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.api.AddProfileTagEnum;
|
|
||||||
import ca.uhn.fhir.context.support.IContextValidationSupport;
|
|
||||||
import ca.uhn.fhir.fluentpath.IFluentPath;
|
|
||||||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
|
||||||
import ca.uhn.fhir.model.api.*;
|
|
||||||
import ca.uhn.fhir.model.view.ViewGenerator;
|
|
||||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
|
||||||
import ca.uhn.fhir.parser.*;
|
|
||||||
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
|
|
||||||
import ca.uhn.fhir.rest.client.api.*;
|
|
||||||
import ca.uhn.fhir.util.*;
|
|
||||||
import ca.uhn.fhir.validation.FhirValidator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The FHIR context is the central starting point for the use of the HAPI FHIR API. It should be created once, and then
|
* The FHIR context is the central starting point for the use of the HAPI FHIR API. It should be created once, and then
|
||||||
* used as a factory for various other types of objects (parsers, clients, etc.).
|
* used as a factory for various other types of objects (parsers, clients, etc.).
|
||||||
|
@ -68,6 +75,7 @@ public class FhirContext {
|
||||||
|
|
||||||
private static final List<Class<? extends IBaseResource>> EMPTY_LIST = Collections.emptyList();
|
private static final List<Class<? extends IBaseResource>> EMPTY_LIST = Collections.emptyList();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContext.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirContext.class);
|
||||||
|
private final IFhirVersion myVersion;
|
||||||
private AddProfileTagEnum myAddProfileTagWhenEncoding = AddProfileTagEnum.ONLY_FOR_CUSTOM;
|
private AddProfileTagEnum myAddProfileTagWhenEncoding = AddProfileTagEnum.ONLY_FOR_CUSTOM;
|
||||||
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
private volatile Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myClassToElementDefinition = Collections.emptyMap();
|
||||||
private ArrayList<Class<? extends IBase>> myCustomTypes;
|
private ArrayList<Class<? extends IBase>> myCustomTypes;
|
||||||
|
@ -87,9 +95,6 @@ public class FhirContext {
|
||||||
private volatile IRestfulClientFactory myRestfulClientFactory;
|
private volatile IRestfulClientFactory myRestfulClientFactory;
|
||||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||||
private IContextValidationSupport<?, ?, ?, ?, ?, ?> myValidationSupport;
|
private IContextValidationSupport<?, ?, ?, ?, ?, ?> myValidationSupport;
|
||||||
|
|
||||||
private final IFhirVersion myVersion;
|
|
||||||
|
|
||||||
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -208,6 +213,30 @@ public class FhirContext {
|
||||||
return myAddProfileTagWhenEncoding;
|
return myAddProfileTagWhenEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When encoding resources, this setting configures the parser to include
|
||||||
|
* an entry in the resource's metadata section which indicates which profile(s) the
|
||||||
|
* resource claims to conform to. The default is {@link AddProfileTagEnum#ONLY_FOR_CUSTOM}.
|
||||||
|
* <p>
|
||||||
|
* This feature is intended for situations where custom resource types are being used,
|
||||||
|
* avoiding the need to manually add profile declarations for these custom types.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* See <a href="http://jamesagnew.gihhub.io/hapi-fhir/doc_extensions.html">Profiling and Extensions</a>
|
||||||
|
* for more information on using custom types.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Note that this feature automatically adds the profile, but leaves any profile tags
|
||||||
|
* which have been manually added in place as well.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param theAddProfileTagWhenEncoding The add profile mode (must not be <code>null</code>)
|
||||||
|
*/
|
||||||
|
public void setAddProfileTagWhenEncoding(AddProfileTagEnum theAddProfileTagWhenEncoding) {
|
||||||
|
Validate.notNull(theAddProfileTagWhenEncoding, "theAddProfileTagWhenEncoding must not be null");
|
||||||
|
myAddProfileTagWhenEncoding = theAddProfileTagWhenEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
Collection<RuntimeResourceDefinition> getAllResourceDefinitions() {
|
Collection<RuntimeResourceDefinition> getAllResourceDefinitions() {
|
||||||
validateInitialized();
|
validateInitialized();
|
||||||
return myNameToResourceDefinition.values();
|
return myNameToResourceDefinition.values();
|
||||||
|
@ -249,7 +278,9 @@ public class FhirContext {
|
||||||
return myNameToElementDefinition.get(theElementName.toLowerCase());
|
return myNameToElementDefinition.get(theElementName.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For unit tests only */
|
/**
|
||||||
|
* For unit tests only
|
||||||
|
*/
|
||||||
int getElementDefinitionCount() {
|
int getElementDefinitionCount() {
|
||||||
validateInitialized();
|
validateInitialized();
|
||||||
return myClassToElementDefinition.size();
|
return myClassToElementDefinition.size();
|
||||||
|
@ -274,10 +305,22 @@ public class FhirContext {
|
||||||
return myLocalizer;
|
return myLocalizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||||
|
* caution
|
||||||
|
*/
|
||||||
|
public void setLocalizer(HapiLocalizer theMessages) {
|
||||||
|
myLocalizer = theMessages;
|
||||||
|
}
|
||||||
|
|
||||||
public INarrativeGenerator getNarrativeGenerator() {
|
public INarrativeGenerator getNarrativeGenerator() {
|
||||||
return myNarrativeGenerator;
|
return myNarrativeGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNarrativeGenerator(INarrativeGenerator theNarrativeGenerator) {
|
||||||
|
myNarrativeGenerator = theNarrativeGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the parser options object which will be used to supply default
|
* Returns the parser options object which will be used to supply default
|
||||||
* options to newly created parsers
|
* options to newly created parsers
|
||||||
|
@ -288,6 +331,17 @@ public class FhirContext {
|
||||||
return myParserOptions;
|
return myParserOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the parser options object which will be used to supply default
|
||||||
|
* options to newly created parsers
|
||||||
|
*
|
||||||
|
* @param theParserOptions The parser options object - Must not be <code>null</code>
|
||||||
|
*/
|
||||||
|
public void setParserOptions(ParserOptions theParserOptions) {
|
||||||
|
Validate.notNull(theParserOptions, "theParserOptions must not be null");
|
||||||
|
myParserOptions = theParserOptions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configured performance options
|
* Get the configured performance options
|
||||||
*/
|
*/
|
||||||
|
@ -295,6 +349,32 @@ public class FhirContext {
|
||||||
return myPerformanceOptions;
|
return myPerformanceOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Return an unmodifiable collection containing all known resource definitions
|
||||||
|
// */
|
||||||
|
// public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
|
||||||
|
//
|
||||||
|
// Set<Class<? extends IBase>> datatypes = Collections.emptySet();
|
||||||
|
// Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> existing = Collections.emptyMap();
|
||||||
|
// HashMap<String, Class<? extends IBaseResource>> types = new HashMap<String, Class<? extends IBaseResource>>();
|
||||||
|
// ModelScanner.scanVersionPropertyFile(datatypes, types, myVersion.getVersion(), existing);
|
||||||
|
// for (int next : types.)
|
||||||
|
//
|
||||||
|
// return Collections.unmodifiableCollection(myIdToResourceDefinition.values());
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the configured performance options
|
||||||
|
*
|
||||||
|
* @see PerformanceOptionsEnum for a list of available options
|
||||||
|
*/
|
||||||
|
public void setPerformanceOptions(Collection<PerformanceOptionsEnum> theOptions) {
|
||||||
|
myPerformanceOptions.clear();
|
||||||
|
if (theOptions != null) {
|
||||||
|
myPerformanceOptions.addAll(theOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||||
* for extending the core library.
|
* for extending the core library.
|
||||||
|
@ -359,8 +439,12 @@ public class FhirContext {
|
||||||
* <p>
|
* <p>
|
||||||
* Note that this method is case insensitive!
|
* Note that this method is case insensitive!
|
||||||
* </p>
|
* </p>
|
||||||
|
*
|
||||||
|
* @throws DataFormatException If the resource name is not known
|
||||||
*/
|
*/
|
||||||
public RuntimeResourceDefinition getResourceDefinition(String theResourceName) {
|
// Multiple spots in HAPI FHIR and Smile CDR depend on DataFormatException being
|
||||||
|
// thrown by this method, don't change that.
|
||||||
|
public RuntimeResourceDefinition getResourceDefinition(String theResourceName) throws DataFormatException {
|
||||||
validateInitialized();
|
validateInitialized();
|
||||||
Validate.notBlank(theResourceName, "theResourceName must not be blank");
|
Validate.notBlank(theResourceName, "theResourceName must not be blank");
|
||||||
|
|
||||||
|
@ -380,20 +464,6 @@ public class FhirContext {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Return an unmodifiable collection containing all known resource definitions
|
|
||||||
// */
|
|
||||||
// public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
|
|
||||||
//
|
|
||||||
// Set<Class<? extends IBase>> datatypes = Collections.emptySet();
|
|
||||||
// Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> existing = Collections.emptyMap();
|
|
||||||
// HashMap<String, Class<? extends IBaseResource>> types = new HashMap<String, Class<? extends IBaseResource>>();
|
|
||||||
// ModelScanner.scanVersionPropertyFile(datatypes, types, myVersion.getVersion(), existing);
|
|
||||||
// for (int next : types.)
|
|
||||||
//
|
|
||||||
// return Collections.unmodifiableCollection(myIdToResourceDefinition.values());
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||||
* for extending the core library.
|
* for extending the core library.
|
||||||
|
@ -412,6 +482,36 @@ public class FhirContext {
|
||||||
return myIdToResourceDefinition.values();
|
return myIdToResourceDefinition.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an unmodifiable set containing all resource names known to this
|
||||||
|
* context
|
||||||
|
*/
|
||||||
|
public Set<String> getResourceNames() {
|
||||||
|
Set<String> resourceNames = new HashSet<>();
|
||||||
|
|
||||||
|
if (myNameToResourceDefinition.isEmpty()) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
try {
|
||||||
|
props.load(myVersion.getFhirVersionPropertiesFile());
|
||||||
|
} catch (IOException theE) {
|
||||||
|
throw new ConfigurationException("Failed to load version properties file");
|
||||||
|
}
|
||||||
|
Enumeration<?> propNames = props.propertyNames();
|
||||||
|
while (propNames.hasMoreElements()) {
|
||||||
|
String next = (String) propNames.nextElement();
|
||||||
|
if (next.startsWith("resource.")) {
|
||||||
|
resourceNames.add(next.substring("resource.".length()).trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RuntimeResourceDefinition next : myNameToResourceDefinition.values()) {
|
||||||
|
resourceNames.add(next.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableSet(resourceNames);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the restful client factory. If no factory has been set, this will be initialized with
|
* Get the restful client factory. If no factory has been set, this will be initialized with
|
||||||
* a new ApacheRestfulClientFactory.
|
* a new ApacheRestfulClientFactory.
|
||||||
|
@ -429,6 +529,16 @@ public class FhirContext {
|
||||||
return myRestfulClientFactory;
|
return myRestfulClientFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the restful client factory
|
||||||
|
*
|
||||||
|
* @param theRestfulClientFactory
|
||||||
|
*/
|
||||||
|
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
|
||||||
|
Validate.notNull(theRestfulClientFactory, "theRestfulClientFactory must not be null");
|
||||||
|
this.myRestfulClientFactory = theRestfulClientFactory;
|
||||||
|
}
|
||||||
|
|
||||||
public RuntimeChildUndeclaredExtensionDefinition getRuntimeChildUndeclaredExtensionDefinition() {
|
public RuntimeChildUndeclaredExtensionDefinition getRuntimeChildUndeclaredExtensionDefinition() {
|
||||||
validateInitialized();
|
validateInitialized();
|
||||||
return myRuntimeChildUndeclaredExtensionDefinition;
|
return myRuntimeChildUndeclaredExtensionDefinition;
|
||||||
|
@ -448,6 +558,15 @@ public class FhirContext {
|
||||||
return myValidationSupport;
|
return myValidationSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the validation support module to use for this context. The validation support module
|
||||||
|
* is used to supply underlying infrastructure such as conformance resources (StructureDefinition, ValueSet, etc)
|
||||||
|
* as well as to provide terminology services to modules such as the validator and FluentPath executor
|
||||||
|
*/
|
||||||
|
public void setValidationSupport(IContextValidationSupport<?, ?, ?, ?, ?, ?> theValidationSupport) {
|
||||||
|
myValidationSupport = theValidationSupport;
|
||||||
|
}
|
||||||
|
|
||||||
public IFhirVersion getVersion() {
|
public IFhirVersion getVersion() {
|
||||||
return myVersion;
|
return myVersion;
|
||||||
}
|
}
|
||||||
|
@ -519,13 +638,10 @@ public class FhirContext {
|
||||||
* without incurring any performance penalty
|
* without incurring any performance penalty
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theClientType
|
* @param theClientType The client type, which is an interface type to be instantiated
|
||||||
* The client type, which is an interface type to be instantiated
|
* @param theServerBase The URL of the base for the restful FHIR server to connect to
|
||||||
* @param theServerBase
|
|
||||||
* The URL of the base for the restful FHIR server to connect to
|
|
||||||
* @return A newly created client
|
* @return A newly created client
|
||||||
* @throws ConfigurationException
|
* @throws ConfigurationException If the interface type is not an interface
|
||||||
* If the interface type is not an interface
|
|
||||||
*/
|
*/
|
||||||
public <T extends IRestfulClient> T newRestfulClient(Class<T> theClientType, String theServerBase) {
|
public <T extends IRestfulClient> T newRestfulClient(Class<T> theClientType, String theServerBase) {
|
||||||
return getRestfulClientFactory().newClient(theClientType, theServerBase);
|
return getRestfulClientFactory().newClient(theClientType, theServerBase);
|
||||||
|
@ -541,8 +657,7 @@ public class FhirContext {
|
||||||
* without incurring any performance penalty
|
* without incurring any performance penalty
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theServerBase
|
* @param theServerBase The URL of the base for the restful FHIR server to connect to
|
||||||
* The URL of the base for the restful FHIR server to connect to
|
|
||||||
*/
|
*/
|
||||||
public IGenericClient newRestfulGenericClient(String theServerBase) {
|
public IGenericClient newRestfulGenericClient(String theServerBase) {
|
||||||
return getRestfulClientFactory().newGenericClient(theServerBase);
|
return getRestfulClientFactory().newGenericClient(theServerBase);
|
||||||
|
@ -593,8 +708,7 @@ public class FhirContext {
|
||||||
* threads are able to call any methods on this context.
|
* threads are able to call any methods on this context.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theType
|
* @param theType The custom type to add (must not be <code>null</code>)
|
||||||
* The custom type to add (must not be <code>null</code>)
|
|
||||||
*/
|
*/
|
||||||
public void registerCustomType(Class<? extends IBase> theType) {
|
public void registerCustomType(Class<? extends IBase> theType) {
|
||||||
Validate.notNull(theType, "theType must not be null");
|
Validate.notNull(theType, "theType must not be null");
|
||||||
|
@ -613,8 +727,7 @@ public class FhirContext {
|
||||||
* threads are able to call any methods on this context.
|
* threads are able to call any methods on this context.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theTypes
|
* @param theTypes The custom types to add (must not be <code>null</code> or contain null elements in the collection)
|
||||||
* The custom types to add (must not be <code>null</code> or contain null elements in the collection)
|
|
||||||
*/
|
*/
|
||||||
public void registerCustomTypes(Collection<Class<? extends IBase>> theTypes) {
|
public void registerCustomTypes(Collection<Class<? extends IBase>> theTypes) {
|
||||||
Validate.notNull(theTypes, "theTypes must not be null");
|
Validate.notNull(theTypes, "theTypes must not be null");
|
||||||
|
@ -698,31 +811,6 @@ public class FhirContext {
|
||||||
return classToElementDefinition;
|
return classToElementDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* When encoding resources, this setting configures the parser to include
|
|
||||||
* an entry in the resource's metadata section which indicates which profile(s) the
|
|
||||||
* resource claims to conform to. The default is {@link AddProfileTagEnum#ONLY_FOR_CUSTOM}.
|
|
||||||
* <p>
|
|
||||||
* This feature is intended for situations where custom resource types are being used,
|
|
||||||
* avoiding the need to manually add profile declarations for these custom types.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* See <a href="http://jamesagnew.gihhub.io/hapi-fhir/doc_extensions.html">Profiling and Extensions</a>
|
|
||||||
* for more information on using custom types.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Note that this feature automatically adds the profile, but leaves any profile tags
|
|
||||||
* which have been manually added in place as well.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param theAddProfileTagWhenEncoding
|
|
||||||
* The add profile mode (must not be <code>null</code>)
|
|
||||||
*/
|
|
||||||
public void setAddProfileTagWhenEncoding(AddProfileTagEnum theAddProfileTagWhenEncoding) {
|
|
||||||
Validate.notNull(theAddProfileTagWhenEncoding, "theAddProfileTagWhenEncoding must not be null");
|
|
||||||
myAddProfileTagWhenEncoding = theAddProfileTagWhenEncoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the default type which will be used when parsing a resource that is found to be
|
* Sets the default type which will be used when parsing a resource that is found to be
|
||||||
* of the given profile.
|
* of the given profile.
|
||||||
|
@ -733,11 +821,9 @@ public class FhirContext {
|
||||||
* the <code>MyPatient</code> type will be used unless otherwise specified.
|
* the <code>MyPatient</code> type will be used unless otherwise specified.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theProfile
|
* @param theProfile The profile string, e.g. <code>"http://example.com/some_patient_profile"</code>. Must not be
|
||||||
* The profile string, e.g. <code>"http://example.com/some_patient_profile"</code>. Must not be
|
|
||||||
* <code>null</code> or empty.
|
* <code>null</code> or empty.
|
||||||
* @param theClass
|
* @param theClass The resource type, or <code>null</code> to clear any existing type
|
||||||
* The resource type, or <code>null</code> to clear any existing type
|
|
||||||
*/
|
*/
|
||||||
public void setDefaultTypeForProfile(String theProfile, Class<? extends IBaseResource> theClass) {
|
public void setDefaultTypeForProfile(String theProfile, Class<? extends IBaseResource> theClass) {
|
||||||
Validate.notBlank(theProfile, "theProfile must not be null or empty");
|
Validate.notBlank(theProfile, "theProfile must not be null or empty");
|
||||||
|
@ -748,53 +834,16 @@ public class FhirContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
|
||||||
* caution
|
|
||||||
*/
|
|
||||||
public void setLocalizer(HapiLocalizer theMessages) {
|
|
||||||
myLocalizer = theMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNarrativeGenerator(INarrativeGenerator theNarrativeGenerator) {
|
|
||||||
myNarrativeGenerator = theNarrativeGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a parser error handler to use by default on all parsers
|
* Sets a parser error handler to use by default on all parsers
|
||||||
*
|
*
|
||||||
* @param theParserErrorHandler
|
* @param theParserErrorHandler The error handler
|
||||||
* The error handler
|
|
||||||
*/
|
*/
|
||||||
public void setParserErrorHandler(IParserErrorHandler theParserErrorHandler) {
|
public void setParserErrorHandler(IParserErrorHandler theParserErrorHandler) {
|
||||||
Validate.notNull(theParserErrorHandler, "theParserErrorHandler must not be null");
|
Validate.notNull(theParserErrorHandler, "theParserErrorHandler must not be null");
|
||||||
myParserErrorHandler = theParserErrorHandler;
|
myParserErrorHandler = theParserErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the parser options object which will be used to supply default
|
|
||||||
* options to newly created parsers
|
|
||||||
*
|
|
||||||
* @param theParserOptions
|
|
||||||
* The parser options object - Must not be <code>null</code>
|
|
||||||
*/
|
|
||||||
public void setParserOptions(ParserOptions theParserOptions) {
|
|
||||||
Validate.notNull(theParserOptions, "theParserOptions must not be null");
|
|
||||||
myParserOptions = theParserOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the configured performance options
|
|
||||||
*
|
|
||||||
* @see PerformanceOptionsEnum for a list of available options
|
|
||||||
*/
|
|
||||||
public void setPerformanceOptions(Collection<PerformanceOptionsEnum> theOptions) {
|
|
||||||
myPerformanceOptions.clear();
|
|
||||||
if (theOptions != null) {
|
|
||||||
myPerformanceOptions.addAll(theOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the configured performance options
|
* Sets the configured performance options
|
||||||
*
|
*
|
||||||
|
@ -808,26 +857,7 @@ public class FhirContext {
|
||||||
setPerformanceOptions(asList);
|
setPerformanceOptions(asList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@SuppressWarnings({"cast"})
|
||||||
* Set the restful client factory
|
|
||||||
*
|
|
||||||
* @param theRestfulClientFactory
|
|
||||||
*/
|
|
||||||
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
|
|
||||||
Validate.notNull(theRestfulClientFactory, "theRestfulClientFactory must not be null");
|
|
||||||
this.myRestfulClientFactory = theRestfulClientFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the validation support module to use for this context. The validation support module
|
|
||||||
* is used to supply underlying infrastructure such as conformance resources (StructureDefinition, ValueSet, etc)
|
|
||||||
* as well as to provide terminology services to modules such as the validator and FluentPath executor
|
|
||||||
*/
|
|
||||||
public void setValidationSupport(IContextValidationSupport<?, ?, ?, ?, ?, ?> theValidationSupport) {
|
|
||||||
myValidationSupport = theValidationSupport;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "cast" })
|
|
||||||
private List<Class<? extends IElement>> toElementList(Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
private List<Class<? extends IElement>> toElementList(Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
||||||
if (theResourceTypes == null) {
|
if (theResourceTypes == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -858,13 +888,6 @@ public class FhirContext {
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2);
|
return new FhirContext(FhirVersionEnum.DSTU2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2 DSTU2} (2016 May DSTU3 Snapshot)
|
|
||||||
*/
|
|
||||||
public static FhirContext forDstu2_1() {
|
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_HL7ORG DSTU2} (using the Reference
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_HL7ORG DSTU2} (using the Reference
|
||||||
* Implementation Structures)
|
* Implementation Structures)
|
||||||
|
@ -873,6 +896,13 @@ public class FhirContext {
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
return new FhirContext(FhirVersionEnum.DSTU2_HL7ORG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2 DSTU2} (2016 May DSTU3 Snapshot)
|
||||||
|
*/
|
||||||
|
public static FhirContext forDstu2_1() {
|
||||||
|
return new FhirContext(FhirVersionEnum.DSTU2_1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU3 DSTU3}
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU3 DSTU3}
|
||||||
*
|
*
|
||||||
|
@ -891,7 +921,6 @@ public class FhirContext {
|
||||||
return new FhirContext(FhirVersionEnum.R4);
|
return new FhirContext(FhirVersionEnum.R4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Collection<Class<? extends IBaseResource>> toCollection(Class<? extends IBaseResource> theResourceType) {
|
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<Class<? extends IBaseResource>>(1);
|
||||||
retVal.add(theResourceType);
|
retVal.add(theResourceType);
|
||||||
|
@ -909,34 +938,4 @@ public class FhirContext {
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an unmodifiable set containing all resource names known to this
|
|
||||||
* context
|
|
||||||
*/
|
|
||||||
public Set<String> getResourceNames() {
|
|
||||||
Set<String> resourceNames= new HashSet<>();
|
|
||||||
|
|
||||||
if (myNameToResourceDefinition.isEmpty()) {
|
|
||||||
Properties props = new Properties();
|
|
||||||
try {
|
|
||||||
props.load(myVersion.getFhirVersionPropertiesFile());
|
|
||||||
} catch (IOException theE) {
|
|
||||||
throw new ConfigurationException("Failed to load version properties file");
|
|
||||||
}
|
|
||||||
Enumeration<?> propNames = props.propertyNames();
|
|
||||||
while (propNames.hasMoreElements()){
|
|
||||||
String next = (String) propNames.nextElement();
|
|
||||||
if (next.startsWith("resource.")) {
|
|
||||||
resourceNames.add(next.substring("resource.".length()).trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (RuntimeResourceDefinition next : myNameToResourceDefinition.values()) {
|
|
||||||
resourceNames.add(next.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableSet(resourceNames);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,17 @@ public class UrlPathTokenizer {
|
||||||
return myTok.hasMoreTokens();
|
return myTok.hasMoreTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String nextToken() {
|
/**
|
||||||
return UrlUtil.unescape(myTok.nextToken());
|
* Returns the next portion. Any URL-encoding is undone, but we will
|
||||||
|
* HTML encode the < and " marks since they are both
|
||||||
|
* not useful un URL paths in FHIR and potentially represent injection
|
||||||
|
* attacks.
|
||||||
|
*
|
||||||
|
* @see UrlUtil#sanitizeUrlPart(String)
|
||||||
|
* @see UrlUtil#unescape(String)
|
||||||
|
*/
|
||||||
|
public String nextTokenUnescapedAndSanitized() {
|
||||||
|
return UrlUtil.sanitizeUrlPart(UrlUtil.unescape(myTok.nextToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class UrlUtil {
|
||||||
return theExtensionUrl;
|
return theExtensionUrl;
|
||||||
}
|
}
|
||||||
if (theExtensionUrl == null) {
|
if (theExtensionUrl == null) {
|
||||||
return theExtensionUrl;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parentLastSlashIdx = theParentExtensionUrl.lastIndexOf('/');
|
int parentLastSlashIdx = theParentExtensionUrl.lastIndexOf('/');
|
||||||
|
@ -119,6 +119,18 @@ public class UrlUtil {
|
||||||
return value.startsWith("http://") || value.startsWith("https://");
|
return value.startsWith("http://") || value.startsWith("https://");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isNeedsSanitization(String theString) {
|
||||||
|
if (theString != null) {
|
||||||
|
for (int i = 0; i < theString.length(); i++) {
|
||||||
|
char nextChar = theString.charAt(i);
|
||||||
|
if (nextChar == '<' || nextChar == '"') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isValid(String theUrl) {
|
public static boolean isValid(String theUrl) {
|
||||||
if (theUrl == null || theUrl.length() < 8) {
|
if (theUrl == null || theUrl.length() < 8) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -164,7 +176,7 @@ public class UrlUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String[]> parseQueryString(String theQueryString) {
|
public static Map<String, String[]> parseQueryString(String theQueryString) {
|
||||||
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
|
HashMap<String, List<String>> map = new HashMap<>();
|
||||||
parseQueryString(theQueryString, map);
|
parseQueryString(theQueryString, map);
|
||||||
return toQueryStringMap(map);
|
return toQueryStringMap(map);
|
||||||
}
|
}
|
||||||
|
@ -197,17 +209,13 @@ public class UrlUtil {
|
||||||
nextKey = unescape(nextKey);
|
nextKey = unescape(nextKey);
|
||||||
nextValue = unescape(nextValue);
|
nextValue = unescape(nextValue);
|
||||||
|
|
||||||
List<String> list = map.get(nextKey);
|
List<String> list = map.computeIfAbsent(nextKey, k -> new ArrayList<>());
|
||||||
if (list == null) {
|
|
||||||
list = new ArrayList<>();
|
|
||||||
map.put(nextKey, list);
|
|
||||||
}
|
|
||||||
list.add(nextValue);
|
list.add(nextValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String[]> parseQueryStrings(String... theQueryString) {
|
public static Map<String, String[]> parseQueryStrings(String... theQueryString) {
|
||||||
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
|
HashMap<String, List<String>> map = new HashMap<>();
|
||||||
for (String next : theQueryString) {
|
for (String next : theQueryString) {
|
||||||
parseQueryString(next, map);
|
parseQueryString(next, map);
|
||||||
}
|
}
|
||||||
|
@ -222,7 +230,6 @@ public class UrlUtil {
|
||||||
* <li>[Resource Type]/[Resource ID]/_history/[Version ID]
|
* <li>[Resource Type]/[Resource ID]/_history/[Version ID]
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
//@formatter:on
|
|
||||||
public static UrlParts parseUrl(String theUrl) {
|
public static UrlParts parseUrl(String theUrl) {
|
||||||
String url = theUrl;
|
String url = theUrl;
|
||||||
UrlParts retVal = new UrlParts();
|
UrlParts retVal = new UrlParts();
|
||||||
|
@ -243,7 +250,7 @@ public class UrlUtil {
|
||||||
retVal.setVersionId(id.getVersionIdPart());
|
retVal.setVersionId(id.getVersionIdPart());
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
if (url.matches("\\/[a-zA-Z]+\\?.*")) {
|
if (url.matches("/[a-zA-Z]+\\?.*")) {
|
||||||
url = url.substring(1);
|
url = url.substring(1);
|
||||||
}
|
}
|
||||||
int nextStart = 0;
|
int nextStart = 0;
|
||||||
|
@ -282,12 +289,47 @@ public class UrlUtil {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//@formatter:off
|
/**
|
||||||
|
* This method specifically HTML-encodes the " and
|
||||||
|
* < characters in order to prevent injection attacks
|
||||||
|
*/
|
||||||
|
public static String sanitizeUrlPart(String theString) {
|
||||||
|
if (theString == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needsSanitization = isNeedsSanitization(theString);
|
||||||
|
|
||||||
|
if (needsSanitization) {
|
||||||
|
// Ok, we're sanitizing
|
||||||
|
StringBuilder buffer = new StringBuilder(theString.length() + 10);
|
||||||
|
for (int j = 0; j < theString.length(); j++) {
|
||||||
|
|
||||||
|
char nextChar = theString.charAt(j);
|
||||||
|
switch (nextChar) {
|
||||||
|
case '"':
|
||||||
|
buffer.append(""");
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
buffer.append("<");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buffer.append(nextChar);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // for build escaped string
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return theString;
|
||||||
|
}
|
||||||
|
|
||||||
private static Map<String, String[]> toQueryStringMap(HashMap<String, List<String>> map) {
|
private static Map<String, String[]> toQueryStringMap(HashMap<String, List<String>> map) {
|
||||||
HashMap<String, String[]> retVal = new HashMap<String, String[]>();
|
HashMap<String, String[]> retVal = new HashMap<>();
|
||||||
for (Entry<String, List<String>> nextEntry : map.entrySet()) {
|
for (Entry<String, List<String>> nextEntry : map.entrySet()) {
|
||||||
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[nextEntry.getValue().size()]));
|
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[0]));
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,13 @@
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</logger>
|
</logger>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
It's useful to have this log when uploading big terminologies
|
||||||
|
-->
|
||||||
|
<logger name="ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl" additivity="false" level="info">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</logger>
|
||||||
|
|
||||||
|
|
||||||
<root level="warn">
|
<root level="warn">
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Object execute() {
|
public Object execute() {
|
||||||
if (myOperationName != null && myOperationName.equals(Constants.EXTOP_PROCESS_MESSAGE)) {
|
if (myOperationName != null && myOperationName.equals(Constants.EXTOP_PROCESS_MESSAGE) && myMsgBundle != null) {
|
||||||
Map<String, List<String>> urlParams = new LinkedHashMap<String, List<String>>();
|
Map<String, List<String>> urlParams = new LinkedHashMap<String, List<String>>();
|
||||||
// Set Url parameter Async and Response-Url
|
// Set Url parameter Async and Response-Url
|
||||||
if (myIsAsync != null) {
|
if (myIsAsync != null) {
|
||||||
|
|
|
@ -57,17 +57,6 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
||||||
private IIdType myForceResourceId;
|
private IIdType myForceResourceId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, Map<String, List<String>> theParams, String... theUrlPath) {
|
|
||||||
super(theContext);
|
|
||||||
myResource = theResource;
|
|
||||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
|
||||||
myResources = null;
|
|
||||||
myContents = null;
|
|
||||||
myParams = theParams;
|
|
||||||
myBundleType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, String theUrlPath) {
|
public BaseHttpClientInvocationWithContents(FhirContext theContext, IBaseResource theResource, String theUrlPath) {
|
||||||
super(theContext);
|
super(theContext);
|
||||||
myResource = theResource;
|
myResource = theResource;
|
||||||
|
@ -105,17 +94,6 @@ abstract class BaseHttpClientInvocationWithContents extends BaseHttpClientInvoca
|
||||||
myBundleType = null;
|
myBundleType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseHttpClientInvocationWithContents(FhirContext theContext, String theContents, Map<String, List<String>> theParams, String... theUrlPath) {
|
|
||||||
super(theContext);
|
|
||||||
myResource = null;
|
|
||||||
myUrlPath = StringUtils.join(theUrlPath, '/');
|
|
||||||
myResources = null;
|
|
||||||
myContents = theContents;
|
|
||||||
myParams = theParams;
|
|
||||||
myBundleType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) throws DataFormatException {
|
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) throws DataFormatException {
|
||||||
StringBuilder url = new StringBuilder();
|
StringBuilder url = new StringBuilder();
|
||||||
|
|
|
@ -1301,20 +1301,24 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't keep duplicate tags
|
|
||||||
Set<TagDefinition> allDefsPresent = new HashSet<>();
|
|
||||||
theEntity.getTags().removeIf(theResourceTag -> !allDefsPresent.add(theResourceTag.getTag()));
|
|
||||||
|
|
||||||
// Remove any tags that have been removed
|
|
||||||
for (ResourceTag next : allTagsOld) {
|
|
||||||
if (!allDefs.contains(next)) {
|
|
||||||
if (shouldDroppedTagBeRemovedOnUpdate(theRequest, next)) {
|
|
||||||
theEntity.getTags().remove(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<ResourceTag> allTagsNew = getAllTagDefinitions(theEntity);
|
Set<ResourceTag> allTagsNew = getAllTagDefinitions(theEntity);
|
||||||
|
Set<TagDefinition> allDefsPresent = new HashSet<>();
|
||||||
|
allTagsNew.forEach(tag -> {
|
||||||
|
|
||||||
|
// Don't keep duplicate tags
|
||||||
|
if (!allDefsPresent.add(tag.getTag())) {
|
||||||
|
theEntity.getTags().remove(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop any tags that have been removed
|
||||||
|
if (!allDefs.contains(tag)) {
|
||||||
|
if (shouldDroppedTagBeRemovedOnUpdate(theRequest, tag)) {
|
||||||
|
theEntity.getTags().remove(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
if (!allTagsOld.equals(allTagsNew)) {
|
if (!allTagsOld.equals(allTagsNew)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -1473,6 +1477,15 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses may override to provide behaviour. Called when a pre-existing resource has been updated in the database
|
||||||
|
*
|
||||||
|
* @param theEntity The resource
|
||||||
|
*/
|
||||||
|
protected void postDelete(ResourceTable theEntity) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses may override to provide behaviour. Called when a resource has been inserted into the database for the first time.
|
* Subclasses may override to provide behaviour. Called when a resource has been inserted into the database for the first time.
|
||||||
*
|
*
|
||||||
|
@ -1483,15 +1496,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses may override to provide behaviour. Called when a pre-existing resource has been updated in the database
|
|
||||||
*
|
|
||||||
* @param theEntity The resource
|
|
||||||
*/
|
|
||||||
protected void postDelete(ResourceTable theEntity) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses may override to provide behaviour. Called when a pre-existing resource has been updated in the database
|
* Subclasses may override to provide behaviour. Called when a pre-existing resource has been updated in the database
|
||||||
*
|
*
|
||||||
|
@ -1638,7 +1642,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
resourceEncoding = history.getEncoding();
|
resourceEncoding = history.getEncoding();
|
||||||
myTagList = history.getTags();
|
myTagList = history.getTags();
|
||||||
} else if (theEntity instanceof ResourceTable) {
|
} else if (theEntity instanceof ResourceTable) {
|
||||||
ResourceTable resource = (ResourceTable)theEntity;
|
ResourceTable resource = (ResourceTable) theEntity;
|
||||||
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersion(theEntity.getId(), theEntity.getVersion());
|
ResourceHistoryTable history = myResourceHistoryTableDao.findForIdAndVersion(theEntity.getId(), theEntity.getVersion());
|
||||||
if (history == null) {
|
if (history == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1648,7 +1652,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
myTagList = resource.getTags();
|
myTagList = resource.getTags();
|
||||||
} else if (theEntity instanceof ResourceSearchView) {
|
} else if (theEntity instanceof ResourceSearchView) {
|
||||||
// This is the search View
|
// This is the search View
|
||||||
ResourceSearchView myView = (ResourceSearchView)theEntity;
|
ResourceSearchView myView = (ResourceSearchView) theEntity;
|
||||||
resourceBytes = myView.getResource();
|
resourceBytes = myView.getResource();
|
||||||
resourceEncoding = myView.getEncoding();
|
resourceEncoding = myView.getEncoding();
|
||||||
if (theTagList == null)
|
if (theTagList == null)
|
||||||
|
@ -2046,6 +2050,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
postPersist(theEntity, (T) theResource);
|
postPersist(theEntity, (T) theResource);
|
||||||
|
|
||||||
} else if (theEntity.getDeleted() != null) {
|
} else if (theEntity.getDeleted() != null) {
|
||||||
|
theEntity = myEntityManager.merge(theEntity);
|
||||||
|
|
||||||
postDelete(theEntity);
|
postDelete(theEntity);
|
||||||
|
|
||||||
|
@ -2060,10 +2065,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
*/
|
*/
|
||||||
if (theCreateNewHistoryEntry) {
|
if (theCreateNewHistoryEntry) {
|
||||||
final ResourceHistoryTable historyEntry = theEntity.toHistory();
|
final ResourceHistoryTable historyEntry = theEntity.toHistory();
|
||||||
// if (theEntity.getVersion() > 1) {
|
|
||||||
// existing = myResourceHistoryTableDao.findForIdAndVersion(theEntity.getId(), theEntity.getVersion());
|
|
||||||
// ourLog.warn("Reusing existing history entry entity {}", theEntity.getIdDt().getValue());
|
|
||||||
// }
|
|
||||||
historyEntry.setEncoding(changed.getEncoding());
|
historyEntry.setEncoding(changed.getEncoding());
|
||||||
historyEntry.setResource(changed.getResource());
|
historyEntry.setResource(changed.getResource());
|
||||||
|
|
||||||
|
@ -2195,12 +2196,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
||||||
|
|
||||||
} // if thePerformIndexing
|
} // if thePerformIndexing
|
||||||
|
|
||||||
theEntity = myEntityManager.merge(theEntity);
|
|
||||||
|
|
||||||
if (theResource != null) {
|
if (theResource != null) {
|
||||||
populateResourceIdFromEntity(theEntity, theResource);
|
populateResourceIdFromEntity(theEntity, theResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return theEntity;
|
return theEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -395,16 +395,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
"This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID");
|
"This server cannot create an entity with a user-specified numeric ID - Client should not specify an ID when creating a new resource, or should include at least one letter in the ID to force a client-defined ID");
|
||||||
}
|
}
|
||||||
createForcedIdIfNeeded(entity, theResource.getIdElement());
|
createForcedIdIfNeeded(entity, theResource.getIdElement());
|
||||||
|
|
||||||
if (entity.getForcedId() != null) {
|
|
||||||
try {
|
|
||||||
translateForcedIdToPid(getResourceName(), theResource.getIdElement().getIdPart());
|
|
||||||
throw new UnprocessableEntityException(getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "duplicateCreateForcedId", theResource.getIdElement().getIdPart()));
|
|
||||||
} catch (ResourceNotFoundException e) {
|
|
||||||
// good, this ID doesn't exist so we can create it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
|
@ -1211,7 +1201,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Note: resourcdeId will not be null or empty here, because we check it and reject requests in BaseOutcomeReturningMethodBindingWithResourceParam
|
* Note: resourceId will not be null or empty here, because we
|
||||||
|
* check it and reject requests in
|
||||||
|
* BaseOutcomeReturningMethodBindingWithResourceParam
|
||||||
*/
|
*/
|
||||||
resourceId = theResource.getIdElement();
|
resourceId = theResource.getIdElement();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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.model.dstu2.resource.MessageHeader;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
|
public class FhirResourceDaoMessageHeaderDstu2 extends FhirResourceDaoDstu2<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||||
|
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IBaseBundle throwProcessMessageNotImplemented() {
|
||||||
|
throw new NotImplementedOperationException("This operation is not yet implemented on this server");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IFhirResourceDaoMessageHeader<T extends IBaseResource> extends IFhirResourceDao<T> {
|
||||||
|
|
||||||
|
IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage);
|
||||||
|
|
||||||
|
}
|
|
@ -34,15 +34,18 @@ import java.util.List;
|
||||||
|
|
||||||
public interface ITermConceptDao extends JpaRepository<TermConcept, Long> {
|
public interface ITermConceptDao extends JpaRepository<TermConcept, Long> {
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(t) FROM TermConcept t WHERE t.myCodeSystem.myId = :cs_pid")
|
||||||
|
Integer countByCodeSystemVersion(@Param("cs_pid") Long thePid);
|
||||||
|
|
||||||
@Query("SELECT c FROM TermConcept c WHERE c.myCodeSystem = :code_system AND c.myCode = :code")
|
@Query("SELECT c FROM TermConcept c WHERE c.myCodeSystem = :code_system AND c.myCode = :code")
|
||||||
TermConcept findByCodeSystemAndCode(@Param("code_system") TermCodeSystemVersion theCodeSystem, @Param("code") String theCode);
|
TermConcept findByCodeSystemAndCode(@Param("code_system") TermCodeSystemVersion theCodeSystem, @Param("code") String theCode);
|
||||||
|
|
||||||
@Query("SELECT c FROM TermConcept c WHERE c.myCodeSystem = :code_system")
|
|
||||||
List<TermConcept> findByCodeSystemVersion(@Param("code_system") TermCodeSystemVersion theCodeSystem);
|
|
||||||
|
|
||||||
@Query("SELECT t FROM TermConcept t WHERE t.myCodeSystem.myId = :cs_pid")
|
@Query("SELECT t FROM TermConcept t WHERE t.myCodeSystem.myId = :cs_pid")
|
||||||
Slice<TermConcept> findByCodeSystemVersion(Pageable thePage, @Param("cs_pid") Long thePid);
|
Slice<TermConcept> findByCodeSystemVersion(Pageable thePage, @Param("cs_pid") Long thePid);
|
||||||
|
|
||||||
|
@Query("SELECT c FROM TermConcept c WHERE c.myCodeSystem = :code_system")
|
||||||
|
List<TermConcept> findByCodeSystemVersion(@Param("code_system") TermCodeSystemVersion theCodeSystem);
|
||||||
|
|
||||||
@Query("SELECT t FROM TermConcept t WHERE t.myIndexStatus = null")
|
@Query("SELECT t FROM TermConcept t WHERE t.myIndexStatus = null")
|
||||||
Page<TermConcept> findResourcesRequiringReindexing(Pageable thePageRequest);
|
Page<TermConcept> findResourcesRequiringReindexing(Pageable thePageRequest);
|
||||||
|
|
||||||
|
|
|
@ -32,4 +32,7 @@ public interface ITermConceptDesignationDao extends JpaRepository<TermConceptDes
|
||||||
@Query("SELECT t FROM TermConceptDesignation t WHERE t.myCodeSystemVersion.myId = :csv_pid")
|
@Query("SELECT t FROM TermConceptDesignation t WHERE t.myCodeSystemVersion.myId = :csv_pid")
|
||||||
Slice<TermConceptDesignation> findByCodeSystemVersion(Pageable thePage, @Param("csv_pid") Long thePid);
|
Slice<TermConceptDesignation> findByCodeSystemVersion(Pageable thePage, @Param("csv_pid") Long thePid);
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(t) FROM TermConceptDesignation t WHERE t.myCodeSystemVersion.myId = :csv_pid")
|
||||||
|
Integer countByCodeSystemVersion(@Param("csv_pid") Long thePid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ import java.util.Collection;
|
||||||
|
|
||||||
public interface ITermConceptParentChildLinkDao extends JpaRepository<TermConceptParentChildLink, Long> {
|
public interface ITermConceptParentChildLinkDao extends JpaRepository<TermConceptParentChildLink, Long> {
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(t) FROM TermConceptParentChildLink t WHERE t.myCodeSystem.myId = :cs_pid")
|
||||||
|
Integer countByCodeSystemVersion(@Param("cs_pid") Long thePid);
|
||||||
|
|
||||||
@Query("SELECT t.myParentPid FROM TermConceptParentChildLink t WHERE t.myChildPid = :child_pid")
|
@Query("SELECT t.myParentPid FROM TermConceptParentChildLink t WHERE t.myChildPid = :child_pid")
|
||||||
Collection<Long> findAllWithChild(@Param("child_pid") Long theConceptPid);
|
Collection<Long> findAllWithChild(@Param("child_pid") Long theConceptPid);
|
||||||
|
|
||||||
|
|
|
@ -32,4 +32,6 @@ public interface ITermConceptPropertyDao extends JpaRepository<TermConceptProper
|
||||||
@Query("SELECT t FROM TermConceptProperty t WHERE t.myCodeSystemVersion.myId = :cs_pid")
|
@Query("SELECT t FROM TermConceptProperty t WHERE t.myCodeSystemVersion.myId = :cs_pid")
|
||||||
Slice<TermConceptProperty> findByCodeSystemVersion(Pageable thePage, @Param("cs_pid") Long thePid);
|
Slice<TermConceptProperty> findByCodeSystemVersion(Pageable thePage, @Param("cs_pid") Long thePid);
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(t) FROM TermConceptProperty t WHERE t.myCodeSystemVersion.myId = :cs_pid")
|
||||||
|
Integer countByCodeSystemVersion(@Param("cs_pid") Long thePid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import org.hl7.fhir.dstu3.model.MessageHeader;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
|
public class FhirResourceDaoMessageHeaderDstu3 extends FhirResourceDaoDstu3<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||||
|
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.StringUtils;
|
import org.apache.commons.codec.binary.StringUtils;
|
||||||
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
||||||
|
@ -35,6 +36,8 @@ import org.hl7.fhir.dstu3.model.ValueSet.*;
|
||||||
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
@ -223,6 +226,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
if (vs != null) {
|
if (vs != null) {
|
||||||
ValueSet expansion = doExpand(vs);
|
ValueSet expansion = doExpand(vs);
|
||||||
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
List<ValueSetExpansionContainsComponent> contains = expansion.getExpansion().getContains();
|
||||||
|
|
||||||
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
ValidateCodeResult result = validateCodeIsInContains(contains, toStringOrNull(theSystem), toStringOrNull(theCode), theCoding, theCodeableConcept);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
if (theDisplay != null && isNotBlank(theDisplay.getValue()) && isNotBlank(result.getDisplay())) {
|
||||||
|
@ -238,6 +242,9 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
|
||||||
|
|
||||||
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
private String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
||||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
import org.hl7.fhir.r4.model.MessageHeader;
|
||||||
|
|
||||||
|
public class FhirResourceDaoMessageHeaderR4 extends FhirResourceDaoR4<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaseBundle messageHeaderProcessMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||||
|
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -187,7 +187,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<>();
|
||||||
|
|
||||||
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : searchParams) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
|
@ -290,7 +290,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<>();
|
||||||
|
|
||||||
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : searchParams) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
|
@ -354,7 +354,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<>();
|
||||||
|
|
||||||
String resourceName = getContext().getResourceDefinition(theResource).getName();
|
String resourceName = getContext().getResourceDefinition(theResource).getName();
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
addSearchTerm(theEntity, retVal, nextSpName, searchTerm);
|
addSearchTerm(theEntity, retVal, nextSpName, searchTerm);
|
||||||
} else {
|
} else {
|
||||||
if (nextObject instanceof HumanName) {
|
if (nextObject instanceof HumanName) {
|
||||||
ArrayList<StringType> allNames = new ArrayList<StringType>();
|
ArrayList<StringType> allNames = new ArrayList<>();
|
||||||
HumanName nextHumanName = (HumanName) nextObject;
|
HumanName nextHumanName = (HumanName) nextObject;
|
||||||
if (isNotBlank(nextHumanName.getFamily())) {
|
if (isNotBlank(nextHumanName.getFamily())) {
|
||||||
allNames.add(nextHumanName.getFamilyElement());
|
allNames.add(nextHumanName.getFamilyElement());
|
||||||
|
@ -407,7 +407,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof Address) {
|
} else if (nextObject instanceof Address) {
|
||||||
ArrayList<StringType> allNames = new ArrayList<StringType>();
|
ArrayList<StringType> allNames = new ArrayList<>();
|
||||||
Address nextAddress = (Address) nextObject;
|
Address nextAddress = (Address) nextObject;
|
||||||
allNames.addAll(nextAddress.getLine());
|
allNames.addAll(nextAddress.getLine());
|
||||||
allNames.add(nextAddress.getCityElement());
|
allNames.add(nextAddress.getCityElement());
|
||||||
|
@ -573,7 +573,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
|
|
||||||
assert systems.size() == codes.size() : "Systems contains " + systems + ", codes contains: " + codes;
|
assert systems.size() == codes.size() : "Systems contains " + systems + ", codes contains: " + codes;
|
||||||
|
|
||||||
Set<Pair<String, String>> haveValues = new HashSet<Pair<String, String>>();
|
Set<Pair<String, String>> haveValues = new HashSet<>();
|
||||||
for (int i = 0; i < systems.size(); i++) {
|
for (int i = 0; i < systems.size(); i++) {
|
||||||
String system = systems.get(i);
|
String system = systems.get(i);
|
||||||
String code = codes.get(i);
|
String code = codes.get(i);
|
||||||
|
@ -608,7 +608,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<ResourceIndexedSearchParamUri>();
|
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<>();
|
||||||
|
|
||||||
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : searchParams) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
|
@ -690,7 +690,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
IWorkerContext worker = new org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext(getContext(), myValidationSupport);
|
IWorkerContext worker = new org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext(getContext(), myValidationSupport);
|
||||||
FHIRPathEngine fp = new FHIRPathEngine(worker);
|
FHIRPathEngine fp = new FHIRPathEngine(worker);
|
||||||
|
|
||||||
List<Object> values = new ArrayList<Object>();
|
List<Object> values = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
String[] nextPathsSplit = SPLIT.split(thePaths);
|
String[] nextPathsSplit = SPLIT.split(thePaths);
|
||||||
for (String nextPath : nextPathsSplit) {
|
for (String nextPath : nextPathsSplit) {
|
||||||
|
@ -717,7 +717,7 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef) {
|
public List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef) {
|
||||||
ArrayList<PathAndRef> retVal = new ArrayList<PathAndRef>();
|
ArrayList<PathAndRef> retVal = new ArrayList<>();
|
||||||
|
|
||||||
String[] nextPathsSplit = SPLIT.split(theNextSpDef.getPath());
|
String[] nextPathsSplit = SPLIT.split(theNextSpDef.getPath());
|
||||||
for (String path : nextPathsSplit) {
|
for (String path : nextPathsSplit) {
|
||||||
|
|
|
@ -63,6 +63,7 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
|
||||||
|
|
||||||
public abstract BaseTag addTag(TagDefinition theDef);
|
public abstract BaseTag addTag(TagDefinition theDef);
|
||||||
|
|
||||||
|
@Override
|
||||||
public Date getDeleted() {
|
public Date getDeleted() {
|
||||||
return myDeleted;
|
return myDeleted;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +73,7 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public FhirVersionEnum getFhirVersion() {
|
public FhirVersionEnum getFhirVersion() {
|
||||||
return myFhirVersion;
|
return myFhirVersion;
|
||||||
}
|
}
|
||||||
|
@ -88,10 +90,13 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
|
||||||
myForcedId = theForcedId;
|
myForcedId = theForcedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public abstract Long getId();
|
public abstract Long getId();
|
||||||
|
|
||||||
|
@Override
|
||||||
public abstract IdDt getIdDt();
|
public abstract IdDt getIdDt();
|
||||||
|
|
||||||
|
@Override
|
||||||
public InstantDt getPublished() {
|
public InstantDt getPublished() {
|
||||||
if (myPublished != null) {
|
if (myPublished != null) {
|
||||||
return new InstantDt(myPublished);
|
return new InstantDt(myPublished);
|
||||||
|
@ -104,12 +109,15 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
|
||||||
myPublished = thePublished;
|
myPublished = thePublished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public abstract Long getResourceId();
|
public abstract Long getResourceId();
|
||||||
|
|
||||||
|
@Override
|
||||||
public abstract String getResourceType();
|
public abstract String getResourceType();
|
||||||
|
|
||||||
public abstract Collection<? extends BaseTag> getTags();
|
public abstract Collection<? extends BaseTag> getTags();
|
||||||
|
|
||||||
|
@Override
|
||||||
public InstantDt getUpdated() {
|
public InstantDt getUpdated() {
|
||||||
return new InstantDt(myUpdated);
|
return new InstantDt(myUpdated);
|
||||||
}
|
}
|
||||||
|
@ -118,12 +126,15 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
|
||||||
myUpdated = theUpdated;
|
myUpdated = theUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Date getUpdatedDate() {
|
public Date getUpdatedDate() {
|
||||||
return myUpdated;
|
return myUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public abstract long getVersion();
|
public abstract long getVersion();
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isHasTags() {
|
public boolean isHasTags() {
|
||||||
return myHasTags;
|
return myHasTags;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,16 +24,18 @@ import org.hibernate.annotations.ColumnDefault;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = {
|
@Table(name = "HFJ_FORCED_ID", uniqueConstraints = {
|
||||||
@UniqueConstraint(name = "IDX_FORCEDID_RESID", columnNames = {"RESOURCE_PID"}),
|
@UniqueConstraint(name = "IDX_FORCEDID_RESID", columnNames = {"RESOURCE_PID"}),
|
||||||
@UniqueConstraint(name = "IDX_FORCEDID_TYPE_RESID", columnNames = {"RESOURCE_TYPE", "RESOURCE_PID"}),
|
|
||||||
@UniqueConstraint(name = "IDX_FORCEDID_TYPE_FID", columnNames = {"RESOURCE_TYPE", "FORCED_ID"})
|
@UniqueConstraint(name = "IDX_FORCEDID_TYPE_FID", columnNames = {"RESOURCE_TYPE", "FORCED_ID"})
|
||||||
}, indexes = {
|
}, indexes = {
|
||||||
@Index(name = "IDX_FORCEDID_TYPE_FORCEDID", columnList = "RESOURCE_TYPE,FORCED_ID"),
|
/*
|
||||||
|
* NB: We previously had indexes named
|
||||||
|
* - IDX_FORCEDID_TYPE_FORCEDID
|
||||||
|
* - IDX_FORCEDID_TYPE_RESID
|
||||||
|
* so don't reuse these names
|
||||||
|
*/
|
||||||
})
|
})
|
||||||
//@formatter:on
|
|
||||||
public class ForcedId {
|
public class ForcedId {
|
||||||
|
|
||||||
public static final int MAX_FORCED_ID_LENGTH = 100;
|
public static final int MAX_FORCED_ID_LENGTH = 100;
|
||||||
|
|
|
@ -62,7 +62,8 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
||||||
public String mySystem;
|
public String mySystem;
|
||||||
@Field()
|
@Field()
|
||||||
@Column(name = "SP_VALUE", nullable = true, length = MAX_LENGTH)
|
@Column(name = "SP_VALUE", nullable = true, length = MAX_LENGTH)
|
||||||
public String myValue;
|
private String myValue;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
@Id
|
@Id
|
||||||
@SequenceGenerator(name = "SEQ_SPIDX_TOKEN", sequenceName = "SEQ_SPIDX_TOKEN")
|
@SequenceGenerator(name = "SEQ_SPIDX_TOKEN", sequenceName = "SEQ_SPIDX_TOKEN")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_TOKEN")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_SPIDX_TOKEN")
|
||||||
|
@ -152,40 +153,40 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
||||||
return b.isEquals();
|
return b.isEquals();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getHashSystem() {
|
Long getHashSystem() {
|
||||||
calculateHashes();
|
calculateHashes();
|
||||||
return myHashSystem;
|
return myHashSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getHashIdentity() {
|
private Long getHashIdentity() {
|
||||||
calculateHashes();
|
calculateHashes();
|
||||||
return myHashIdentity;
|
return myHashIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashIdentity(Long theHashIdentity) {
|
private void setHashIdentity(Long theHashIdentity) {
|
||||||
myHashIdentity = theHashIdentity;
|
myHashIdentity = theHashIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashSystem(Long theHashSystem) {
|
private void setHashSystem(Long theHashSystem) {
|
||||||
myHashSystem = theHashSystem;
|
myHashSystem = theHashSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getHashSystemAndValue() {
|
Long getHashSystemAndValue() {
|
||||||
calculateHashes();
|
calculateHashes();
|
||||||
return myHashSystemAndValue;
|
return myHashSystemAndValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashSystemAndValue(Long theHashSystemAndValue) {
|
private void setHashSystemAndValue(Long theHashSystemAndValue) {
|
||||||
calculateHashes();
|
calculateHashes();
|
||||||
myHashSystemAndValue = theHashSystemAndValue;
|
myHashSystemAndValue = theHashSystemAndValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getHashValue() {
|
Long getHashValue() {
|
||||||
calculateHashes();
|
calculateHashes();
|
||||||
return myHashValue;
|
return myHashValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashValue(Long theHashValue) {
|
private void setHashValue(Long theHashValue) {
|
||||||
myHashValue = theHashValue;
|
myHashValue = theHashValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
@Table(name = "TRM_CONCEPT", uniqueConstraints = {
|
@Table(name = "TRM_CONCEPT", uniqueConstraints = {
|
||||||
@UniqueConstraint(name = "IDX_CONCEPT_CS_CODE", columnNames = {"CODESYSTEM_PID", "CODE"})
|
@UniqueConstraint(name = "IDX_CONCEPT_CS_CODE", columnNames = {"CODESYSTEM_PID", "CODE"})
|
||||||
}, indexes = {
|
}, indexes = {
|
||||||
@Index(name = "IDX_CONCEPT_INDEXSTATUS", columnList = "INDEX_STATUS")
|
@Index(name = "IDX_CONCEPT_INDEXSTATUS", columnList = "INDEX_STATUS"),
|
||||||
|
@Index(name = "IDX_CONCEPT_UPDATED", columnList = "CONCEPT_UPDATED")
|
||||||
})
|
})
|
||||||
public class TermConcept implements Serializable {
|
public class TermConcept implements Serializable {
|
||||||
protected static final int MAX_DESC_LENGTH = 400;
|
protected static final int MAX_DESC_LENGTH = 400;
|
||||||
|
@ -59,15 +60,15 @@ public class TermConcept implements Serializable {
|
||||||
@Column(name = "CODE", length = 100, nullable = false)
|
@Column(name = "CODE", length = 100, nullable = false)
|
||||||
@Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),})
|
@Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),})
|
||||||
private String myCode;
|
private String myCode;
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
@Column(name = "CONCEPT_UPDATED", nullable = true)
|
||||||
|
private Date myUpdated;
|
||||||
@ManyToOne()
|
@ManyToOne()
|
||||||
@JoinColumn(name = "CODESYSTEM_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID"))
|
@JoinColumn(name = "CODESYSTEM_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID"))
|
||||||
private TermCodeSystemVersion myCodeSystem;
|
private TermCodeSystemVersion myCodeSystem;
|
||||||
|
|
||||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
||||||
@Fields({@Field(name = "myCodeSystemVersionPid")})
|
@Fields({@Field(name = "myCodeSystemVersionPid")})
|
||||||
private long myCodeSystemVersionPid;
|
private long myCodeSystemVersionPid;
|
||||||
|
|
||||||
@Column(name = "DISPLAY", length = MAX_DESC_LENGTH, nullable = true)
|
@Column(name = "DISPLAY", length = MAX_DESC_LENGTH, nullable = true)
|
||||||
@Fields({
|
@Fields({
|
||||||
@Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
@Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
|
||||||
|
@ -76,15 +77,12 @@ public class TermConcept implements Serializable {
|
||||||
@Field(name = "myDisplayPhonetic", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompletePhoneticAnalyzer"))
|
@Field(name = "myDisplayPhonetic", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompletePhoneticAnalyzer"))
|
||||||
})
|
})
|
||||||
private String myDisplay;
|
private String myDisplay;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "myConcept", orphanRemoval = false)
|
@OneToMany(mappedBy = "myConcept", orphanRemoval = false)
|
||||||
@Field(name = "PROPmyProperties", analyzer = @Analyzer(definition = "termConceptPropertyAnalyzer"))
|
@Field(name = "PROPmyProperties", analyzer = @Analyzer(definition = "termConceptPropertyAnalyzer"))
|
||||||
@FieldBridge(impl = TermConceptPropertyFieldBridge.class)
|
@FieldBridge(impl = TermConceptPropertyFieldBridge.class)
|
||||||
private Collection<TermConceptProperty> myProperties;
|
private Collection<TermConceptProperty> myProperties;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "myConcept", orphanRemoval = false)
|
@OneToMany(mappedBy = "myConcept", orphanRemoval = false)
|
||||||
private Collection<TermConceptDesignation> myDesignations;
|
private Collection<TermConceptDesignation> myDesignations;
|
||||||
|
|
||||||
@Id()
|
@Id()
|
||||||
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
|
@SequenceGenerator(name = "SEQ_CONCEPT_PID", sequenceName = "SEQ_CONCEPT_PID")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID")
|
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PID")
|
||||||
|
@ -92,18 +90,17 @@ public class TermConcept implements Serializable {
|
||||||
private Long myId;
|
private Long myId;
|
||||||
@Column(name = "INDEX_STATUS", nullable = true)
|
@Column(name = "INDEX_STATUS", nullable = true)
|
||||||
private Long myIndexStatus;
|
private Long myIndexStatus;
|
||||||
@Transient
|
|
||||||
@Field(name = "myParentPids", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "conceptParentPidsAnalyzer"))
|
@Field(name = "myParentPids", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "conceptParentPidsAnalyzer"))
|
||||||
|
@Lob
|
||||||
|
@Column(name="PARENT_PIDS", nullable = true)
|
||||||
private String myParentPids;
|
private String myParentPids;
|
||||||
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "myChild")
|
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "myChild")
|
||||||
private Collection<TermConceptParentChildLink> myParents;
|
private Collection<TermConceptParentChildLink> myParents;
|
||||||
@Column(name = "CODE_SEQUENCE", nullable = true)
|
@Column(name = "CODE_SEQUENCE", nullable = true)
|
||||||
private Integer mySequence;
|
private Integer mySequence;
|
||||||
|
|
||||||
public TermConcept() {
|
public TermConcept() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TermConcept(TermCodeSystemVersion theCs, String theCode) {
|
public TermConcept(TermCodeSystemVersion theCs, String theCode) {
|
||||||
setCodeSystemVersion(theCs);
|
setCodeSystemVersion(theCs);
|
||||||
setCode(theCode);
|
setCode(theCode);
|
||||||
|
@ -296,6 +293,14 @@ public class TermConcept implements Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getUpdated() {
|
||||||
|
return myUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdated(Date theUpdated) {
|
||||||
|
myUpdated = theUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
HashCodeBuilder b = new HashCodeBuilder();
|
HashCodeBuilder b = new HashCodeBuilder();
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ca.uhn.fhir.jpa.provider;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.MessageHeader;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BaseJpaResourceProviderMessageHeaderDstu2 extends JpaResourceProviderDstu2<MessageHeader> {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /MessageHeader/$process-message
|
||||||
|
*/
|
||||||
|
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
|
||||||
|
public IBaseBundle processMessage(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
RequestDetails theRequestDetails,
|
||||||
|
|
||||||
|
@OperationParam(name = "content", min = 1, max = 1)
|
||||||
|
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
|
||||||
|
Bundle theMessageToProcess
|
||||||
|
) {
|
||||||
|
|
||||||
|
startRequest(theServletRequest);
|
||||||
|
try {
|
||||||
|
return ((IFhirResourceDaoMessageHeader<MessageHeader>) getDao()).messageHeaderProcessMessage(theRequestDetails, theMessageToProcess);
|
||||||
|
} finally {
|
||||||
|
endRequest(theServletRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
|
import org.hl7.fhir.dstu3.model.MessageHeader;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BaseJpaResourceProviderMessageHeaderDstu3 extends JpaResourceProviderDstu3<MessageHeader> {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /MessageHeader/$process-message
|
||||||
|
*/
|
||||||
|
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
|
||||||
|
public IBaseBundle processMessage(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
RequestDetails theRequestDetails,
|
||||||
|
|
||||||
|
@OperationParam(name = "content", min = 1, max = 1)
|
||||||
|
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
|
||||||
|
Bundle theMessageToProcess
|
||||||
|
) {
|
||||||
|
|
||||||
|
startRequest(theServletRequest);
|
||||||
|
try {
|
||||||
|
return ((IFhirResourceDaoMessageHeader<MessageHeader>) getDao()).messageHeaderProcessMessage(theRequestDetails, theMessageToProcess);
|
||||||
|
} finally {
|
||||||
|
endRequest(theServletRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ca.uhn.fhir.jpa.provider.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoMessageHeader;
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
|
import org.hl7.fhir.r4.model.MessageHeader;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 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%
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BaseJpaResourceProviderMessageHeaderR4 extends JpaResourceProviderR4<MessageHeader> {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /MessageHeader/$process-message
|
||||||
|
*/
|
||||||
|
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
|
||||||
|
public IBaseBundle processMessage(
|
||||||
|
HttpServletRequest theServletRequest,
|
||||||
|
RequestDetails theRequestDetails,
|
||||||
|
|
||||||
|
@OperationParam(name = "content", min = 1, max = 1)
|
||||||
|
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
|
||||||
|
Bundle theMessageToProcess
|
||||||
|
) {
|
||||||
|
|
||||||
|
startRequest(theServletRequest);
|
||||||
|
try {
|
||||||
|
return ((IFhirResourceDaoMessageHeader<MessageHeader>) getDao()).messageHeaderProcessMessage(theRequestDetails, theMessageToProcess);
|
||||||
|
} finally {
|
||||||
|
endRequest(theServletRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -20,9 +20,7 @@ package ca.uhn.fhir.jpa.search;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.lucene.analysis.core.LowerCaseFilterFactory;
|
import org.apache.lucene.analysis.core.*;
|
||||||
import org.apache.lucene.analysis.core.StopFilterFactory;
|
|
||||||
import org.apache.lucene.analysis.core.WhitespaceTokenizerFactory;
|
|
||||||
import org.apache.lucene.analysis.miscellaneous.WordDelimiterFilterFactory;
|
import org.apache.lucene.analysis.miscellaneous.WordDelimiterFilterFactory;
|
||||||
import org.apache.lucene.analysis.ngram.EdgeNGramFilterFactory;
|
import org.apache.lucene.analysis.ngram.EdgeNGramFilterFactory;
|
||||||
import org.apache.lucene.analysis.ngram.NGramFilterFactory;
|
import org.apache.lucene.analysis.ngram.NGramFilterFactory;
|
||||||
|
@ -65,7 +63,7 @@ public class LuceneSearchMappingFactory {
|
||||||
.param("maxGramSize", "20")
|
.param("maxGramSize", "20")
|
||||||
.analyzerDef("standardAnalyzer", StandardTokenizerFactory.class)
|
.analyzerDef("standardAnalyzer", StandardTokenizerFactory.class)
|
||||||
.filter(LowerCaseFilterFactory.class)
|
.filter(LowerCaseFilterFactory.class)
|
||||||
.analyzerDef("exactAnalyzer", StandardTokenizerFactory.class)
|
.analyzerDef("exactAnalyzer", KeywordTokenizerFactory.class)
|
||||||
.analyzerDef("conceptParentPidsAnalyzer", WhitespaceTokenizerFactory.class)
|
.analyzerDef("conceptParentPidsAnalyzer", WhitespaceTokenizerFactory.class)
|
||||||
.analyzerDef("termConceptPropertyAnalyzer", WhitespaceTokenizerFactory.class);
|
.analyzerDef("termConceptPropertyAnalyzer", WhitespaceTokenizerFactory.class);
|
||||||
|
|
||||||
|
|
|
@ -45,14 +45,15 @@ import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.queries.TermsQuery;
|
import org.apache.lucene.queries.TermsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.*;
|
||||||
import org.apache.lucene.search.RegexpQuery;
|
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||||
import org.hibernate.search.jpa.FullTextQuery;
|
import org.hibernate.search.jpa.FullTextQuery;
|
||||||
import org.hibernate.search.query.dsl.BooleanJunction;
|
import org.hibernate.search.query.dsl.BooleanJunction;
|
||||||
import org.hibernate.search.query.dsl.QueryBuilder;
|
import org.hibernate.search.query.dsl.QueryBuilder;
|
||||||
|
import org.hibernate.search.query.dsl.TermMatchingContext;
|
||||||
|
import org.hibernate.search.query.dsl.TermTermination;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.CodeSystem;
|
import org.hl7.fhir.r4.model.CodeSystem;
|
||||||
|
@ -66,6 +67,7 @@ import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
@ -82,6 +84,7 @@ import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.*;
|
import javax.persistence.criteria.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
@ -273,74 +276,43 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
myEntityManager.flush();
|
myEntityManager.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteCodeSystemVersion(Long theCodeSystemVersionPid) {
|
public void deleteCodeSystemVersion(final Long theCodeSystemVersionPid) {
|
||||||
ourLog.info(" * Deleting code system version {}", theCodeSystemVersionPid);
|
ourLog.info(" * Deleting code system version {}", theCodeSystemVersionPid);
|
||||||
|
|
||||||
PageRequest page = PageRequest.of(0, 1000);
|
PageRequest page1000 = PageRequest.of(0, 1000);
|
||||||
int count;
|
|
||||||
|
|
||||||
// Parent/Child links
|
// Parent/Child links
|
||||||
ourLog.info(" * Deleting parent/child links");
|
{
|
||||||
count = 0;
|
String descriptor = "parent/child links";
|
||||||
while (true) {
|
Supplier<Slice<TermConceptParentChildLink>> loader = () -> myConceptParentChildLinkDao.findByCodeSystemVersion(page1000, theCodeSystemVersionPid);
|
||||||
Slice<TermConceptParentChildLink> link = myConceptParentChildLinkDao.findByCodeSystemVersion(page, theCodeSystemVersionPid);
|
Supplier<Integer> counter = () -> myConceptParentChildLinkDao.countByCodeSystemVersion(theCodeSystemVersionPid);
|
||||||
if (link.hasContent() == false) {
|
doDelete(descriptor, loader, counter, myConceptParentChildLinkDao);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
myConceptParentChildLinkDao.deleteInBatch(link);
|
|
||||||
|
|
||||||
count += link.getNumberOfElements();
|
|
||||||
ourLog.info(" * {} parent/child links deleted", count);
|
|
||||||
}
|
|
||||||
myConceptParentChildLinkDao.flush();
|
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
ourLog.info(" * Deleting properties");
|
{
|
||||||
count = 0;
|
String descriptor = "concept properties";
|
||||||
while (true) {
|
Supplier<Slice<TermConceptProperty>> loader = () -> myConceptPropertyDao.findByCodeSystemVersion(page1000, theCodeSystemVersionPid);
|
||||||
Slice<TermConceptProperty> link = myConceptPropertyDao.findByCodeSystemVersion(page, theCodeSystemVersionPid);
|
Supplier<Integer> counter = () -> myConceptPropertyDao.countByCodeSystemVersion(theCodeSystemVersionPid);
|
||||||
if (link.hasContent() == false) {
|
doDelete(descriptor, loader, counter, myConceptPropertyDao);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
myConceptPropertyDao.deleteInBatch(link);
|
// Designations
|
||||||
|
{
|
||||||
count += link.getNumberOfElements();
|
String descriptor = "concept designations";
|
||||||
ourLog.info(" * {} concept properties deleted", count);
|
Supplier<Slice<TermConceptDesignation>> loader = () -> myConceptDesignationDao.findByCodeSystemVersion(page1000, theCodeSystemVersionPid);
|
||||||
|
Supplier<Integer> counter = () -> myConceptDesignationDao.countByCodeSystemVersion(theCodeSystemVersionPid);
|
||||||
|
doDelete(descriptor, loader, counter, myConceptDesignationDao);
|
||||||
}
|
}
|
||||||
myConceptPropertyDao.flush();
|
|
||||||
|
|
||||||
// Properties
|
|
||||||
ourLog.info(" * Deleting designations");
|
|
||||||
count = 0;
|
|
||||||
while (true) {
|
|
||||||
Slice<TermConceptDesignation> link = myConceptDesignationDao.findByCodeSystemVersion(page, theCodeSystemVersionPid);
|
|
||||||
if (link.hasContent() == false) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
myConceptDesignationDao.deleteInBatch(link);
|
|
||||||
|
|
||||||
count += link.getNumberOfElements();
|
|
||||||
ourLog.info(" * {} concept designations deleted", count);
|
|
||||||
}
|
|
||||||
myConceptDesignationDao.flush();
|
|
||||||
|
|
||||||
// Concepts
|
// Concepts
|
||||||
ourLog.info(" * Deleting concepts");
|
{
|
||||||
count = 0;
|
String descriptor = "concepts";
|
||||||
while (true) {
|
// For some reason, concepts are much slower to delete, so use a smaller batch size
|
||||||
Slice<TermConcept> link = myConceptDao.findByCodeSystemVersion(page, theCodeSystemVersionPid);
|
PageRequest page100 = PageRequest.of(0, 100);
|
||||||
if (link.hasContent() == false) {
|
Supplier<Slice<TermConcept>> loader = () -> myConceptDao.findByCodeSystemVersion(page100, theCodeSystemVersionPid);
|
||||||
break;
|
Supplier<Integer> counter = () -> myConceptDao.countByCodeSystemVersion(theCodeSystemVersionPid);
|
||||||
}
|
doDelete(descriptor, loader, counter, myConceptDao);
|
||||||
|
|
||||||
myConceptDao.deleteInBatch(link);
|
|
||||||
myConceptDao.flush();
|
|
||||||
|
|
||||||
count += link.getNumberOfElements();
|
|
||||||
ourLog.info(" * {} concepts deleted", count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<TermCodeSystem> codeSystemOpt = myCodeSystemDao.findWithCodeSystemVersionAsCurrentVersion(theCodeSystemVersionPid);
|
Optional<TermCodeSystem> codeSystemOpt = myCodeSystemDao.findWithCodeSystemVersionAsCurrentVersion(theCodeSystemVersionPid);
|
||||||
|
@ -397,6 +369,26 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
deleteConceptMap(theResourceTable);
|
deleteConceptMap(theResourceTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> void doDelete(String theDescriptor, Supplier<Slice<T>> theLoader, Supplier<Integer> theCounter, JpaRepository<T, ?> theDao) {
|
||||||
|
int count;
|
||||||
|
ourLog.info(" * Deleting {}", theDescriptor);
|
||||||
|
int totalCount = theCounter.get();
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
count = 0;
|
||||||
|
while (true) {
|
||||||
|
Slice<T> link = theLoader.get();
|
||||||
|
if (link.hasContent() == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
theDao.deleteInBatch(link);
|
||||||
|
|
||||||
|
count += link.getNumberOfElements();
|
||||||
|
ourLog.info(" * {} {} deleted - {}/sec - ETA: {}", count, theDescriptor, sw.formatThroughput(count, TimeUnit.SECONDS), sw.getEstimatedTimeRemaining(count, totalCount));
|
||||||
|
}
|
||||||
|
theDao.flush();
|
||||||
|
}
|
||||||
|
|
||||||
private int ensureParentsSaved(Collection<TermConceptParentChildLink> theParents) {
|
private int ensureParentsSaved(Collection<TermConceptParentChildLink> theParents) {
|
||||||
ourLog.trace("Checking {} parents", theParents.size());
|
ourLog.trace("Checking {} parents", theParents.size());
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
|
@ -406,6 +398,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
TermConcept nextParent = nextLink.getParent();
|
TermConcept nextParent = nextLink.getParent();
|
||||||
retVal += ensureParentsSaved(nextParent.getParents());
|
retVal += ensureParentsSaved(nextParent.getParents());
|
||||||
if (nextParent.getId() == null) {
|
if (nextParent.getId() == null) {
|
||||||
|
nextParent.setUpdated(new Date());
|
||||||
myConceptDao.saveAndFlush(nextParent);
|
myConceptDao.saveAndFlush(nextParent);
|
||||||
retVal++;
|
retVal++;
|
||||||
ourLog.debug("Saved parent code {} and got id {}", nextParent.getCode(), nextParent.getId());
|
ourLog.debug("Saved parent code {} and got id {}", nextParent.getCode(), nextParent.getId());
|
||||||
|
@ -466,21 +459,6 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
|
|
||||||
bool.must(qb.keyword().onField("myCodeSystemVersionPid").matching(csv.getPid()).createQuery());
|
bool.must(qb.keyword().onField("myCodeSystemVersionPid").matching(csv.getPid()).createQuery());
|
||||||
|
|
||||||
/*
|
|
||||||
* Include Concepts
|
|
||||||
*/
|
|
||||||
|
|
||||||
String codes = include
|
|
||||||
.getConcept()
|
|
||||||
.stream()
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.map(ValueSet.ConceptReferenceComponent::getCode)
|
|
||||||
.filter(StringUtils::isNotBlank)
|
|
||||||
.collect(Collectors.joining(" "));
|
|
||||||
if (isNotBlank(codes)) {
|
|
||||||
bool.must(qb.keyword().onField("myCode").matching(codes).createQuery());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Filters
|
* Filters
|
||||||
*/
|
*/
|
||||||
|
@ -559,6 +537,32 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
}
|
}
|
||||||
|
|
||||||
Query luceneQuery = bool.createQuery();
|
Query luceneQuery = bool.createQuery();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include Concepts
|
||||||
|
*/
|
||||||
|
|
||||||
|
List<Term> codes = include
|
||||||
|
.getConcept()
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(ValueSet.ConceptReferenceComponent::getCode)
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.map(t->new Term("myCode", t))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (codes.size() > 0) {
|
||||||
|
MultiPhraseQuery query = new MultiPhraseQuery();
|
||||||
|
query.add(codes.toArray(new Term[0]));
|
||||||
|
luceneQuery = new BooleanQuery.Builder()
|
||||||
|
.add(luceneQuery, BooleanClause.Occur.MUST)
|
||||||
|
.add(query, BooleanClause.Occur.MUST)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute the query
|
||||||
|
*/
|
||||||
|
|
||||||
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, TermConcept.class);
|
FullTextQuery jpaQuery = em.createFullTextQuery(luceneQuery, TermConcept.class);
|
||||||
jpaQuery.setMaxResults(1000);
|
jpaQuery.setMaxResults(1000);
|
||||||
|
|
||||||
|
@ -896,9 +900,11 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
|
|
||||||
for (TermConcept nextConcept : concepts) {
|
for (TermConcept nextConcept : concepts) {
|
||||||
|
|
||||||
|
if (isBlank(nextConcept.getParentPidsAsString())) {
|
||||||
StringBuilder parentsBuilder = new StringBuilder();
|
StringBuilder parentsBuilder = new StringBuilder();
|
||||||
createParentsString(parentsBuilder, nextConcept.getId());
|
createParentsString(parentsBuilder, nextConcept.getId());
|
||||||
nextConcept.setParentPids(parentsBuilder.toString());
|
nextConcept.setParentPids(parentsBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
saveConcept(nextConcept);
|
saveConcept(nextConcept);
|
||||||
count++;
|
count++;
|
||||||
|
@ -932,6 +938,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
||||||
if (theConcept.getId() == null || theConcept.getIndexStatus() == null) {
|
if (theConcept.getId() == null || theConcept.getIndexStatus() == null) {
|
||||||
retVal++;
|
retVal++;
|
||||||
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
|
||||||
|
theConcept.setUpdated(new Date());
|
||||||
myConceptDao.save(theConcept);
|
myConceptDao.save(theConcept);
|
||||||
|
|
||||||
for (TermConceptProperty next : theConcept.getProperties()) {
|
for (TermConceptProperty next : theConcept.getProperties()) {
|
||||||
|
|
|
@ -150,6 +150,11 @@ public class JpaConstants {
|
||||||
*/
|
*/
|
||||||
public static final String OPERATION_EVERYTHING = "$everything";
|
public static final String OPERATION_EVERYTHING = "$everything";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation name for the $process-message operation
|
||||||
|
*/
|
||||||
|
public static final String OPERATION_PROCESS_MESSAGE = "$process-message";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation name for the $meta-delete operation
|
* Operation name for the $meta-delete operation
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
@ -43,11 +44,6 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
||||||
private Exception myLastStackTrace;
|
private Exception myLastStackTrace;
|
||||||
private String myLastStackTraceThreadName;
|
private String myLastStackTraceThreadName;
|
||||||
|
|
||||||
@Bean(name="maxDatabaseThreadsForTest")
|
|
||||||
public Integer getMaxThread(){
|
|
||||||
return ourMaxThreads;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean()
|
@Bean()
|
||||||
public DaoConfig daoConfig() {
|
public DaoConfig daoConfig() {
|
||||||
return new DaoConfig();
|
return new DaoConfig();
|
||||||
|
@ -131,6 +127,11 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "maxDatabaseThreadsForTest")
|
||||||
|
public Integer getMaxThread() {
|
||||||
|
return ourMaxThreads;
|
||||||
|
}
|
||||||
|
|
||||||
private Properties jpaProperties() {
|
private Properties jpaProperties() {
|
||||||
Properties extraProperties = new Properties();
|
Properties extraProperties = new Properties();
|
||||||
extraProperties.put("hibernate.format_sql", "true");
|
extraProperties.put("hibernate.format_sql", "true");
|
||||||
|
@ -165,4 +166,9 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UnregisterScheduledProcessor unregisterScheduledProcessor(Environment theEnv) {
|
||||||
|
return new UnregisterScheduledProcessor(theEnv);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,9 @@ import ca.uhn.fhir.jpa.subscription.email.IEmailSender;
|
||||||
import ca.uhn.fhir.jpa.subscription.email.JavaMailEmailSender;
|
import ca.uhn.fhir.jpa.subscription.email.JavaMailEmailSender;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel;
|
|
||||||
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
@ -22,13 +17,11 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
|
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -194,23 +187,4 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class UnregisterScheduledProcessor implements BeanFactoryPostProcessor {
|
|
||||||
|
|
||||||
private final Environment myEnvironment;
|
|
||||||
|
|
||||||
public UnregisterScheduledProcessor(Environment theEnv) {
|
|
||||||
myEnvironment = theEnv;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
|
||||||
String schedulingDisabled = myEnvironment.getProperty("scheduling_disabled");
|
|
||||||
if ("true".equals(schedulingDisabled)) {
|
|
||||||
for (String beanName : beanFactory.getBeanNamesForType(ScheduledAnnotationBeanPostProcessor.class)) {
|
|
||||||
((DefaultListableBeanFactory) beanFactory).removeBeanDefinition(beanName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,13 @@ import net.ttddyy.dsproxy.listener.ThreadQueryCountHolder;
|
||||||
import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel;
|
import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel;
|
||||||
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
|
||||||
import org.hibernate.query.criteria.LiteralHandlingMode;
|
import org.hibernate.query.criteria.LiteralHandlingMode;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.orm.hibernate5.HibernateExceptionTranslator;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
|
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
@ -163,6 +161,11 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UnregisterScheduledProcessor unregisterScheduledProcessor(Environment theEnv) {
|
||||||
|
return new UnregisterScheduledProcessor(theEnv);
|
||||||
|
}
|
||||||
|
|
||||||
public static int getMaxThreads() {
|
public static int getMaxThreads() {
|
||||||
return ourMaxThreads;
|
return ourMaxThreads;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package ca.uhn.fhir.jpa.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
|
||||||
|
import org.springframework.scheduling.concurrent.ExecutorConfigurationSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This bean postprocessor disables all scheduled tasks. It is intended
|
||||||
|
* only to be used in unit tests in circumstances where scheduled
|
||||||
|
* tasks cause issues.
|
||||||
|
*/
|
||||||
|
public class UnregisterScheduledProcessor implements BeanFactoryPostProcessor {
|
||||||
|
|
||||||
|
private final Environment myEnvironment;
|
||||||
|
|
||||||
|
public UnregisterScheduledProcessor(Environment theEnv) {
|
||||||
|
myEnvironment = theEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||||
|
String schedulingDisabled = myEnvironment.getProperty("scheduling_disabled");
|
||||||
|
if ("true".equals(schedulingDisabled)) {
|
||||||
|
for (String beanName : beanFactory.getBeanNamesForType(ScheduledAnnotationBeanPostProcessor.class)) {
|
||||||
|
((DefaultListableBeanFactory) beanFactory).removeBeanDefinition(beanName);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String beanName : beanFactory.getBeanNamesForType(ExecutorConfigurationSupport.class)) {
|
||||||
|
ExecutorConfigurationSupport executorConfigSupport = ((DefaultListableBeanFactory) beanFactory).getBean(beanName, ExecutorConfigurationSupport.class);
|
||||||
|
executorConfigSupport.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -104,6 +104,8 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
||||||
@Qualifier("myConceptMapDaoR4")
|
@Qualifier("myConceptMapDaoR4")
|
||||||
protected IFhirResourceDaoConceptMap<ConceptMap> myConceptMapDao;
|
protected IFhirResourceDaoConceptMap<ConceptMap> myConceptMapDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
protected ITermConceptDao myTermConceptDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myConditionDaoR4")
|
@Qualifier("myConditionDaoR4")
|
||||||
protected IFhirResourceDao<Condition> myConditionDao;
|
protected IFhirResourceDao<Condition> myConditionDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import net.ttddyy.dsproxy.QueryCountHolder;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.DateTimeType;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@TestPropertySource(properties = {
|
||||||
|
"scheduling_disabled=true"
|
||||||
|
})
|
||||||
|
public class FhirResourceDaoR4QueryCountTest extends BaseJpaR4Test {
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4QueryCountTest.class);
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void afterResetDao() {
|
||||||
|
myDaoConfig.setResourceMetaCountHardLimit(new DaoConfig().getResourceMetaCountHardLimit());
|
||||||
|
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateClientAssignedId() {
|
||||||
|
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
||||||
|
|
||||||
|
QueryCountHolder.clear();
|
||||||
|
ourLog.info("** Starting Update Non-Existing resource with client assigned ID");
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getPhotoFirstRep().setCreationElement(new DateTimeType("2011")); // non-indexed field
|
||||||
|
myPatientDao.update(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
assertEquals(1, QueryCountHolder.getGrandTotal().getSelect());
|
||||||
|
assertEquals(4, QueryCountHolder.getGrandTotal().getInsert());
|
||||||
|
assertEquals(0, QueryCountHolder.getGrandTotal().getDelete());
|
||||||
|
// Because of the forced ID's bidirectional link HFJ_RESOURCE <-> HFJ_FORCED_ID
|
||||||
|
assertEquals(1, QueryCountHolder.getGrandTotal().getUpdate());
|
||||||
|
runInTransaction(() -> {
|
||||||
|
assertEquals(1, myResourceTableDao.count());
|
||||||
|
assertEquals(1, myResourceHistoryTableDao.count());
|
||||||
|
assertEquals(1, myForcedIdDao.count());
|
||||||
|
assertEquals(1, myResourceIndexedSearchParamTokenDao.count());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ok how about an update
|
||||||
|
|
||||||
|
QueryCountHolder.clear();
|
||||||
|
ourLog.info("** Starting Update Existing resource with client assigned ID");
|
||||||
|
p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getPhotoFirstRep().setCreationElement(new DateTimeType("2012")); // non-indexed field
|
||||||
|
myPatientDao.update(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
assertEquals(5, QueryCountHolder.getGrandTotal().getSelect());
|
||||||
|
assertEquals(1, QueryCountHolder.getGrandTotal().getInsert());
|
||||||
|
assertEquals(0, QueryCountHolder.getGrandTotal().getDelete());
|
||||||
|
assertEquals(1, QueryCountHolder.getGrandTotal().getUpdate());
|
||||||
|
runInTransaction(() -> {
|
||||||
|
assertEquals(1, myResourceTableDao.count());
|
||||||
|
assertEquals(2, myResourceHistoryTableDao.count());
|
||||||
|
assertEquals(1, myForcedIdDao.count());
|
||||||
|
assertEquals(1, myResourceIndexedSearchParamTokenDao.count());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneRowPerUpdate() {
|
||||||
|
myDaoConfig.setIndexMissingFields(DaoConfig.IndexEnabledEnum.DISABLED);
|
||||||
|
|
||||||
|
QueryCountHolder.clear();
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.getPhotoFirstRep().setCreationElement(new DateTimeType("2011")); // non-indexed field
|
||||||
|
IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
assertEquals(3, QueryCountHolder.getGrandTotal().getInsert());
|
||||||
|
runInTransaction(() -> {
|
||||||
|
assertEquals(1, myResourceTableDao.count());
|
||||||
|
assertEquals(1, myResourceHistoryTableDao.count());
|
||||||
|
});
|
||||||
|
|
||||||
|
QueryCountHolder.clear();
|
||||||
|
p = new Patient();
|
||||||
|
p.setId(id);
|
||||||
|
p.getPhotoFirstRep().setCreationElement(new DateTimeType("2012")); // non-indexed field
|
||||||
|
myPatientDao.update(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
assertEquals(1, QueryCountHolder.getGrandTotal().getInsert());
|
||||||
|
runInTransaction(() -> {
|
||||||
|
assertEquals(1, myResourceTableDao.count());
|
||||||
|
assertEquals(2, myResourceHistoryTableDao.count());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,30 +1,13 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
|
||||||
import static org.hamcrest.Matchers.containsStringIgnoringCase;
|
|
||||||
import static org.hamcrest.Matchers.empty;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
|
||||||
import org.hl7.fhir.r4.model.*;
|
|
||||||
import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceCategory;
|
|
||||||
import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
|
||||||
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
|
|
||||||
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
|
|
||||||
import org.hl7.fhir.r4.model.ValueSet.*;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.junit.*;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.entity.*;
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||||
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
@ -34,13 +17,29 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import ca.uhn.fhir.validation.FhirValidator;
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
import ca.uhn.fhir.validation.ValidationResult;
|
import ca.uhn.fhir.validation.ValidationResult;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.r4.model.*;
|
||||||
|
import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceCategory;
|
||||||
|
import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
|
||||||
|
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
|
||||||
|
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
|
import org.hl7.fhir.r4.model.ValueSet.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4TerminologyTest.class);
|
|
||||||
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
|
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
|
||||||
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
|
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4TerminologyTest.class);
|
||||||
@Autowired
|
@Autowired
|
||||||
private IHapiTerminologySvc myHapiTerminologySvc;
|
private IHapiTerminologySvc myHapiTerminologySvc;
|
||||||
|
|
||||||
|
@ -96,38 +95,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
|
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
|
||||||
parentC.addChild(childCA, RelationshipTypeEnum.ISA);
|
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", cs);
|
||||||
return codeSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CodeSystem createExternalCsLarge() {
|
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
|
||||||
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
|
||||||
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
|
||||||
|
|
||||||
ResourceTable table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);
|
|
||||||
|
|
||||||
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
|
||||||
cs.setResource(table);
|
|
||||||
|
|
||||||
TermConcept parentA = new TermConcept(cs, "codeA").setDisplay("CodeA");
|
|
||||||
cs.getConcepts().add(parentA);
|
|
||||||
|
|
||||||
for (int i = 0; i < 450; i++) {
|
|
||||||
TermConcept childI = new TermConcept(cs, "subCodeA"+i).setDisplay("Sub-code A"+i);
|
|
||||||
parentA.addChild(childI, RelationshipTypeEnum.ISA);
|
|
||||||
}
|
|
||||||
|
|
||||||
TermConcept parentB = new TermConcept(cs, "codeB").setDisplay("CodeB");
|
|
||||||
cs.getConcepts().add(parentB);
|
|
||||||
|
|
||||||
for (int i = 0; i < 450; i++) {
|
|
||||||
TermConcept childI = new TermConcept(cs, "subCodeB"+i).setDisplay("Sub-code B"+i);
|
|
||||||
parentB.addChild(childI, RelationshipTypeEnum.ISA);
|
|
||||||
}
|
|
||||||
|
|
||||||
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM,"SYSTEM NAME" , cs);
|
|
||||||
return codeSystem;
|
return codeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +131,38 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
|
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
|
||||||
dogs.addChild(beagle, RelationshipTypeEnum.ISA);
|
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", cs);
|
||||||
|
return codeSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodeSystem createExternalCsLarge() {
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||||
|
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||||
|
|
||||||
|
ResourceTable table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);
|
||||||
|
|
||||||
|
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||||
|
cs.setResource(table);
|
||||||
|
|
||||||
|
TermConcept parentA = new TermConcept(cs, "codeA").setDisplay("CodeA");
|
||||||
|
cs.getConcepts().add(parentA);
|
||||||
|
|
||||||
|
for (int i = 0; i < 450; i++) {
|
||||||
|
TermConcept childI = new TermConcept(cs, "subCodeA" + i).setDisplay("Sub-code A" + i);
|
||||||
|
parentA.addChild(childI, RelationshipTypeEnum.ISA);
|
||||||
|
}
|
||||||
|
|
||||||
|
TermConcept parentB = new TermConcept(cs, "codeB").setDisplay("CodeB");
|
||||||
|
cs.getConcepts().add(parentB);
|
||||||
|
|
||||||
|
for (int i = 0; i < 450; i++) {
|
||||||
|
TermConcept childI = new TermConcept(cs, "subCodeB" + i).setDisplay("Sub-code B" + i);
|
||||||
|
parentB.addChild(childI, RelationshipTypeEnum.ISA);
|
||||||
|
}
|
||||||
|
|
||||||
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||||
return codeSystem;
|
return codeSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +251,20 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConceptTimestamps() {
|
||||||
|
long start = System.currentTimeMillis() - 10;
|
||||||
|
|
||||||
|
createExternalCsDogs();
|
||||||
|
|
||||||
|
runInTransaction(() -> {
|
||||||
|
List<TermConcept> concepts = myTermConceptDao.findAll();
|
||||||
|
for (TermConcept next : concepts) {
|
||||||
|
assertTrue(next.getUpdated().getTime() > start);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandInvalid() {
|
public void testExpandInvalid() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
|
@ -300,47 +313,6 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: get this working
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
public void testExpandWithOpEquals() {
|
|
||||||
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expandByIdentifier("http://hl7.org/fhir/ValueSet/doc-typecodes", "");
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandWithCodesAndDisplayFilterPartialOnFilter() {
|
|
||||||
CodeSystem codeSystem = createExternalCsDogs();
|
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
|
||||||
valueSet.setUrl(URL_MY_VALUE_SET);
|
|
||||||
valueSet.getCompose()
|
|
||||||
.addInclude()
|
|
||||||
.setSystem(codeSystem.getUrl())
|
|
||||||
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
|
||||||
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
|
||||||
valueSet.getCompose()
|
|
||||||
.addInclude()
|
|
||||||
.setSystem(codeSystem.getUrl())
|
|
||||||
.addFilter()
|
|
||||||
.setProperty("concept")
|
|
||||||
.setOp(FilterOperator.ISA)
|
|
||||||
.setValue("dogs");
|
|
||||||
|
|
||||||
myValueSetDao.create(valueSet, mySrd);
|
|
||||||
|
|
||||||
ValueSet result = myValueSetDao.expand(valueSet, "lab");
|
|
||||||
logAndValidateValueSet(result);
|
|
||||||
|
|
||||||
assertEquals(1, result.getExpansion().getTotal());
|
|
||||||
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
|
||||||
assertThat(codes, containsInAnyOrder("labrador"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithCodesAndDisplayFilterPartialOnCodes() {
|
public void testExpandWithCodesAndDisplayFilterPartialOnCodes() {
|
||||||
CodeSystem codeSystem = createExternalCsDogs();
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
@ -389,6 +361,36 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithCodesAndDisplayFilterPartialOnFilter() {
|
||||||
|
CodeSystem codeSystem = createExternalCsDogs();
|
||||||
|
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("hello"))
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("goodbye"));
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addFilter()
|
||||||
|
.setProperty("concept")
|
||||||
|
.setOp(FilterOperator.ISA)
|
||||||
|
.setValue("dogs");
|
||||||
|
|
||||||
|
myValueSetDao.create(valueSet, mySrd);
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expand(valueSet, "lab");
|
||||||
|
logAndValidateValueSet(result);
|
||||||
|
|
||||||
|
assertEquals(1, result.getExpansion().getTotal());
|
||||||
|
ArrayList<String> codes = toCodesContains(result.getExpansion().getContains());
|
||||||
|
assertThat(codes, containsInAnyOrder("labrador"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithDisplayInExternalValueSetFuzzyMatching() {
|
public void testExpandWithDisplayInExternalValueSetFuzzyMatching() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
|
@ -442,6 +444,56 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
assertThat(codes, containsInAnyOrder("ParentA", "ParentB", "childAB", "childAAB", "ParentC", "childBA", "childCA"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithIncludeContainingDashesInInclude() {
|
||||||
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
|
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
|
||||||
|
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
|
||||||
|
|
||||||
|
ResourceTable table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);
|
||||||
|
|
||||||
|
TermCodeSystemVersion cs = new TermCodeSystemVersion();
|
||||||
|
cs.setResource(table);
|
||||||
|
|
||||||
|
TermConcept concept;
|
||||||
|
concept = new TermConcept(cs, "LA1111-2");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
concept = new TermConcept(cs, "LA2222-2");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
concept = new TermConcept(cs, "LA3333-2");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
concept = new TermConcept(cs, "LA1122-2");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
concept = new TermConcept(cs, "LA1133-2");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
concept = new TermConcept(cs, "LA4444-2");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
concept = new TermConcept(cs, "LA9999-7");
|
||||||
|
cs.getConcepts().add(concept);
|
||||||
|
|
||||||
|
myTermSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", cs);
|
||||||
|
|
||||||
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setUrl(URL_MY_VALUE_SET);
|
||||||
|
valueSet.getCompose()
|
||||||
|
.addInclude()
|
||||||
|
.setSystem(codeSystem.getUrl())
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("LA2222-2"))
|
||||||
|
.addConcept(new ConceptReferenceComponent().setCode("LA1122-2"));
|
||||||
|
IIdType vsid = myValueSetDao.create(valueSet, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
ValueSet expansion = myValueSetDao.expand(vsid, null, null);
|
||||||
|
Set<String> codes = expansion
|
||||||
|
.getExpansion()
|
||||||
|
.getContains()
|
||||||
|
.stream()
|
||||||
|
.map(t -> t.getCode())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
ourLog.info("Codes: {}", codes);
|
||||||
|
assertThat(codes, containsInAnyOrder("LA2222-2", "LA1122-2"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithInvalidExclude() {
|
public void testExpandWithInvalidExclude() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
|
@ -543,6 +595,16 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: get this working
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testExpandWithOpEquals() {
|
||||||
|
|
||||||
|
|
||||||
|
ValueSet result = myValueSetDao.expandByIdentifier("http://hl7.org/fhir/ValueSet/doc-typecodes", "");
|
||||||
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
public void testExpandWithSystemAndCodesAndFilterKeywordInLocalValueSet() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
|
@ -713,7 +775,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
cs.setResource(table);
|
cs.setResource(table);
|
||||||
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
|
||||||
cs.getConcepts().add(parentA);
|
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", cs);
|
||||||
|
|
||||||
StringType code = new StringType("ParentA");
|
StringType code = new StringType("ParentA");
|
||||||
StringType system = new StringType("http://snomed.info/sct");
|
StringType system = new StringType("http://snomed.info/sct");
|
||||||
|
@ -818,19 +880,6 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeInUnknownCodeSystem() {
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
|
|
||||||
try {
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
} catch (InvalidRequestException e) {
|
|
||||||
assertEquals("Unable to find imported value set http://example.com/my_value_set", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeBelowBuiltInCodesystem() {
|
public void testSearchCodeBelowBuiltInCodesystem() {
|
||||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||||
|
@ -918,33 +967,6 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSearchCodeBelowLocalCodesystem() {
|
|
||||||
createLocalCsAndVs();
|
|
||||||
|
|
||||||
Observation obsAA = new Observation();
|
|
||||||
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
|
||||||
IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsBA = new Observation();
|
|
||||||
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
|
||||||
IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
Observation obsCA = new Observation();
|
|
||||||
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
|
||||||
IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue()));
|
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
|
||||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW));
|
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeBelowExternalCodesystemLarge() {
|
public void testSearchCodeBelowExternalCodesystemLarge() {
|
||||||
createExternalCsLarge();
|
createExternalCsLarge();
|
||||||
|
@ -975,6 +997,32 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeBelowLocalCodesystem() {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
Observation obsAA = new Observation();
|
||||||
|
obsAA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("AA");
|
||||||
|
IIdType idAA = myObservationDao.create(obsAA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsBA = new Observation();
|
||||||
|
obsBA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("BA");
|
||||||
|
IIdType idBA = myObservationDao.create(obsBA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Observation obsCA = new Observation();
|
||||||
|
obsCA.getCode().addCoding().setSystem(URL_MY_CODE_SYSTEM).setCode("CA");
|
||||||
|
IIdType idCA = myObservationDao.create(obsCA, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "A").setModifier(TokenParamModifier.BELOW));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), containsInAnyOrder(idAA.getValue()));
|
||||||
|
|
||||||
|
params = new SearchParameterMap();
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.BELOW));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeInBuiltInValueSet() {
|
public void testSearchCodeInBuiltInValueSet() {
|
||||||
AllergyIntolerance ai1 = new AllergyIntolerance();
|
AllergyIntolerance ai1 = new AllergyIntolerance();
|
||||||
|
@ -1093,7 +1141,6 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeInLocalCodesystem() {
|
public void testSearchCodeInLocalCodesystem() {
|
||||||
createLocalCsAndVs();
|
createLocalCsAndVs();
|
||||||
|
@ -1116,6 +1163,19 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchCodeInUnknownCodeSystem() {
|
||||||
|
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
|
||||||
|
try {
|
||||||
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
|
assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty());
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Unable to find imported value set http://example.com/my_value_set", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() {
|
public void testSearchCodeInValueSetThatImportsInvalidCodeSystem() {
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
|
@ -1131,7 +1191,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
|
||||||
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN));
|
||||||
try {
|
try {
|
||||||
myObservationDao.search(params);
|
myObservationDao.search(params);
|
||||||
} catch(InvalidRequestException e) {
|
} catch (InvalidRequestException e) {
|
||||||
assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage());
|
assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,7 @@ public class FhirResourceDaoR4UpdateTagSnapshotTest extends BaseJpaR4Test {
|
||||||
myPatientDao.update(p, mySrd);
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
p = myPatientDao.read(new IdType("A"), mySrd);
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
// It would be nice if this didn't trigger a version update but
|
assertEquals("1", p.getIdElement().getVersionIdPart());
|
||||||
// i guess it's not so bad that it does
|
|
||||||
assertEquals("2", p.getIdElement().getVersionIdPart());
|
|
||||||
assertEquals(true, p.getActive());
|
assertEquals(true, p.getActive());
|
||||||
assertEquals(1, p.getMeta().getTag().size());
|
assertEquals(1, p.getMeta().getTag().size());
|
||||||
}
|
}
|
||||||
|
@ -86,9 +84,7 @@ public class FhirResourceDaoR4UpdateTagSnapshotTest extends BaseJpaR4Test {
|
||||||
myPatientDao.update(p, mySrd);
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
p = myPatientDao.read(new IdType("A"), mySrd);
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
// It would be nice if this didn't trigger a version update but
|
assertEquals("1", p.getIdElement().getVersionIdPart());
|
||||||
// i guess it's not so bad that it does
|
|
||||||
assertEquals("2", p.getIdElement().getVersionIdPart());
|
|
||||||
assertEquals(true, p.getActive());
|
assertEquals(true, p.getActive());
|
||||||
assertEquals(1, p.getMeta().getTag().size());
|
assertEquals(1, p.getMeta().getTag().size());
|
||||||
assertEquals("urn:foo", p.getMeta().getTag().get(0).getSystem());
|
assertEquals("urn:foo", p.getMeta().getTag().get(0).getSystem());
|
||||||
|
@ -136,9 +132,7 @@ public class FhirResourceDaoR4UpdateTagSnapshotTest extends BaseJpaR4Test {
|
||||||
p = myPatientDao.read(new IdType("A"), mySrd);
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
assertEquals(true, p.getActive());
|
assertEquals(true, p.getActive());
|
||||||
assertEquals(0, p.getMeta().getTag().size());
|
assertEquals(0, p.getMeta().getTag().size());
|
||||||
// It would be nice if this didn't trigger a version update but
|
assertEquals("1", p.getIdElement().getVersionIdPart());
|
||||||
// i guess it's not so bad that it does
|
|
||||||
assertEquals("2", p.getIdElement().getVersionIdPart());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
|
|
@ -25,7 +25,11 @@ import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.*;
|
import ca.uhn.fhir.rest.server.exceptions.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
|
||||||
|
@TestPropertySource(properties = {
|
||||||
|
"scheduling_disabled=true"
|
||||||
|
})
|
||||||
public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
|
public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UpdateTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UpdateTest.class);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.provider;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
@ -20,10 +21,7 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.*;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.*;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
|
||||||
import ca.uhn.fhir.util.BundleUtil;
|
import ca.uhn.fhir.util.BundleUtil;
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
@ -87,12 +85,12 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
|
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
|
private void checkParamMissing(String paramName) throws IOException {
|
||||||
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
|
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
|
||||||
CloseableHttpResponse resp = ourHttpClient.execute(get);
|
try (CloseableHttpResponse resp = ourHttpClient.execute(get)) {
|
||||||
IOUtils.closeQuietly(resp.getEntity().getContent());
|
|
||||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #484
|
* See #484
|
||||||
|
@ -186,7 +184,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCountParam() throws Exception {
|
public void testCountParam() {
|
||||||
// NB this does not get used- The paging provider has its own limits built in
|
// NB this does not get used- The paging provider has its own limits built in
|
||||||
myDaoConfig.setHardSearchLimit(100);
|
myDaoConfig.setHardSearchLimit(100);
|
||||||
|
|
||||||
|
@ -224,7 +222,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* See #438
|
* See #438
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateAndUpdateBinary() throws ClientProtocolException, Exception {
|
public void testCreateAndUpdateBinary() throws Exception {
|
||||||
byte[] arr = {1, 21, 74, 123, -44};
|
byte[] arr = {1, 21, 74, 123, -44};
|
||||||
Binary binary = new Binary();
|
Binary binary = new Binary();
|
||||||
binary.setContent(arr);
|
binary.setContent(arr);
|
||||||
|
@ -289,7 +287,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateQuestionnaireResponseWithValidation() throws IOException {
|
public void testCreateQuestionnaireResponseWithValidation() {
|
||||||
ValueSet options = new ValueSet();
|
ValueSet options = new ValueSet();
|
||||||
options.getCodeSystem().setSystem("urn:system").addConcept().setCode("code0");
|
options.getCodeSystem().setSystem("urn:system").addConcept().setCode("code0");
|
||||||
IIdType optId = ourClient.create().resource(options).execute().getId();
|
IIdType optId = ourClient.create().resource(options).execute().getId();
|
||||||
|
@ -419,6 +417,27 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateResourceWithNumericId() throws IOException {
|
||||||
|
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
||||||
|
|
||||||
|
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
|
||||||
|
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
|
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||||
|
try {
|
||||||
|
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseString);
|
||||||
|
assertEquals(400, response.getStatusLine().getStatusCode());
|
||||||
|
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
|
||||||
|
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)",
|
||||||
|
oo.getIssue().get(0).getDiagnostics());
|
||||||
|
} finally {
|
||||||
|
response.getEntity().getContent().close();
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// private void delete(String theResourceType, String theParamName, String theParamValue) {
|
// private void delete(String theResourceType, String theParamName, String theParamValue) {
|
||||||
// Bundle resources;
|
// Bundle resources;
|
||||||
// do {
|
// do {
|
||||||
|
@ -445,28 +464,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateResourceWithNumericId() throws IOException {
|
public void testCreateWithForcedId() {
|
||||||
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"></Patient>";
|
|
||||||
|
|
||||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/2");
|
|
||||||
post.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
|
||||||
|
|
||||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
|
||||||
try {
|
|
||||||
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
|
||||||
ourLog.info(responseString);
|
|
||||||
assertEquals(400, response.getStatusLine().getStatusCode());
|
|
||||||
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
|
|
||||||
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)",
|
|
||||||
oo.getIssue().get(0).getDiagnostics());
|
|
||||||
} finally {
|
|
||||||
response.getEntity().getContent().close();
|
|
||||||
response.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateWithForcedId() throws IOException {
|
|
||||||
String methodName = "testCreateWithForcedId";
|
String methodName = "testCreateWithForcedId";
|
||||||
|
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -628,7 +626,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* Based on email from Rene Spronk
|
* Based on email from Rene Spronk
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteResourceConditional2() throws IOException, Exception {
|
public void testDeleteResourceConditional2() throws Exception {
|
||||||
String methodName = "testDeleteResourceConditional2";
|
String methodName = "testDeleteResourceConditional2";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
|
@ -695,7 +693,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* See issue #52
|
* See issue #52
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testDiagnosticOrderResources() throws Exception {
|
public void testDiagnosticOrderResources() {
|
||||||
IGenericClient client = ourClient;
|
IGenericClient client = ourClient;
|
||||||
|
|
||||||
int initialSize = client
|
int initialSize = client
|
||||||
|
@ -787,7 +785,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingEncounterInstance() throws Exception {
|
public void testEverythingEncounterInstance() {
|
||||||
String methodName = "testEverythingEncounterInstance";
|
String methodName = "testEverythingEncounterInstance";
|
||||||
|
|
||||||
Organization org1parent = new Organization();
|
Organization org1parent = new Organization();
|
||||||
|
@ -851,7 +849,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingEncounterType() throws Exception {
|
public void testEverythingEncounterType() {
|
||||||
String methodName = "testEverythingEncounterInstance";
|
String methodName = "testEverythingEncounterInstance";
|
||||||
|
|
||||||
Organization org1parent = new Organization();
|
Organization org1parent = new Organization();
|
||||||
|
@ -951,7 +949,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
List<IIdType> actual;
|
List<IIdType> actual;
|
||||||
StringAndListParam param;
|
StringAndListParam param;
|
||||||
|
|
||||||
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
|
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart());
|
||||||
|
|
||||||
param = new StringAndListParam();
|
param = new StringAndListParam();
|
||||||
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
|
||||||
|
@ -974,7 +972,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* See #147
|
* See #147
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingPatientDoesntRepeatPatient() throws Exception {
|
public void testEverythingPatientDoesntRepeatPatient() {
|
||||||
ca.uhn.fhir.model.dstu2.resource.Bundle b;
|
ca.uhn.fhir.model.dstu2.resource.Bundle b;
|
||||||
b = myFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
|
b = myFhirCtx.newJsonParser().parseResource(ca.uhn.fhir.model.dstu2.resource.Bundle.class, new InputStreamReader(ResourceProviderDstu2Test.class.getResourceAsStream("/bug147-bundle.json")));
|
||||||
|
|
||||||
|
@ -1033,7 +1031,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* Test for #226
|
* Test for #226
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingPatientIncludesBackReferences() throws Exception {
|
public void testEverythingPatientIncludesBackReferences() {
|
||||||
String methodName = "testEverythingIncludesBackReferences";
|
String methodName = "testEverythingIncludesBackReferences";
|
||||||
|
|
||||||
Medication med = new Medication();
|
Medication med = new Medication();
|
||||||
|
@ -1060,7 +1058,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* See #148
|
* See #148
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingPatientIncludesCondition() throws Exception {
|
public void testEverythingPatientIncludesCondition() {
|
||||||
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
ca.uhn.fhir.model.dstu2.resource.Bundle b = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
p.setId("1");
|
p.setId("1");
|
||||||
|
@ -1092,7 +1090,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingPatientOperation() throws Exception {
|
public void testEverythingPatientOperation() {
|
||||||
String methodName = "testEverythingOperation";
|
String methodName = "testEverythingOperation";
|
||||||
|
|
||||||
Organization org1parent = new Organization();
|
Organization org1parent = new Organization();
|
||||||
|
@ -1137,7 +1135,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingPatientType() throws Exception {
|
public void testEverythingPatientType() {
|
||||||
String methodName = "testEverythingPatientType";
|
String methodName = "testEverythingPatientType";
|
||||||
|
|
||||||
Organization o1 = new Organization();
|
Organization o1 = new Organization();
|
||||||
|
@ -1451,7 +1449,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMetaOperations() throws Exception {
|
public void testMetaOperations() {
|
||||||
String methodName = "testMetaOperations";
|
String methodName = "testMetaOperations";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
|
@ -1488,7 +1486,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPagingOverEverythingSet() throws InterruptedException {
|
public void testPagingOverEverythingSet() throws InterruptedException {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -1543,7 +1540,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPagingOverEverythingSetWithNoPagingProvider() throws InterruptedException {
|
public void testPagingOverEverythingSetWithNoPagingProvider() {
|
||||||
ourRestServer.setPagingProvider(null);
|
ourRestServer.setPagingProvider(null);
|
||||||
|
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -1576,11 +1573,30 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessMessage() {
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.setType(BundleTypeEnum.MESSAGE);
|
||||||
|
|
||||||
|
Parameters parameters = new Parameters();
|
||||||
|
parameters.addParameter()
|
||||||
|
.setName("content")
|
||||||
|
.setResource(bundle);
|
||||||
|
try {
|
||||||
|
ourClient.operation().onType(MessageHeader.class).named(JpaConstants.OPERATION_PROCESS_MESSAGE).withParameters(parameters).execute();
|
||||||
|
fail();
|
||||||
|
} catch (NotImplementedOperationException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("This operation is not yet implemented on this server"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for issue #60
|
* Test for issue #60
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testReadAllInstancesOfType() throws Exception {
|
public void testReadAllInstancesOfType() {
|
||||||
Patient pat;
|
Patient pat;
|
||||||
|
|
||||||
pat = new Patient();
|
pat = new Patient();
|
||||||
|
@ -1960,7 +1976,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testSearchReturnsResults(String search) throws IOException, ClientProtocolException {
|
private void testSearchReturnsResults(String search) throws IOException {
|
||||||
int matches;
|
int matches;
|
||||||
HttpGet get = new HttpGet(ourServerBase + search);
|
HttpGet get = new HttpGet(ourServerBase + search);
|
||||||
CloseableHttpResponse response = ourHttpClient.execute(get);
|
CloseableHttpResponse response = ourHttpClient.execute(get);
|
||||||
|
@ -2001,7 +2017,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithInclude() throws Exception {
|
public void testSearchWithInclude() {
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
|
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue("testSearchWithInclude01");
|
||||||
IdDt orgId = (IdDt) ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
IdDt orgId = (IdDt) ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId();
|
||||||
|
@ -2029,7 +2045,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidRequestException.class)
|
@Test(expected = InvalidRequestException.class)
|
||||||
public void testSearchWithInvalidSort() throws Exception {
|
public void testSearchWithInvalidSort() {
|
||||||
Observation o = new Observation();
|
Observation o = new Observation();
|
||||||
o.getCode().setText("testSearchWithInvalidSort");
|
o.getCode().setText("testSearchWithInvalidSort");
|
||||||
myObservationDao.create(o, mySrd);
|
myObservationDao.create(o, mySrd);
|
||||||
|
@ -2042,7 +2058,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithMissing() throws Exception {
|
public void testSearchWithMissing() {
|
||||||
ourLog.info("Starting testSearchWithMissing");
|
ourLog.info("Starting testSearchWithMissing");
|
||||||
|
|
||||||
String methodName = "testSearchWithMissing";
|
String methodName = "testSearchWithMissing";
|
||||||
|
@ -2286,7 +2302,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
* Test for issue #60
|
* Test for issue #60
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testStoreUtf8Characters() throws Exception {
|
public void testStoreUtf8Characters() {
|
||||||
Organization org = new Organization();
|
Organization org = new Organization();
|
||||||
org.setName("測試醫院");
|
org.setName("測試醫院");
|
||||||
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
|
org.addIdentifier().setSystem("urn:system").setValue("testStoreUtf8Characters_01");
|
||||||
|
@ -2340,7 +2356,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateInvalidUrl() throws IOException, Exception {
|
public void testUpdateInvalidUrl() throws Exception {
|
||||||
String methodName = "testUpdateInvalidReference";
|
String methodName = "testUpdateInvalidReference";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
|
@ -2362,7 +2378,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateRejectsInvalidTypes() throws InterruptedException {
|
public void testUpdateRejectsInvalidTypes() {
|
||||||
|
|
||||||
Patient p1 = new Patient();
|
Patient p1 = new Patient();
|
||||||
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
|
p1.addIdentifier().setSystem("urn:system").setValue("testUpdateRejectsInvalidTypes");
|
||||||
|
@ -2467,7 +2483,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateResourceWithPrefer() throws IOException, Exception {
|
public void testUpdateResourceWithPrefer() throws Exception {
|
||||||
String methodName = "testUpdateResourceWithPrefer";
|
String methodName = "testUpdateResourceWithPrefer";
|
||||||
|
|
||||||
Patient pt = new Patient();
|
Patient pt = new Patient();
|
||||||
|
@ -2680,7 +2696,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
|
||||||
|
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addName().addGiven("James" + StringUtils.leftPad("James", 1000000, 'A'));
|
patient.addName().addGiven("James" + StringUtils.leftPad("James", 1000000, 'A'));
|
||||||
;
|
|
||||||
patient.setBirthDate(new DateDt("2011-02-02"));
|
patient.setBirthDate(new DateDt("2011-02-02"));
|
||||||
|
|
||||||
Parameters input = new Parameters();
|
Parameters input = new Parameters();
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
package ca.uhn.fhir.jpa.provider.dstu3;
|
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.dstu3.model.Composition;
|
import org.hl7.fhir.dstu3.model.Composition;
|
||||||
|
import org.hl7.fhir.dstu3.model.MessageHeader;
|
||||||
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class ResourceProviderDstu3BundleTest extends BaseResourceProviderDstu3Test {
|
public class ResourceProviderDstu3BundleTest extends BaseResourceProviderDstu3Test {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3BundleTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3BundleTest.class);
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() {
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #401
|
* See #401
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testBundlePreservesFullUrl() throws Exception {
|
public void testBundlePreservesFullUrl() {
|
||||||
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.setType(BundleType.DOCUMENT);
|
bundle.setType(BundleType.DOCUMENT);
|
||||||
|
@ -42,5 +40,29 @@ public class ResourceProviderDstu3BundleTest extends BaseResourceProviderDstu3Te
|
||||||
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
|
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessMessage() {
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.setType(Bundle.BundleType.MESSAGE);
|
||||||
|
|
||||||
|
Parameters parameters = new Parameters();
|
||||||
|
parameters.addParameter()
|
||||||
|
.setName("content")
|
||||||
|
.setResource(bundle);
|
||||||
|
try {
|
||||||
|
ourClient.operation().onType(MessageHeader.class).named(JpaConstants.OPERATION_PROCESS_MESSAGE).withParameters(parameters).execute();
|
||||||
|
fail();
|
||||||
|
} catch (NotImplementedOperationException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("This operation is not yet implemented on this server"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
|
@ -10,8 +11,11 @@ import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
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.HttpPost;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
|
@ -109,6 +113,16 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createLocalVsWithIncludeConcept() {
|
||||||
|
myLocalVs = new ValueSet();
|
||||||
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
|
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addConcept().setCode("A");
|
||||||
|
include.addConcept().setCode("AA");
|
||||||
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
private void createLocalVsWithUnknownCode(CodeSystem codeSystem) {
|
private void createLocalVsWithUnknownCode(CodeSystem codeSystem) {
|
||||||
myLocalVs = new ValueSet();
|
myLocalVs = new ValueSet();
|
||||||
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
|
@ -172,7 +186,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
* $expand?identifier=foo is legacy.. It's actually not valid in FHIR as of STU3
|
* $expand?identifier=foo is legacy.. It's actually not valid in FHIR as of STU3
|
||||||
* but we supported it for longer than we should have so I don't want to delete
|
* but we supported it for longer than we should have so I don't want to delete
|
||||||
* it right now.
|
* it right now.
|
||||||
*
|
* <p>
|
||||||
* https://groups.google.com/d/msgid/hapi-fhir/CAN2Cfy8kW%2BAOkgC6VjPsU3gRCpExCNZBmJdi-k5R_TWeyWH4tA%40mail.gmail.com?utm_medium=email&utm_source=footer
|
* https://groups.google.com/d/msgid/hapi-fhir/CAN2Cfy8kW%2BAOkgC6VjPsU3gRCpExCNZBmJdi-k5R_TWeyWH4tA%40mail.gmail.com?utm_medium=email&utm_source=footer
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@ -462,6 +476,29 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
createLocalVsWithIncludeConcept();
|
||||||
|
|
||||||
|
String url = ourServerBase +
|
||||||
|
"/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" +
|
||||||
|
UrlUtil.escapeUrlParam(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM) +
|
||||||
|
"&code=AA";
|
||||||
|
|
||||||
|
ourLog.info("* Requesting: {}", url);
|
||||||
|
|
||||||
|
HttpGet request = new HttpGet(url);
|
||||||
|
request.addHeader("Accept", "application/fhir+json");
|
||||||
|
try (CloseableHttpResponse response = ourHttpClient.execute(request)) {
|
||||||
|
String respString = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(respString);
|
||||||
|
|
||||||
|
Parameters respParam = myFhirCtx.newJsonParser().parseResource(Parameters.class, respString);
|
||||||
|
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemType() {
|
public void testValidateCodeOperationByCodeAndSystemType() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
|
|
@ -1,31 +1,29 @@
|
||||||
package ca.uhn.fhir.jpa.provider.r4;
|
package ca.uhn.fhir.jpa.provider.r4;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import org.hl7.fhir.r4.model.MessageHeader;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.r4.model.Composition;
|
import org.hl7.fhir.r4.model.Composition;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test {
|
public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4BundleTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4BundleTest.class);
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void afterClassClearContext() {
|
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #401
|
* See #401
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testBundlePreservesFullUrl() throws Exception {
|
public void testBundlePreservesFullUrl() {
|
||||||
|
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.setType(BundleType.DOCUMENT);
|
bundle.setType(BundleType.DOCUMENT);
|
||||||
|
@ -34,13 +32,38 @@ public class ResourceProviderR4BundleTest extends BaseResourceProviderR4Test {
|
||||||
composition.setTitle("Visit Summary");
|
composition.setTitle("Visit Summary");
|
||||||
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
|
bundle.addEntry().setFullUrl("http://foo").setResource(composition);
|
||||||
|
|
||||||
IIdType id = ourClient.create().resource(bundle).execute().getId();
|
IIdType id = myClient.create().resource(bundle).execute().getId();
|
||||||
|
|
||||||
|
Bundle retBundle = myClient.read().resource(Bundle.class).withId(id).execute();
|
||||||
|
|
||||||
Bundle retBundle = ourClient.read().resource(Bundle.class).withId(id).execute();
|
|
||||||
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
|
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(retBundle));
|
||||||
|
|
||||||
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
|
assertEquals("http://foo", bundle.getEntry().get(0).getFullUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessMessage() {
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.setType(BundleType.MESSAGE);
|
||||||
|
|
||||||
|
Parameters parameters = new Parameters();
|
||||||
|
parameters.addParameter()
|
||||||
|
.setName("content")
|
||||||
|
.setResource(bundle);
|
||||||
|
try {
|
||||||
|
myClient.operation().onType(MessageHeader.class).named(JpaConstants.OPERATION_PROCESS_MESSAGE).withParameters(parameters).execute();
|
||||||
|
fail();
|
||||||
|
} catch (NotImplementedOperationException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("This operation is not yet implemented on this server"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,11 @@ import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
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.HttpPost;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
|
@ -72,7 +75,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createLocalCsAndVs() {
|
private void createLocalCsAndVs() {
|
||||||
//@formatter:off
|
|
||||||
CodeSystem codeSystem = new CodeSystem();
|
CodeSystem codeSystem = new CodeSystem();
|
||||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||||
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
|
||||||
|
@ -86,10 +88,17 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
.addConcept().setCode("B").setDisplay("Code B")
|
.addConcept().setCode("B").setDisplay("Code B")
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA"))
|
.addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA"))
|
||||||
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB"));
|
.addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB"));
|
||||||
//@formatter:on
|
|
||||||
myCodeSystemDao.create(codeSystem, mySrd);
|
myCodeSystemDao.create(codeSystem, mySrd);
|
||||||
|
}
|
||||||
|
|
||||||
createLocalVs(codeSystem);
|
private void createLocalVsWithIncludeConcept() {
|
||||||
|
myLocalVs = new ValueSet();
|
||||||
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
|
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
||||||
|
include.setSystem(URL_MY_CODE_SYSTEM);
|
||||||
|
include.addConcept().setCode("A");
|
||||||
|
include.addConcept().setCode("AA");
|
||||||
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createLocalVs(CodeSystem codeSystem) {
|
private void createLocalVs(CodeSystem codeSystem) {
|
||||||
|
@ -97,7 +106,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
myLocalVs.setUrl(URL_MY_VALUE_SET);
|
||||||
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
ConceptSetComponent include = myLocalVs.getCompose().addInclude();
|
||||||
include.setSystem(codeSystem.getUrl());
|
include.setSystem(codeSystem.getUrl());
|
||||||
include.addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("childAA");
|
include.addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("ParentA");
|
||||||
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +128,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandById() throws IOException {
|
public void testExpandById() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
Parameters respParam = ourClient
|
Parameters respParam = ourClient
|
||||||
.operation()
|
.operation()
|
||||||
|
@ -149,7 +158,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandByIdWithFilter() throws IOException {
|
public void testExpandByIdWithFilter() {
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
Parameters respParam = ourClient
|
Parameters respParam = ourClient
|
||||||
|
@ -208,7 +217,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandInlineVsAgainstBuiltInCs() throws IOException {
|
public void testExpandInlineVsAgainstBuiltInCs() {
|
||||||
createLocalVsPointingAtBuiltInCodeSystem();
|
createLocalVsPointingAtBuiltInCodeSystem();
|
||||||
assertNotNull(myLocalValueSetId);
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
@ -229,7 +238,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandInlineVsAgainstExternalCs() throws IOException {
|
public void testExpandInlineVsAgainstExternalCs() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
assertNotNull(myLocalVs);
|
assertNotNull(myLocalVs);
|
||||||
myLocalVs.setId("");
|
myLocalVs.setId("");
|
||||||
|
@ -304,7 +313,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandLocalVsAgainstBuiltInCs() throws IOException {
|
public void testExpandLocalVsAgainstBuiltInCs() {
|
||||||
createLocalVsPointingAtBuiltInCodeSystem();
|
createLocalVsPointingAtBuiltInCodeSystem();
|
||||||
assertNotNull(myLocalValueSetId);
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
@ -325,7 +334,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandLocalVsAgainstExternalCs() throws IOException {
|
public void testExpandLocalVsAgainstExternalCs() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
assertNotNull(myLocalValueSetId);
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
@ -349,7 +358,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandLocalVsCanonicalAgainstExternalCs() throws IOException {
|
public void testExpandLocalVsCanonicalAgainstExternalCs() {
|
||||||
createExternalCsAndLocalVs();
|
createExternalCsAndLocalVs();
|
||||||
assertNotNull(myLocalValueSetId);
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
@ -373,7 +382,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandLocalVsWithUnknownCode() throws IOException {
|
public void testExpandLocalVsWithUnknownCode() {
|
||||||
createExternalCsAndLocalVsWithUnknownCode();
|
createExternalCsAndLocalVsWithUnknownCode();
|
||||||
assertNotNull(myLocalValueSetId);
|
assertNotNull(myLocalValueSetId);
|
||||||
|
|
||||||
|
@ -400,8 +409,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
HttpPost post = new HttpPost(ourServerBase + "/ValueSet/%24expand");
|
HttpPost post = new HttpPost(ourServerBase + "/ValueSet/%24expand");
|
||||||
post.setEntity(new StringEntity(string, ContentType.parse(ca.uhn.fhir.rest.api.Constants.CT_FHIR_JSON_NEW)));
|
post.setEntity(new StringEntity(string, ContentType.parse(ca.uhn.fhir.rest.api.Constants.CT_FHIR_JSON_NEW)));
|
||||||
|
|
||||||
CloseableHttpResponse resp = ourHttpClient.execute(post);
|
try (CloseableHttpResponse resp = ourHttpClient.execute(post)) {
|
||||||
try {
|
|
||||||
|
|
||||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
ourLog.info(respString);
|
ourLog.info(respString);
|
||||||
|
@ -411,8 +419,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
assertEquals(400, resp.getStatusLine().getStatusCode());
|
assertEquals(400, resp.getStatusLine().getStatusCode());
|
||||||
assertThat(respString, containsString("Unknown FilterOperator code 'n'"));
|
assertThat(respString, containsString("Unknown FilterOperator code 'n'"));
|
||||||
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(resp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +432,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
.withParameter(Parameters.class, "code", new CodeType("8495-4"))
|
.withParameter(Parameters.class, "code", new CodeType("8495-4"))
|
||||||
.andParameter("system", new UriType("http://acme.org"))
|
.andParameter("system", new UriType("http://acme.org"))
|
||||||
.execute();
|
.execute();
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
|
@ -434,6 +439,49 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeOperationByCodeAndSystemInstanceOnType() throws IOException {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
|
||||||
|
String url = ourServerBase +
|
||||||
|
"/ValueSet/$validate-code?system=" +
|
||||||
|
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
||||||
|
"&code=AA";
|
||||||
|
|
||||||
|
HttpGet request = new HttpGet(url);
|
||||||
|
request.addHeader("Accept", "application/fhir+json");
|
||||||
|
try (CloseableHttpResponse response = ourHttpClient.execute(request)) {
|
||||||
|
String respString = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(respString);
|
||||||
|
|
||||||
|
Parameters respParam = myFhirCtx.newJsonParser().parseResource(Parameters.class, respString);
|
||||||
|
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException {
|
||||||
|
createLocalCsAndVs();
|
||||||
|
createLocalVsWithIncludeConcept();
|
||||||
|
|
||||||
|
String url = ourServerBase +
|
||||||
|
"/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" +
|
||||||
|
UrlUtil.escapeUrlParam(URL_MY_CODE_SYSTEM) +
|
||||||
|
"&code=AA";
|
||||||
|
|
||||||
|
ourLog.info("* Requesting: {}", url);
|
||||||
|
|
||||||
|
HttpGet request = new HttpGet(url);
|
||||||
|
request.addHeader("Accept", "application/fhir+json");
|
||||||
|
try (CloseableHttpResponse response = ourHttpClient.execute(request)) {
|
||||||
|
String respString = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(respString);
|
||||||
|
|
||||||
|
Parameters respParam = myFhirCtx.newJsonParser().parseResource(Parameters.class, respString);
|
||||||
|
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeOperationByCodeAndSystemType() {
|
public void testValidateCodeOperationByCodeAndSystemType() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
@ -444,7 +492,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
|
||||||
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
|
||||||
.andParameter("system", new UriType("http://acme.org"))
|
.andParameter("system", new UriType("http://acme.org"))
|
||||||
.execute();
|
.execute();
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||||
ourLog.info(resp);
|
ourLog.info(resp);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.term;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
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.jpa.dao.dstu3.BaseJpaDstu3Test;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
@ -52,17 +53,6 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
.findFirst();
|
.findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Type> Optional<T> getPropertyPart(Parameters theParameters, String thePropName, String thePart) {
|
|
||||||
return theParameters
|
|
||||||
.getParameter()
|
|
||||||
.stream()
|
|
||||||
.filter(t -> t.getName().equals(thePropName))
|
|
||||||
.flatMap(t -> t.getPart().stream())
|
|
||||||
.filter(t -> t.getName().equals(thePart))
|
|
||||||
.map(t -> (T) t.getValue())
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpandWithPropertyCoding() throws Exception {
|
public void testExpandWithPropertyCoding() throws Exception {
|
||||||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
|
@ -169,7 +159,6 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLookupWithProperties2() throws Exception {
|
public void testLookupWithProperties2() throws Exception {
|
||||||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
|
@ -186,10 +175,9 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
assertTrue(propertyValue.isPresent());
|
assertTrue(propertyValue.isPresent());
|
||||||
assertEquals(IHapiTerminologyLoaderSvc.LOINC_URI, propertyValue.get().getSystem());
|
assertEquals(IHapiTerminologyLoaderSvc.LOINC_URI, propertyValue.get().getSystem());
|
||||||
assertEquals("LP19258-0", propertyValue.get().getCode());
|
assertEquals("LP19258-0", propertyValue.get().getCode());
|
||||||
assertEquals("Qn", propertyValue.get().getDisplay());
|
assertEquals("Large unstained cells/100 leukocytes", propertyValue.get().getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLookupWithPropertiesExplicit() throws Exception {
|
public void testLookupWithPropertiesExplicit() throws Exception {
|
||||||
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
|
@ -214,6 +202,30 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeFound() throws Exception {
|
||||||
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
|
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||||
|
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||||
|
|
||||||
|
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(null, null, new StringType("10013-1"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
||||||
|
|
||||||
|
assertTrue(result.isResult());
|
||||||
|
assertEquals("Found code", result.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeNotFound() throws Exception {
|
||||||
|
ZipCollectionBuilder files = new ZipCollectionBuilder();
|
||||||
|
TerminologyLoaderSvcLoincTest.addLoincMandatoryFilesToZip(files);
|
||||||
|
myLoader.loadLoinc(files.getFiles(), mySrd);
|
||||||
|
|
||||||
|
IFhirResourceDaoValueSet.ValidateCodeResult result = myValueSetDao.validateCode(null, null, new StringType("10013-1-9999999999"), new StringType(IHapiTerminologyLoaderSvc.LOINC_URI), null, null, null, mySrd);
|
||||||
|
|
||||||
|
assertFalse(result.isResult());
|
||||||
|
assertEquals("Code not found", result.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
private Set<String> toExpandedCodes(ValueSet theExpanded) {
|
private Set<String> toExpandedCodes(ValueSet theExpanded) {
|
||||||
return theExpanded
|
return theExpanded
|
||||||
.getExpansion()
|
.getExpansion()
|
||||||
|
|
|
@ -137,6 +137,39 @@ drop table cdr_xact_log_step cascade constraints;
|
||||||
drop table cdr_xact_log cascade constraints;
|
drop table cdr_xact_log cascade constraints;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
drop table hfj_history_tag cascade;
|
||||||
|
drop table hfj_forced_id cascade;
|
||||||
|
drop table hfj_res_link cascade;
|
||||||
|
drop table hfj_spidx_coords cascade;
|
||||||
|
drop table hfj_spidx_date cascade;
|
||||||
|
drop table hfj_spidx_number cascade;
|
||||||
|
drop table hfj_spidx_quantity cascade;
|
||||||
|
drop table hfj_spidx_string cascade;
|
||||||
|
drop table hfj_spidx_token cascade;
|
||||||
|
drop table hfj_spidx_uri cascade;
|
||||||
|
drop table hfj_res_tag cascade;
|
||||||
|
drop table hfj_search_result cascade;
|
||||||
|
drop table hfj_search_include cascade;
|
||||||
|
drop table hfj_search cascade;
|
||||||
|
drop table hfj_res_param_present cascade;
|
||||||
|
drop table hfj_idx_cmp_string_uniq cascade;
|
||||||
|
drop table hfj_subscription_stats cascade;
|
||||||
|
drop table trm_concept_property cascade;
|
||||||
|
drop table trm_concept_pc_link cascade;
|
||||||
|
drop table trm_concept cascade;
|
||||||
|
drop table trm_codesystem_ver cascade;
|
||||||
|
drop table trm_codesystem cascade;
|
||||||
|
DROP TABLE hfj_resource cascade;
|
||||||
|
DROP TABLE hfj_res_ver cascade;
|
||||||
|
drop table hfj_search_parm cascade;
|
||||||
|
drop table hfj_tag_def cascade;
|
||||||
|
|
||||||
|
drop index IDX_FORCEDID_TYPE_FORCEDID;
|
||||||
|
alter table hfj_forced_id drop constraint idx_forcedid_type_resid;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Upgrading
|
Upgrading
|
||||||
drop index IDX_SP_STRING;
|
drop index IDX_SP_STRING;
|
||||||
create index IDX_SP_STRING_HASH_NRM;
|
create index IDX_SP_STRING_HASH_NRM;
|
||||||
|
@ -153,6 +186,7 @@ drop index IDX_SP_QUANTITY;
|
||||||
create index IDX_SP_QUANTITY_HASH;
|
create index IDX_SP_QUANTITY_HASH;
|
||||||
create index IDX_SP_QUANTITY_HASH_UN;
|
create index IDX_SP_QUANTITY_HASH_UN;
|
||||||
drop index IDX_FORCEDID_TYPE_FORCEDID;
|
drop index IDX_FORCEDID_TYPE_FORCEDID;
|
||||||
|
alter table hfj_forced_id drop constraint idx_forcedid_type_resid;
|
||||||
create index IDX_FORCEDID_TYPE_FID;
|
create index IDX_FORCEDID_TYPE_FID;
|
||||||
drop index IDX_SP_NUMBER;
|
drop index IDX_SP_NUMBER;
|
||||||
create index IDX_SP_NUMBER_HASH_VAL;
|
create index IDX_SP_NUMBER_HASH_VAL;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -19,6 +20,8 @@ import java.io.Reader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
|
||||||
|
@ -184,6 +187,21 @@ public abstract class RequestDetails {
|
||||||
public void setParameters(Map<String, String[]> theParams) {
|
public void setParameters(Map<String, String[]> theParams) {
|
||||||
myParameters = theParams;
|
myParameters = theParams;
|
||||||
myUnqualifiedToQualifiedNames = null;
|
myUnqualifiedToQualifiedNames = null;
|
||||||
|
|
||||||
|
// Sanitize keys if necessary to prevent injection attacks
|
||||||
|
boolean needsSanitization = false;
|
||||||
|
for (String nextKey : theParams.keySet()) {
|
||||||
|
if (UrlUtil.isNeedsSanitization(nextKey)) {
|
||||||
|
needsSanitization = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needsSanitization) {
|
||||||
|
myParameters = myParameters
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(t -> UrlUtil.sanitizeUrlPart((String) ((Map.Entry) t).getKey()), t -> (String[]) ((Map.Entry) t).getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1246,7 +1246,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
String operation = null;
|
String operation = null;
|
||||||
String compartment = null;
|
String compartment = null;
|
||||||
if (tok.hasMoreTokens()) {
|
if (tok.hasMoreTokens()) {
|
||||||
resourceName = tok.nextToken();
|
resourceName = tok.nextTokenUnescapedAndSanitized();
|
||||||
if (partIsOperation(resourceName)) {
|
if (partIsOperation(resourceName)) {
|
||||||
operation = resourceName;
|
operation = resourceName;
|
||||||
resourceName = null;
|
resourceName = null;
|
||||||
|
@ -1255,7 +1255,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
theRequestDetails.setResourceName(resourceName);
|
theRequestDetails.setResourceName(resourceName);
|
||||||
|
|
||||||
if (tok.hasMoreTokens()) {
|
if (tok.hasMoreTokens()) {
|
||||||
String nextString = tok.nextToken();
|
String nextString = tok.nextTokenUnescapedAndSanitized();
|
||||||
if (partIsOperation(nextString)) {
|
if (partIsOperation(nextString)) {
|
||||||
operation = nextString;
|
operation = nextString;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1265,10 +1265,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok.hasMoreTokens()) {
|
if (tok.hasMoreTokens()) {
|
||||||
String nextString = tok.nextToken();
|
String nextString = tok.nextTokenUnescapedAndSanitized();
|
||||||
if (nextString.equals(Constants.PARAM_HISTORY)) {
|
if (nextString.equals(Constants.PARAM_HISTORY)) {
|
||||||
if (tok.hasMoreTokens()) {
|
if (tok.hasMoreTokens()) {
|
||||||
String versionString = tok.nextToken();
|
String versionString = tok.nextTokenUnescapedAndSanitized();
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw new InvalidRequestException("Don't know how to handle request path: " + theRequestPath);
|
throw new InvalidRequestException("Don't know how to handle request path: " + theRequestPath);
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1290,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
String secondaryOperation = null;
|
String secondaryOperation = null;
|
||||||
|
|
||||||
while (tok.hasMoreTokens()) {
|
while (tok.hasMoreTokens()) {
|
||||||
String nextString = tok.nextToken();
|
String nextString = tok.nextTokenUnescapedAndSanitized();
|
||||||
if (operation == null) {
|
if (operation == null) {
|
||||||
operation = nextString;
|
operation = nextString;
|
||||||
} else if (secondaryOperation == null) {
|
} else if (secondaryOperation == null) {
|
||||||
|
|
|
@ -122,7 +122,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
||||||
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
|
myOtherOperatiopnType = RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
myReturnParams = new ArrayList<OperationMethodBinding.ReturnType>();
|
myReturnParams = new ArrayList<>();
|
||||||
if (theReturnParams != null) {
|
if (theReturnParams != null) {
|
||||||
for (OperationParam next : theReturnParams) {
|
for (OperationParam next : theReturnParams) {
|
||||||
ReturnType type = new ReturnType();
|
ReturnType type = new ReturnType();
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class UrlBaseTenantIdentificationStrategy implements ITenantIdentificatio
|
||||||
public void extractTenant(UrlPathTokenizer theUrlPathTokenizer, RequestDetails theRequestDetails) {
|
public void extractTenant(UrlPathTokenizer theUrlPathTokenizer, RequestDetails theRequestDetails) {
|
||||||
String tenantId = null;
|
String tenantId = null;
|
||||||
if (theUrlPathTokenizer.hasMoreTokens()) {
|
if (theUrlPathTokenizer.hasMoreTokens()) {
|
||||||
tenantId = defaultIfBlank(theUrlPathTokenizer.nextToken(), null);
|
tenantId = defaultIfBlank(theUrlPathTokenizer.nextTokenUnescapedAndSanitized(), null);
|
||||||
ourLog.trace("Found tenant ID {} in request string", tenantId);
|
ourLog.trace("Found tenant ID {} in request string", tenantId);
|
||||||
theRequestDetails.setTenantId(tenantId);
|
theRequestDetails.setTenantId(tenantId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -958,6 +958,8 @@ public class ClientR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithStringIncludes() throws Exception {
|
public void testSearchWithStringIncludes() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.BundleUtil;
|
import ca.uhn.fhir.util.BundleUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.io.input.ReaderInputStream;
|
import org.apache.commons.io.input.ReaderInputStream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -44,6 +45,7 @@ import java.io.StringReader;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -228,7 +230,7 @@ public class GenericClientTest {
|
||||||
|
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -255,7 +257,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -306,7 +308,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -353,7 +355,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -382,7 +384,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -406,7 +408,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(ooStr), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(ooStr), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -523,7 +525,7 @@ public class GenericClientTest {
|
||||||
|
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -543,6 +545,37 @@ public class GenericClientTest {
|
||||||
assertEquals("http://example.com/fhir/Patient?name%3Amissing=false", capt.getValue().getRequestLine().getUri());
|
assertEquals("http://example.com/fhir/Patient?name%3Amissing=false", capt.getValue().getRequestLine().getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProcessMessage() throws IOException {
|
||||||
|
Bundle respBundle = new Bundle();
|
||||||
|
respBundle.setType(BundleType.MESSAGE);
|
||||||
|
String respString = ourCtx.newJsonParser().encodeResourceToString(respBundle);
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
|
||||||
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")));
|
||||||
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[0]);
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.setType(BundleType.MESSAGE);
|
||||||
|
|
||||||
|
Parameters parameters = new Parameters();
|
||||||
|
parameters.addParameter()
|
||||||
|
.setName("content")
|
||||||
|
.setResource(bundle);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
client.operation().onType(MessageHeader.class).named("$process-message").withParameters(parameters).execute();
|
||||||
|
|
||||||
|
assertEquals("http://example.com/fhir/MessageHeader/$process-message", capt.getAllValues().get(count).getURI().toString());
|
||||||
|
String requestContent = IOUtils.toString(((HttpPost) capt.getAllValues().get(count)).getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
assertThat(requestContent, startsWith("<Parameters xmlns=\"http://hl7.org/fhir\">"));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRead() throws Exception {
|
public void testRead() throws Exception {
|
||||||
|
|
||||||
|
@ -633,7 +666,7 @@ public class GenericClientTest {
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||||
Header[] headers = new Header[] { new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"),
|
Header[] headers = new Header[] {new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT"),
|
||||||
new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333"),
|
new BasicHeader(Constants.HEADER_CONTENT_LOCATION, "http://foo.com/Patient/123/_history/2333"),
|
||||||
};
|
};
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
|
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
|
||||||
|
@ -1533,7 +1566,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -1594,7 +1627,7 @@ public class GenericClientTest {
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22") });
|
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
|
|
@ -1587,6 +1587,46 @@ public class AuthorizationInterceptorR4Test {
|
||||||
assertFalse(ourHitMethod);
|
assertFalse(ourHitMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOperationTypeLevelDifferentBodyType() throws Exception {
|
||||||
|
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||||
|
@Override
|
||||||
|
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||||
|
return new RuleBuilder()
|
||||||
|
.allow("RULE 1").operation().named("process-message").onType(MessageHeader.class).andThen()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpPost httpPost;
|
||||||
|
HttpResponse status;
|
||||||
|
String response;
|
||||||
|
|
||||||
|
Bundle input = new Bundle();
|
||||||
|
input.setType(Bundle.BundleType.MESSAGE);
|
||||||
|
String inputString = ourCtx.newJsonParser().encodeResourceToString(input);
|
||||||
|
|
||||||
|
// With body
|
||||||
|
ourHitMethod = false;
|
||||||
|
httpPost = new HttpPost("http://localhost:" + ourPort + "/MessageHeader/$process-message");
|
||||||
|
httpPost.setEntity(new StringEntity(inputString, ContentType.create(Constants.CT_FHIR_JSON_NEW, Charsets.UTF_8)));
|
||||||
|
status = ourClient.execute(httpPost);
|
||||||
|
response = extractResponseAndClose(status);
|
||||||
|
ourLog.info(response);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertTrue(ourHitMethod);
|
||||||
|
|
||||||
|
// With body
|
||||||
|
ourHitMethod = false;
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/MessageHeader/$process-message");
|
||||||
|
status = ourClient.execute(httpGet);
|
||||||
|
response = extractResponseAndClose(status);
|
||||||
|
ourLog.info(response);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertTrue(ourHitMethod);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOperationWithTester() throws Exception {
|
public void testOperationWithTester() throws Exception {
|
||||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||||
|
@ -2946,12 +2986,13 @@ public class AuthorizationInterceptorR4Test {
|
||||||
DummyEncounterResourceProvider encProv = new DummyEncounterResourceProvider();
|
DummyEncounterResourceProvider encProv = new DummyEncounterResourceProvider();
|
||||||
DummyCarePlanResourceProvider cpProv = new DummyCarePlanResourceProvider();
|
DummyCarePlanResourceProvider cpProv = new DummyCarePlanResourceProvider();
|
||||||
DummyDiagnosticReportResourceProvider drProv = new DummyDiagnosticReportResourceProvider();
|
DummyDiagnosticReportResourceProvider drProv = new DummyDiagnosticReportResourceProvider();
|
||||||
|
DummyMessageHeaderResourceProvider mshProv = new DummyMessageHeaderResourceProvider();
|
||||||
PlainProvider plainProvider = new PlainProvider();
|
PlainProvider plainProvider = new PlainProvider();
|
||||||
|
|
||||||
ServletHandler proxyHandler = new ServletHandler();
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
ourServlet.setFhirContext(ourCtx);
|
ourServlet.setFhirContext(ourCtx);
|
||||||
ourServlet.setResourceProviders(patProvider, obsProv, encProv, cpProv, orgProv, drProv);
|
ourServlet.setResourceProviders(patProvider, obsProv, encProv, cpProv, orgProv, drProv, mshProv);
|
||||||
ourServlet.setPlainProviders(plainProvider);
|
ourServlet.setPlainProviders(plainProvider);
|
||||||
ourServlet.setPagingProvider(new FifoMemoryPagingProvider(100));
|
ourServlet.setPagingProvider(new FifoMemoryPagingProvider(100));
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
|
@ -3027,6 +3068,22 @@ public class AuthorizationInterceptorR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class DummyMessageHeaderResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return MessageHeader.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(name = "process-message", idempotent = true)
|
||||||
|
public Parameters operation0(@OperationParam(name="content") Bundle theInput) {
|
||||||
|
ourHitMethod = true;
|
||||||
|
return (Parameters) new Parameters().setId("1");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static class DummyDiagnosticReportResourceProvider implements IResourceProvider {
|
public static class DummyDiagnosticReportResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Read;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class InjectionAttackTest {
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(InjectionAttackTest.class);
|
||||||
|
private static CloseableHttpClient ourClient;
|
||||||
|
private static FhirContext ourCtx = FhirContext.forR4();
|
||||||
|
private static int ourPort;
|
||||||
|
private static Server ourServer;
|
||||||
|
private static RestfulServer ourServlet;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPreventHtmlInjectionViaInvalidContentType() throws Exception {
|
||||||
|
String requestUrl = "http://localhost:" +
|
||||||
|
ourPort +
|
||||||
|
"/Patient/123";
|
||||||
|
|
||||||
|
// XML HTML
|
||||||
|
HttpGet httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, "application/<script>");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPreventHtmlInjectionViaInvalidParameterName() throws Exception {
|
||||||
|
String requestUrl = "http://localhost:" +
|
||||||
|
ourPort +
|
||||||
|
"/Patient?a" +
|
||||||
|
UrlUtil.escapeUrlParam("<script>") +
|
||||||
|
"=123";
|
||||||
|
|
||||||
|
// XML HTML
|
||||||
|
HttpGet httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_HTML + ", " + Constants.CT_FHIR_XML_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals("text/html", status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON HTML
|
||||||
|
httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_HTML + ", " + Constants.CT_FHIR_JSON_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals("text/html", status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// XML HTML
|
||||||
|
httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON Plain
|
||||||
|
httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPreventHtmlInjectionViaInvalidResourceType() throws Exception {
|
||||||
|
String requestUrl = "http://localhost:" +
|
||||||
|
ourPort +
|
||||||
|
"/AA" +
|
||||||
|
UrlUtil.escapeUrlParam("<script>");
|
||||||
|
|
||||||
|
// XML HTML
|
||||||
|
HttpGet httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_HTML + ", " + Constants.CT_FHIR_XML_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(404, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals("text/html", status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON HTML
|
||||||
|
httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_HTML + ", " + Constants.CT_FHIR_JSON_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(404, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals("text/html", status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// XML HTML
|
||||||
|
httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_XML_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(404, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals(Constants.CT_FHIR_XML_NEW, status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON Plain
|
||||||
|
httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, Constants.CT_FHIR_JSON_NEW);
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(404, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
assertEquals(Constants.CT_FHIR_JSON_NEW, status.getFirstHeader("Content-Type").getValue().toLowerCase().replaceAll(";.*", "").trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPreventHtmlInjectionViaInvalidTokenParamModifier() throws Exception {
|
||||||
|
String requestUrl = "http://localhost:" +
|
||||||
|
ourPort +
|
||||||
|
"/Patient?identifier:" +
|
||||||
|
UrlUtil.escapeUrlParam("<script>") +
|
||||||
|
"=123";
|
||||||
|
HttpGet httpGet = new HttpGet(requestUrl);
|
||||||
|
httpGet.addHeader(Constants.HEADER_ACCEPT, "application/<script>");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(responseContent, not(containsString("<script>")));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
ourServer.stop();
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
|
||||||
|
ourPort = PortUtil.findFreePort();
|
||||||
|
ourServer = new Server(ourPort);
|
||||||
|
|
||||||
|
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
|
ourServlet.setFhirContext(ourCtx);
|
||||||
|
ourServlet.setResourceProviders(patientProvider);
|
||||||
|
ourServlet.registerInterceptor(new ResponseHighlighterInterceptor());
|
||||||
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
ourServer.start();
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Patient> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Read
|
||||||
|
public Patient read(@IdParam IdType theId) {
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setId(theId);
|
||||||
|
patient.setActive(true);
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search
|
||||||
|
public List<Patient> search(@OptionalParam(name = "identifier") TokenParam theToken) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,16 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Read;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.param.TokenParam;
|
||||||
|
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
@ -15,29 +20,21 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.util.concurrent.TimeUnit;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import static org.junit.Assert.*;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Read;
|
|
||||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
|
||||||
import ca.uhn.fhir.rest.param.TokenParam;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
|
||||||
import ca.uhn.fhir.util.PortUtil;
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
|
||||||
public class ServerWithResponseHighlightingInterceptorExceptionTest {
|
public class ServerWithResponseHighlightingInterceptorExceptionTest {
|
||||||
private static CloseableHttpClient ourClient;
|
|
||||||
|
|
||||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerWithResponseHighlightingInterceptorExceptionTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerWithResponseHighlightingInterceptorExceptionTest.class);
|
||||||
|
private static CloseableHttpClient ourClient;
|
||||||
|
private static FhirContext ourCtx = FhirContext.forR4();
|
||||||
private static int ourPort;
|
private static int ourPort;
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static RestfulServer ourServlet;
|
private static RestfulServer ourServlet;
|
||||||
|
@ -67,7 +64,6 @@ public class ServerWithResponseHighlightingInterceptorExceptionTest {
|
||||||
assertThat(responseContent, containsString("<diagnostics value=\"Failed to call access method: java.lang.Error: AAABBB\"/>"));
|
assertThat(responseContent, containsString("<diagnostics value=\"Failed to call access method: java.lang.Error: AAABBB\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void afterClassClearContext() throws Exception {
|
public static void afterClassClearContext() throws Exception {
|
||||||
ourServer.stop();
|
ourServer.stop();
|
||||||
|
@ -102,20 +98,21 @@ public class ServerWithResponseHighlightingInterceptorExceptionTest {
|
||||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends IResource> getResourceType() {
|
public Class<? extends Patient> getResourceType() {
|
||||||
return Patient.class;
|
return Patient.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Read
|
@Read
|
||||||
public Patient read(@IdParam IdDt theId) {
|
public Patient read(@IdParam IdType theId) {
|
||||||
throw new InvalidRequestException("AAABBB");
|
throw new InvalidRequestException("AAABBB");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search
|
@Search
|
||||||
public Patient search(@RequiredParam(name="identifier") TokenParam theToken) {
|
public Patient search(@RequiredParam(name = "identifier") TokenParam theToken) {
|
||||||
throw new Error("AAABBB");
|
throw new Error("AAABBB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
public class ${className}ResourceProvider extends
|
public class ${className}ResourceProvider extends
|
||||||
## We have specialized base classes for RPs that handle certain resource types. These
|
## We have specialized base classes for RPs that handle certain resource types. These
|
||||||
## RPs implement type specific operations
|
## RPs implement type specific operations
|
||||||
#if ( $version != 'dstu' && (${className} == 'Encounter' || ${className} == 'Patient' || ${className} == 'Composition' || ${className} == 'ValueSet' || ${className} == 'QuestionnaireAnswers' || ${className} == 'CodeSystem' || ($version != 'dstu2' && ${className} == 'ConceptMap')))
|
#if ( $version != 'dstu' && (${className} == 'Encounter' || ${className} == 'Patient' || ${className} == 'ValueSet' || ${className} == 'QuestionnaireAnswers' || ${className} == 'CodeSystem' || ($version != 'dstu2' && ${className} == 'ConceptMap') || ${className} == 'MessageHeader' || ${className} == 'Composition'))
|
||||||
BaseJpaResourceProvider${className}${versionCapitalized}
|
BaseJpaResourceProvider${className}${versionCapitalized}
|
||||||
#else
|
#else
|
||||||
JpaResourceProvider${versionCapitalized}<${className}>
|
JpaResourceProvider${versionCapitalized}<${className}>
|
||||||
|
|
|
@ -26,11 +26,20 @@ import ca.uhn.fhir.jpa.dao.*;
|
||||||
@Configuration
|
@Configuration
|
||||||
public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jpa.config${package_suffix}.Base${versionCapitalized}Config {
|
public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jpa.config${package_suffix}.Base${versionCapitalized}Config {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses may override
|
||||||
|
*/
|
||||||
|
protected boolean isSupported(String theResourceType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name="myResourceProviders${versionCapitalized}")
|
@Bean(name="myResourceProviders${versionCapitalized}")
|
||||||
public List<IResourceProvider> resourceProviders${versionCapitalized}() {
|
public List<IResourceProvider> resourceProviders${versionCapitalized}() {
|
||||||
List<IResourceProvider> retVal = new ArrayList<IResourceProvider>();
|
List<IResourceProvider> retVal = new ArrayList<IResourceProvider>();
|
||||||
#foreach ( $res in $resources )
|
#foreach ( $res in $resources )
|
||||||
|
if (isSupported("${res.name}")) {
|
||||||
retVal.add(rp${res.declaringClassNameComplete}${versionCapitalized}());
|
retVal.add(rp${res.declaringClassNameComplete}${versionCapitalized}());
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +48,9 @@ public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jp
|
||||||
public List<IFhirResourceDao<?>> resourceDaos${versionCapitalized}() {
|
public List<IFhirResourceDao<?>> resourceDaos${versionCapitalized}() {
|
||||||
List<IFhirResourceDao<?>> retVal = new ArrayList<IFhirResourceDao<?>>();
|
List<IFhirResourceDao<?>> retVal = new ArrayList<IFhirResourceDao<?>>();
|
||||||
#foreach ( $res in $resources )
|
#foreach ( $res in $resources )
|
||||||
|
if (isSupported("${res.name}")) {
|
||||||
retVal.add(dao${res.declaringClassNameComplete}${versionCapitalized}());
|
retVal.add(dao${res.declaringClassNameComplete}${versionCapitalized}());
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +73,7 @@ public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jp
|
||||||
IFhirResourceDaoConceptMap<org.hl7.fhir.dstu3.model.ConceptMap>
|
IFhirResourceDaoConceptMap<org.hl7.fhir.dstu3.model.ConceptMap>
|
||||||
#elseif ( ${versionCapitalized} == 'R4' && ${res.name} == 'ConceptMap' )
|
#elseif ( ${versionCapitalized} == 'R4' && ${res.name} == 'ConceptMap' )
|
||||||
IFhirResourceDaoConceptMap<org.hl7.fhir.r4.model.ConceptMap>
|
IFhirResourceDaoConceptMap<org.hl7.fhir.r4.model.ConceptMap>
|
||||||
#elseif ( ${versionCapitalized} != 'Dstu1' && ( ${res.name} == 'Composition' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'SearchParameter'))
|
#elseif ( ${versionCapitalized} != 'Dstu1' && (${res.name} == 'Composition' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'SearchParameter' || ${res.name} == 'MessageHeader'))
|
||||||
IFhirResourceDao${res.name}<${resourcePackage}.${res.declaringClassNameComplete}>
|
IFhirResourceDao${res.name}<${resourcePackage}.${res.declaringClassNameComplete}>
|
||||||
#else
|
#else
|
||||||
IFhirResourceDao<${resourcePackage}.${res.declaringClassNameComplete}>
|
IFhirResourceDao<${resourcePackage}.${res.declaringClassNameComplete}>
|
||||||
|
@ -72,7 +83,7 @@ public abstract class BaseJavaConfig${versionCapitalized} extends ca.uhn.fhir.jp
|
||||||
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
|
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
|
||||||
#elseif ( ${versionCapitalized} == 'R4' && ${res.name} == 'ConceptMap' )
|
#elseif ( ${versionCapitalized} == 'R4' && ${res.name} == 'ConceptMap' )
|
||||||
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
|
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
|
||||||
#elseif ( ${versionCapitalized} != 'Dstu1' && ( ${res.name} == 'Bundle' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Composition' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'ValueSet' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'SearchParameter' || ${res.name} == 'CodeSystem'))
|
#elseif ( ${res.name} == 'Bundle' || ${res.name} == 'Encounter' || ${res.name} == 'Everything' || ${res.name} == 'Patient' || ${res.name} == 'Subscription' || ${res.name} == 'ValueSet' || ${res.name} == 'QuestionnaireResponse' || ${res.name} == 'SearchParameter' || ${res.name} == 'CodeSystem' || ${res.name} == 'MessageHeader' || ${res.name} == 'Composition')
|
||||||
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
|
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized} retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${res.name}${versionCapitalized}();
|
||||||
#else
|
#else
|
||||||
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${versionCapitalized}<${resourcePackage}.${res.declaringClassNameComplete}> retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${versionCapitalized}<${resourcePackage}.${res.declaringClassNameComplete}>();
|
ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${versionCapitalized}<${resourcePackage}.${res.declaringClassNameComplete}> retVal = new ca.uhn.fhir.jpa.dao${package_suffix}.FhirResourceDao${versionCapitalized}<${resourcePackage}.${res.declaringClassNameComplete}>();
|
||||||
|
|
|
@ -138,6 +138,18 @@
|
||||||
A crash in the JPA server when performing a manual reindex of a deleted resource
|
A crash in the JPA server when performing a manual reindex of a deleted resource
|
||||||
was fixed.
|
was fixed.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Using the generic/fluent client, it is now possible to
|
||||||
|
invoke the $process-message method using a standard
|
||||||
|
client.operation() call. Previously this caused a strange
|
||||||
|
NullPointerException.
|
||||||
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
The REST Server now sanitizes URL path components and query parameter
|
||||||
|
names to escape several reserved characters (e.g. " and <)
|
||||||
|
in order to prevent HTML injection attacks via maliciously
|
||||||
|
crafted URLs.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.4.0" date="2018-05-28">
|
<release version="3.4.0" date="2018-05-28">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue