Merge branch 'master' into rel_4_1_0

This commit is contained in:
James Agnew
2019-11-12 22:37:34 -05:00
13 changed files with 731 additions and 319 deletions

View File

@@ -28,6 +28,10 @@ public class FhirServerConfigCommon {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class);
private Boolean enableIndexMissingFields = HapiProperties.getEnableIndexMissingFields();
private Boolean autoCreatePlaceholderReferenceTargets = HapiProperties.getAutoCreatePlaceholderReferenceTargets();
private Boolean enforceReferentialIntegrityOnWrite = HapiProperties.getEnforceReferentialIntegrityOnWrite();
private Boolean enforceReferentialIntegrityOnDelete = HapiProperties.getEnforceReferentialIntegrityOnDelete();
private Boolean allowContainsSearches = HapiProperties.getAllowContainsSearches();
private Boolean allowMultipleDelete = HapiProperties.getAllowMultipleDelete();
private Boolean allowExternalReferences = HapiProperties.getAllowExternalReferences();
@@ -82,6 +86,10 @@ public class FhirServerConfigCommon {
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
retVal.setIndexMissingFields(this.enableIndexMissingFields ? DaoConfig.IndexEnabledEnum.ENABLED : DaoConfig.IndexEnabledEnum.DISABLED);
retVal.setAutoCreatePlaceholderReferenceTargets(this.autoCreatePlaceholderReferenceTargets);
retVal.setEnforceReferentialIntegrityOnWrite(this.enforceReferentialIntegrityOnWrite);
retVal.setEnforceReferentialIntegrityOnDelete(this.enforceReferentialIntegrityOnDelete);
retVal.setAllowContainsSearches(this.allowContainsSearches);
retVal.setAllowMultipleDelete(this.allowMultipleDelete);
retVal.setAllowExternalReferences(this.allowExternalReferences);

View File

@@ -20,7 +20,11 @@ import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.*;
public class HapiProperties {
public static final String BINARY_STORAGE_ENABLED = "binary_storage.enabled";
static final String ENABLE_INDEX_MISSING_FIELDS = "enable_index_missing_fields";
static final String AUTO_CREATE_PLACEHOLDER_REFERENCE_TARGETS = "auto_create_placeholder_reference_targets";
static final String ENFORCE_REFERENTIAL_INTEGRITY_ON_WRITE = "enforce_referential_integrity_on_write";
static final String ENFORCE_REFERENTIAL_INTEGRITY_ON_DELETE = "enforce_referential_integrity_on_delete";
static final String BINARY_STORAGE_ENABLED = "binary_storage.enabled";
static final String ALLOW_EXTERNAL_REFERENCES = "allow_external_references";
static final String ALLOW_MULTIPLE_DELETE = "allow_multiple_delete";
static final String ALLOW_PLACEHOLDER_REFERENCES = "allow_placeholder_references";
@@ -49,6 +53,7 @@ public class HapiProperties {
static final String SUBSCRIPTION_EMAIL_ENABLED = "subscription.email.enabled";
static final String SUBSCRIPTION_RESTHOOK_ENABLED = "subscription.resthook.enabled";
static final String SUBSCRIPTION_WEBSOCKET_ENABLED = "subscription.websocket.enabled";
static final String ALLOWED_BUNDLE_TYPES = "allowed_bundle_types";
static final String TEST_PORT = "test.port";
static final String TESTER_CONFIG_REFUSE_TO_FETCH_THIRD_PARTY_URLS = "tester.config.refuse_to_fetch_third_party_urls";
static final String CORS_ENABLED = "cors.enabled";
@@ -114,19 +119,19 @@ public class HapiProperties {
@NotNull
private static Properties loadProperties() {
// Load the configurable properties file
// Load the configurable properties file
Properties properties;
try (InputStream in = HapiProperties.class.getClassLoader().getResourceAsStream(HAPI_PROPERTIES)) {
try (InputStream in = HapiProperties.class.getClassLoader().getResourceAsStream(HAPI_PROPERTIES)) {
properties = new Properties();
properties.load(in);
} catch (Exception e) {
throw new ConfigurationException("Could not load HAPI properties", e);
}
} catch (Exception e) {
throw new ConfigurationException("Could not load HAPI properties", e);
}
Properties overrideProps = loadOverrideProperties();
if (overrideProps != null) {
properties.putAll(overrideProps);
}
Properties overrideProps = loadOverrideProperties();
if (overrideProps != null) {
properties.putAll(overrideProps);
}
return properties;
}
@@ -321,6 +326,10 @@ public class HapiProperties {
return HapiProperties.getProperty(CORS_ALLOWED_ORIGIN, "*");
}
public static String getAllowedBundleTypes() {
return HapiProperties.getProperty(ALLOWED_BUNDLE_TYPES, "");
}
public static Set<String> getSupportedResourceTypes() {
String[] types = defaultString(getProperty("supported_resource_types")).split(",");
return Arrays.stream(types)
@@ -407,9 +416,24 @@ public class HapiProperties {
}
public static boolean getGraphqlEnabled() {
return HapiProperties.getBooleanProperty(GRAPHQL_ENABLED, true);
return HapiProperties.getBooleanProperty(GRAPHQL_ENABLED, true);
}
public static boolean getEnforceReferentialIntegrityOnDelete() {
return HapiProperties.getBooleanProperty(ENFORCE_REFERENTIAL_INTEGRITY_ON_DELETE, true);
}
public static boolean getEnforceReferentialIntegrityOnWrite() {
return HapiProperties.getBooleanProperty(ENFORCE_REFERENTIAL_INTEGRITY_ON_WRITE, true);
}
public static boolean getAutoCreatePlaceholderReferenceTargets() {
return HapiProperties.getBooleanProperty(AUTO_CREATE_PLACEHOLDER_REFERENCE_TARGETS, true);
}
public static boolean getEnableIndexMissingFields() {
return HapiProperties.getBooleanProperty(ENABLE_INDEX_MISSING_FIELDS, false);
}
private static boolean getPropertyBoolean(String thePropertyName, boolean theDefaultValue) {
String value = getProperty(thePropertyName, Boolean.toString(theDefaultValue));
return Boolean.parseBoolean(value);

View File

@@ -36,7 +36,10 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import java.util.HashSet;
import java.util.TreeSet;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.Meta;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders;
@@ -49,264 +52,289 @@ import java.util.Set;
public class JpaRestfulServer extends RestfulServer {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
@Override
protected void initialize() throws ServletException {
super.initialize();
@SuppressWarnings("unchecked")
@Override
protected void initialize() throws ServletException {
super.initialize();
/*
* Create a FhirContext object that uses the version of FHIR
* specified in the properties file.
*/
ApplicationContext appCtx = (ApplicationContext) getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
// Customize supported resource types
Set<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
if (!supportedResourceTypes.isEmpty()) {
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
daoRegistry.setSupportedResourceTypes(supportedResourceTypes);
}
/*
* Create a FhirContext object that uses the version of FHIR
* specified in the properties file.
*/
ApplicationContext appCtx = (ApplicationContext) getServletContext()
.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
// Customize supported resource types
Set<String> supportedResourceTypes = HapiProperties.getSupportedResourceTypes();
if (!supportedResourceTypes.isEmpty()) {
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
daoRegistry.setSupportedResourceTypes(supportedResourceTypes);
}
/*
* ResourceProviders are fetched from the Spring context
*/
FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion();
ResourceProviderFactory resourceProviders;
Object systemProvider;
if (fhirVersion == FhirVersionEnum.DSTU2) {
resourceProviders = appCtx.getBean("myResourceProvidersDstu2", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
resourceProviders = appCtx.getBean("myResourceProvidersDstu3", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class);
} else if (fhirVersion == FhirVersionEnum.R4) {
resourceProviders = appCtx.getBean("myResourceProvidersR4", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class);
} else if (fhirVersion == FhirVersionEnum.R5) {
resourceProviders = appCtx.getBean("myResourceProvidersR5", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderR5", JpaSystemProviderR5.class);
} else {
throw new IllegalStateException();
}
/*
* ResourceProviders are fetched from the Spring context
*/
FhirVersionEnum fhirVersion = HapiProperties.getFhirVersion();
ResourceProviderFactory resourceProviders;
Object systemProvider;
if (fhirVersion == FhirVersionEnum.DSTU2) {
resourceProviders = appCtx.getBean("myResourceProvidersDstu2", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class);
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
resourceProviders = appCtx.getBean("myResourceProvidersDstu3", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class);
} else if (fhirVersion == FhirVersionEnum.R4) {
resourceProviders = appCtx.getBean("myResourceProvidersR4", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class);
} else if (fhirVersion == FhirVersionEnum.R5) {
resourceProviders = appCtx.getBean("myResourceProvidersR5", ResourceProviderFactory.class);
systemProvider = appCtx.getBean("mySystemProviderR5", JpaSystemProviderR5.class);
} else {
throw new IllegalStateException();
}
setFhirContext(appCtx.getBean(FhirContext.class));
setFhirContext(appCtx.getBean(FhirContext.class));
registerProviders(resourceProviders.createProviders());
registerProvider(systemProvider);
registerProviders(resourceProviders.createProviders());
registerProvider(systemProvider);
/*
* The conformance provider exports the supported resources, search parameters, etc for
* this server. The JPA version adds resourceProviders counts to the exported statement, so it
* is a nice addition.
*
* You can also create your own subclass of the conformance provider if you need to
* provide further customization of your server's CapabilityStatement
*/
if (fhirVersion == FhirVersionEnum.DSTU2) {
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
IFhirSystemDao<Bundle, Meta> systemDao = appCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.R4) {
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx.getBean("mySystemDaoR4", IFhirSystemDao.class);
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.R5) {
IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx.getBean("mySystemDaoR5", IFhirSystemDao.class);
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao, appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
setServerConformanceProvider(confProvider);
} else {
throw new IllegalStateException();
}
/*
* The conformance provider exports the supported resources, search parameters, etc for
* this server. The JPA version adds resourceProviders counts to the exported statement, so it
* is a nice addition.
*
* You can also create your own subclass of the conformance provider if you need to
* provide further customization of your server's CapabilityStatement
*/
if (fhirVersion == FhirVersionEnum.DSTU2) {
IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDao = appCtx
.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
IFhirSystemDao<Bundle, Meta> systemDao = appCtx
.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.R4) {
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = appCtx
.getBean("mySystemDaoR4", IFhirSystemDao.class);
JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
setServerConformanceProvider(confProvider);
} else if (fhirVersion == FhirVersionEnum.R5) {
IFhirSystemDao<org.hl7.fhir.r5.model.Bundle, org.hl7.fhir.r5.model.Meta> systemDao = appCtx
.getBean("mySystemDaoR5", IFhirSystemDao.class);
JpaConformanceProviderR5 confProvider = new JpaConformanceProviderR5(this, systemDao,
appCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
setServerConformanceProvider(confProvider);
} else {
throw new IllegalStateException();
}
/*
* ETag Support
*/
setETagSupport(HapiProperties.getEtagSupport());
/*
* ETag Support
*/
setETagSupport(HapiProperties.getEtagSupport());
/*
* This server tries to dynamically generate narratives
*/
FhirContext ctx = getFhirContext();
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
/*
* This server tries to dynamically generate narratives
*/
FhirContext ctx = getFhirContext();
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
/*
* Default to JSON and pretty printing
*/
setDefaultPrettyPrint(HapiProperties.getDefaultPrettyPrint());
/*
* Default to JSON and pretty printing
*/
setDefaultPrettyPrint(HapiProperties.getDefaultPrettyPrint());
/*
* Default encoding
*/
setDefaultResponseEncoding(HapiProperties.getDefaultEncoding());
/*
* Default encoding
*/
setDefaultResponseEncoding(HapiProperties.getDefaultEncoding());
/*
* This configures the server to page search results to and from
* the database, instead of only paging them to memory. This may mean
* a performance hit when performing searches that return lots of results,
* but makes the server much more scalable.
*/
setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class));
/*
* This configures the server to page search results to and from
* the database, instead of only paging them to memory. This may mean
* a performance hit when performing searches that return lots of results,
* but makes the server much more scalable.
*/
setPagingProvider(appCtx.getBean(DatabaseBackedPagingProvider.class));
/*
* This interceptor formats the output using nice colourful
* HTML output when the request is detected to come from a
* browser.
*/
ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor();
;
this.registerInterceptor(responseHighlighterInterceptor);
/*
* This interceptor formats the output using nice colourful
* HTML output when the request is detected to come from a
* browser.
*/
ResponseHighlighterInterceptor responseHighlighterInterceptor = new ResponseHighlighterInterceptor();
;
this.registerInterceptor(responseHighlighterInterceptor);
/*
* Add some logging for each request
*/
LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
loggingInterceptor.setLoggerName(HapiProperties.getLoggerName());
loggingInterceptor.setMessageFormat(HapiProperties.getLoggerFormat());
loggingInterceptor.setErrorMessageFormat(HapiProperties.getLoggerErrorFormat());
loggingInterceptor.setLogExceptions(HapiProperties.getLoggerLogExceptions());
this.registerInterceptor(loggingInterceptor);
/*
* Add some logging for each request
*/
LoggingInterceptor loggingInterceptor = new LoggingInterceptor();
loggingInterceptor.setLoggerName(HapiProperties.getLoggerName());
loggingInterceptor.setMessageFormat(HapiProperties.getLoggerFormat());
loggingInterceptor.setErrorMessageFormat(HapiProperties.getLoggerErrorFormat());
loggingInterceptor.setLogExceptions(HapiProperties.getLoggerLogExceptions());
this.registerInterceptor(loggingInterceptor);
/*
* If you are hosting this server at a specific DNS name, the server will try to
* figure out the FHIR base URL based on what the web container tells it, but
* this doesn't always work. If you are setting links in your search bundles that
* just refer to "localhost", you might want to use a server address strategy:
*/
String serverAddress = HapiProperties.getServerAddress();
if (serverAddress != null && serverAddress.length() > 0) {
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
}
/*
* If you are hosting this server at a specific DNS name, the server will try to
* figure out the FHIR base URL based on what the web container tells it, but
* this doesn't always work. If you are setting links in your search bundles that
* just refer to "localhost", you might want to use a server address strategy:
*/
String serverAddress = HapiProperties.getServerAddress();
if (serverAddress != null && serverAddress.length() > 0) {
setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
}
/*
* If you are using DSTU3+, you may want to add a terminology uploader, which allows
* uploading of external terminologies such as Snomed CT. Note that this uploader
* does not have any security attached (any anonymous user may use it by default)
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
* with this feature.
*/
if (false) { // <-- DISABLED RIGHT NOW
registerProvider(appCtx.getBean(TerminologyUploaderProvider.class));
}
/*
* If you are using DSTU3+, you may want to add a terminology uploader, which allows
* uploading of external terminologies such as Snomed CT. Note that this uploader
* does not have any security attached (any anonymous user may use it by default)
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
* with this feature.
*/
if (false) { // <-- DISABLED RIGHT NOW
registerProvider(appCtx.getBean(TerminologyUploaderProvider.class));
}
// If you want to enable the $trigger-subscription operation to allow
// manual triggering of a subscription delivery, enable this provider
if (false) { // <-- DISABLED RIGHT NOW
SubscriptionTriggeringProvider retriggeringProvider = appCtx.getBean(SubscriptionTriggeringProvider.class);
registerProvider(retriggeringProvider);
}
// If you want to enable the $trigger-subscription operation to allow
// manual triggering of a subscription delivery, enable this provider
if (false) { // <-- DISABLED RIGHT NOW
SubscriptionTriggeringProvider retriggeringProvider = appCtx
.getBean(SubscriptionTriggeringProvider.class);
registerProvider(retriggeringProvider);
}
// Define your CORS configuration. This is an example
// showing a typical setup. You should customize this
// to your specific needs
if (HapiProperties.getCorsEnabled()) {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedHeader(HttpHeaders.ORIGIN);
config.addAllowedHeader(HttpHeaders.ACCEPT);
config.addAllowedHeader(HttpHeaders.CONTENT_TYPE);
config.addAllowedHeader(HttpHeaders.AUTHORIZATION);
config.addAllowedHeader(HttpHeaders.CACHE_CONTROL);
config.addAllowedHeader("x-fhir-starter");
config.addAllowedHeader("X-Requested-With");
config.addAllowedHeader("Prefer");
String allAllowedCORSOrigins = HapiProperties.getCorsAllowedOrigin();
Arrays.stream(allAllowedCORSOrigins.split(",")).forEach(o -> {
config.addAllowedOrigin(o);
});
config.addAllowedOrigin(HapiProperties.getCorsAllowedOrigin());
// Define your CORS configuration. This is an example
// showing a typical setup. You should customize this
// to your specific needs
if (HapiProperties.getCorsEnabled()) {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedHeader(HttpHeaders.ORIGIN);
config.addAllowedHeader(HttpHeaders.ACCEPT);
config.addAllowedHeader(HttpHeaders.CONTENT_TYPE);
config.addAllowedHeader(HttpHeaders.AUTHORIZATION);
config.addAllowedHeader(HttpHeaders.CACHE_CONTROL);
config.addAllowedHeader("x-fhir-starter");
config.addAllowedHeader("X-Requested-With");
config.addAllowedHeader("Prefer");
String allAllowedCORSOrigins = HapiProperties.getCorsAllowedOrigin();
Arrays.stream(allAllowedCORSOrigins.split(",")).forEach(o -> {
config.addAllowedOrigin(o);
});
config.addAllowedOrigin(HapiProperties.getCorsAllowedOrigin());
config.addExposedHeader("Location");
config.addExposedHeader("Content-Location");
config.setAllowedMethods(
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
config.addExposedHeader("Location");
config.addExposedHeader("Content-Location");
config.setAllowedMethods(
Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "HEAD"));
config.setAllowCredentials(HapiProperties.getCorsAllowedCredentials());
// Create the interceptor and register it
CorsInterceptor interceptor = new CorsInterceptor(config);
registerInterceptor(interceptor);
}
// Create the interceptor and register it
CorsInterceptor interceptor = new CorsInterceptor(config);
registerInterceptor(interceptor);
}
// If subscriptions are enabled, we want to register the interceptor that
// will activate them and match results against them
if (HapiProperties.getSubscriptionWebsocketEnabled() ||
HapiProperties.getSubscriptionEmailEnabled() ||
HapiProperties.getSubscriptionRestHookEnabled()) {
// Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor)
// with activation of scheduled subscription
SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx.getBean(SubscriptionInterceptorLoader.class);
subscriptionInterceptorLoader.registerInterceptors();
// If subscriptions are enabled, we want to register the interceptor that
// will activate them and match results against them
if (HapiProperties.getSubscriptionWebsocketEnabled() ||
HapiProperties.getSubscriptionEmailEnabled() ||
HapiProperties.getSubscriptionRestHookEnabled()) {
// Loads subscription interceptors (SubscriptionActivatingInterceptor, SubscriptionMatcherInterceptor)
// with activation of scheduled subscription
SubscriptionInterceptorLoader subscriptionInterceptorLoader = appCtx
.getBean(SubscriptionInterceptorLoader.class);
subscriptionInterceptorLoader.registerInterceptors();
// Subscription debug logging
IInterceptorService interceptorService = appCtx.getBean(IInterceptorService.class);
interceptorService.registerInterceptor(new SubscriptionDebugLogInterceptor());
}
// Subscription debug logging
IInterceptorService interceptorService = appCtx.getBean(IInterceptorService.class);
interceptorService.registerInterceptor(new SubscriptionDebugLogInterceptor());
}
// Cascading deletes
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
if (HapiProperties.getAllowCascadingDeletes()) {
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(daoRegistry, interceptorBroadcaster);
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
}
// Cascading deletes
DaoRegistry daoRegistry = appCtx.getBean(DaoRegistry.class);
IInterceptorBroadcaster interceptorBroadcaster = appCtx.getBean(IInterceptorBroadcaster.class);
if (HapiProperties.getAllowCascadingDeletes()) {
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(
daoRegistry, interceptorBroadcaster);
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
}
// Binary Storage
if (HapiProperties.isBinaryStorageEnabled()) {
BinaryStorageInterceptor binaryStorageInterceptor = appCtx.getBean(BinaryStorageInterceptor.class);
getInterceptorService().registerInterceptor(binaryStorageInterceptor);
}
// Binary Storage
if (HapiProperties.isBinaryStorageEnabled()) {
BinaryStorageInterceptor binaryStorageInterceptor = appCtx
.getBean(BinaryStorageInterceptor.class);
getInterceptorService().registerInterceptor(binaryStorageInterceptor);
}
// Validation
IValidatorModule validatorModule;
switch (fhirVersion) {
// Validation
IValidatorModule validatorModule;
switch (fhirVersion) {
case DSTU2:
validatorModule = appCtx.getBean("myInstanceValidatorDstu2", IValidatorModule.class);
break;
case DSTU3:
validatorModule = appCtx.getBean("myInstanceValidatorDstu3", IValidatorModule.class);
break;
case R4:
validatorModule = appCtx.getBean("myInstanceValidatorR4", IValidatorModule.class);
break;
case R5:
validatorModule = appCtx.getBean("myInstanceValidatorR5", IValidatorModule.class);
break;
case DSTU3:
validatorModule = appCtx.getBean("myInstanceValidatorDstu3", IValidatorModule.class);
break;
case R4:
validatorModule = appCtx.getBean("myInstanceValidatorR4", IValidatorModule.class);
break;
case R5:
validatorModule = appCtx.getBean("myInstanceValidatorR5", IValidatorModule.class);
break;
// These versions are not supported by HAPI FHIR JPA
case DSTU2_HL7ORG:
case DSTU2_1:
default:
validatorModule = null;
break;
}
if (validatorModule != null) {
if (HapiProperties.getValidateRequestsEnabled()) {
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
registerInterceptor(interceptor);
}
if (HapiProperties.getValidateResponsesEnabled()) {
ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor();
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
registerInterceptor(interceptor);
}
}
default:
validatorModule = null;
break;
}
if (validatorModule != null) {
if (HapiProperties.getValidateRequestsEnabled()) {
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
registerInterceptor(interceptor);
}
if (HapiProperties.getValidateResponsesEnabled()) {
ResponseValidatingInterceptor interceptor = new ResponseValidatingInterceptor();
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
interceptor.setValidatorModules(Collections.singletonList(validatorModule));
registerInterceptor(interceptor);
}
}
// GraphQL
if (HapiProperties.getGraphqlEnabled()) {
if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
registerProvider(appCtx.getBean(GraphQLProvider.class));
}
}
// GraphQL
if (HapiProperties.getGraphqlEnabled()) {
if (fhirVersion.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
registerProvider(appCtx.getBean(GraphQLProvider.class));
}
}
if (!HapiProperties.getAllowedBundleTypes().isEmpty()) {
String allowedBundleTypesString = HapiProperties.getAllowedBundleTypes();
Set<String> allowedBundleTypes = new HashSet<>();
Arrays.stream(allowedBundleTypesString.split(",")).forEach(o -> {
BundleType type = BundleType.valueOf(o);
allowedBundleTypes.add(type.toCode());
});
DaoConfig config = appCtx.getBean(DaoConfig.class);
config.setBundleTypesAllowedForStorage(
Collections.unmodifiableSet(new TreeSet<>(allowedBundleTypes)));
}
// Bulk Export
if (HapiProperties.getBulkExportEnabled()) {
registerProvider(appCtx.getBean(BulkDataExportProvider.class));