spotless apply formatting
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
package ca.uhn.fhir.jpa.starter;
|
package ca.uhn.fhir.jpa.starter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.ClientIdStrategyEnum;
|
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings.ClientIdStrategyEnum;
|
||||||
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||||
@@ -76,12 +74,13 @@ public class AppProperties {
|
|||||||
private Boolean reload_existing_implementationguides = false;
|
private Boolean reload_existing_implementationguides = false;
|
||||||
private Map<String, PackageInstallationSpec> implementationGuides = null;
|
private Map<String, PackageInstallationSpec> implementationGuides = null;
|
||||||
private Boolean cr_enabled = false;
|
private Boolean cr_enabled = false;
|
||||||
private Boolean ig_runtime_upload_enabled = false;
|
private Boolean ig_runtime_upload_enabled = false;
|
||||||
private String staticLocation = null;
|
private String staticLocation = null;
|
||||||
private String staticLocationPrefix = "/static";
|
private String staticLocationPrefix = "/static";
|
||||||
private Boolean lastn_enabled = false;
|
private Boolean lastn_enabled = false;
|
||||||
private boolean store_resource_in_lucene_index_enabled = false;
|
private boolean store_resource_in_lucene_index_enabled = false;
|
||||||
private NormalizedQuantitySearchLevel normalized_quantity_search_level = NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED;
|
private NormalizedQuantitySearchLevel normalized_quantity_search_level =
|
||||||
|
NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED;
|
||||||
private Boolean use_apache_address_strategy = false;
|
private Boolean use_apache_address_strategy = false;
|
||||||
private Boolean use_apache_address_strategy_https = false;
|
private Boolean use_apache_address_strategy_https = false;
|
||||||
private Integer bundle_batch_pool_size = 20;
|
private Integer bundle_batch_pool_size = 20;
|
||||||
@@ -97,12 +96,10 @@ public class AppProperties {
|
|||||||
this.staticLocationPrefix = staticLocationPrefix;
|
this.staticLocationPrefix = staticLocationPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<String> getCustomInterceptorClasses() {
|
public List<String> getCustomInterceptorClasses() {
|
||||||
return custom_interceptor_classes;
|
return custom_interceptor_classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getStaticLocation() {
|
public String getStaticLocation() {
|
||||||
return staticLocation;
|
return staticLocation;
|
||||||
}
|
}
|
||||||
@@ -111,7 +108,6 @@ public class AppProperties {
|
|||||||
this.staticLocation = staticLocation;
|
this.staticLocation = staticLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Boolean getOpenapi_enabled() {
|
public Boolean getOpenapi_enabled() {
|
||||||
return openapi_enabled;
|
return openapi_enabled;
|
||||||
}
|
}
|
||||||
@@ -168,7 +164,6 @@ public class AppProperties {
|
|||||||
this.ips_enabled = ips_enabled;
|
this.ips_enabled = ips_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Boolean getMdm_enabled() {
|
public Boolean getMdm_enabled() {
|
||||||
return mdm_enabled;
|
return mdm_enabled;
|
||||||
}
|
}
|
||||||
@@ -245,8 +240,7 @@ public class AppProperties {
|
|||||||
return client_id_strategy;
|
return client_id_strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClient_id_strategy(
|
public void setClient_id_strategy(ClientIdStrategyEnum client_id_strategy) {
|
||||||
ClientIdStrategyEnum client_id_strategy) {
|
|
||||||
this.client_id_strategy = client_id_strategy;
|
this.client_id_strategy = client_id_strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,8 +288,7 @@ public class AppProperties {
|
|||||||
return allow_override_default_search_params;
|
return allow_override_default_search_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllow_override_default_search_params(
|
public void setAllow_override_default_search_params(Boolean allow_override_default_search_params) {
|
||||||
Boolean allow_override_default_search_params) {
|
|
||||||
this.allow_override_default_search_params = allow_override_default_search_params;
|
this.allow_override_default_search_params = allow_override_default_search_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,8 +296,7 @@ public class AppProperties {
|
|||||||
return auto_create_placeholder_reference_targets;
|
return auto_create_placeholder_reference_targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuto_create_placeholder_reference_targets(
|
public void setAuto_create_placeholder_reference_targets(Boolean auto_create_placeholder_reference_targets) {
|
||||||
Boolean auto_create_placeholder_reference_targets) {
|
|
||||||
this.auto_create_placeholder_reference_targets = auto_create_placeholder_reference_targets;
|
this.auto_create_placeholder_reference_targets = auto_create_placeholder_reference_targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,8 +356,7 @@ public class AppProperties {
|
|||||||
return enforce_referential_integrity_on_delete;
|
return enforce_referential_integrity_on_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnforce_referential_integrity_on_delete(
|
public void setEnforce_referential_integrity_on_delete(Boolean enforce_referential_integrity_on_delete) {
|
||||||
Boolean enforce_referential_integrity_on_delete) {
|
|
||||||
this.enforce_referential_integrity_on_delete = enforce_referential_integrity_on_delete;
|
this.enforce_referential_integrity_on_delete = enforce_referential_integrity_on_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +364,7 @@ public class AppProperties {
|
|||||||
return enforce_referential_integrity_on_write;
|
return enforce_referential_integrity_on_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnforce_referential_integrity_on_write(
|
public void setEnforce_referential_integrity_on_write(Boolean enforce_referential_integrity_on_write) {
|
||||||
Boolean enforce_referential_integrity_on_write) {
|
|
||||||
this.enforce_referential_integrity_on_write = enforce_referential_integrity_on_write;
|
this.enforce_referential_integrity_on_write = enforce_referential_integrity_on_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,13 +500,11 @@ public class AppProperties {
|
|||||||
this.tester = tester;
|
this.tester = tester;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getNarrative_enabled()
|
public Boolean getNarrative_enabled() {
|
||||||
{
|
|
||||||
return narrative_enabled;
|
return narrative_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNarrative_enabled(Boolean narrative_enabled)
|
public void setNarrative_enabled(Boolean narrative_enabled) {
|
||||||
{
|
|
||||||
this.narrative_enabled = narrative_enabled;
|
this.narrative_enabled = narrative_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,15 +595,14 @@ public class AppProperties {
|
|||||||
public void setAllow_Credentials(Boolean allow_Credentials) {
|
public void setAllow_Credentials(Boolean allow_Credentials) {
|
||||||
this.allow_Credentials = allow_Credentials;
|
this.allow_Credentials = allow_Credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Logger {
|
public static class Logger {
|
||||||
|
|
||||||
private String name = "fhirtest.access";
|
private String name = "fhirtest.access";
|
||||||
private String error_format = "ERROR - ${requestVerb} ${requestUrl}";
|
private String error_format = "ERROR - ${requestVerb} ${requestUrl}";
|
||||||
private String format = "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]";
|
private String format =
|
||||||
|
"Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]";
|
||||||
private Boolean log_exceptions = true;
|
private Boolean log_exceptions = true;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -651,7 +638,6 @@ public class AppProperties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Tester {
|
public static class Tester {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
@@ -692,7 +678,6 @@ public class AppProperties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Validation {
|
public static class Validation {
|
||||||
|
|
||||||
private Boolean requests_enabled = false;
|
private Boolean requests_enabled = false;
|
||||||
@@ -727,6 +712,7 @@ public class AppProperties {
|
|||||||
public void setPartitioning_include_in_search_hashes(Boolean partitioning_include_in_search_hashes) {
|
public void setPartitioning_include_in_search_hashes(Boolean partitioning_include_in_search_hashes) {
|
||||||
this.partitioning_include_in_search_hashes = partitioning_include_in_search_hashes;
|
this.partitioning_include_in_search_hashes = partitioning_include_in_search_hashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getAllow_references_across_partitions() {
|
public Boolean getAllow_references_across_partitions() {
|
||||||
return allow_references_across_partitions;
|
return allow_references_across_partitions;
|
||||||
}
|
}
|
||||||
@@ -766,7 +752,6 @@ public class AppProperties {
|
|||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Email {
|
public static class Email {
|
||||||
public String getFrom() {
|
public String getFrom() {
|
||||||
return from;
|
return from;
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package ca.uhn.fhir.jpa.starter;
|
package ca.uhn.fhir.jpa.starter;
|
||||||
|
|
||||||
import ca.uhn.fhir.batch2.jobs.config.Batch2JobsConfig;
|
import ca.uhn.fhir.batch2.jobs.config.Batch2JobsConfig;
|
||||||
import ca.uhn.fhir.cr.common.IRepositoryFactory;
|
|
||||||
import ca.uhn.fhir.cr.repo.HapiFhirRepository;
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|
||||||
import ca.uhn.fhir.jpa.batch2.JpaBatch2Config;
|
import ca.uhn.fhir.jpa.batch2.JpaBatch2Config;
|
||||||
import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion;
|
import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion;
|
||||||
import ca.uhn.fhir.jpa.starter.cdshooks.StarterCdsHooksConfig;
|
import ca.uhn.fhir.jpa.starter.cdshooks.StarterCdsHooksConfig;
|
||||||
@@ -32,19 +29,19 @@ import org.springframework.context.annotation.Import;
|
|||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
||||||
@ServletComponentScan(basePackageClasses = { RestfulServer.class })
|
@ServletComponentScan(basePackageClasses = {RestfulServer.class})
|
||||||
@SpringBootApplication(exclude = { ElasticsearchRestClientAutoConfiguration.class, ThymeleafAutoConfiguration.class })
|
@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class, ThymeleafAutoConfiguration.class})
|
||||||
@Import({
|
@Import({
|
||||||
StarterCrR4Config.class,
|
StarterCrR4Config.class,
|
||||||
StarterCrDstu3Config.class,
|
StarterCrDstu3Config.class,
|
||||||
StarterCdsHooksConfig.class,
|
StarterCdsHooksConfig.class,
|
||||||
SubscriptionSubmitterConfig.class,
|
SubscriptionSubmitterConfig.class,
|
||||||
SubscriptionProcessorConfig.class,
|
SubscriptionProcessorConfig.class,
|
||||||
SubscriptionChannelConfig.class,
|
SubscriptionChannelConfig.class,
|
||||||
WebsocketDispatcherConfig.class,
|
WebsocketDispatcherConfig.class,
|
||||||
MdmConfig.class,
|
MdmConfig.class,
|
||||||
JpaBatch2Config.class,
|
JpaBatch2Config.class,
|
||||||
Batch2JobsConfig.class
|
Batch2JobsConfig.class
|
||||||
})
|
})
|
||||||
public class Application extends SpringBootServletInitializer {
|
public class Application extends SpringBootServletInitializer {
|
||||||
|
|
||||||
@@ -57,8 +54,7 @@ public class Application extends SpringBootServletInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SpringApplicationBuilder configure(
|
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
|
||||||
SpringApplicationBuilder builder) {
|
|
||||||
return builder.sources(Application.class);
|
return builder.sources(Application.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,11 +76,11 @@ public class Application extends SpringBootServletInitializer {
|
|||||||
@Bean
|
@Bean
|
||||||
public ServletRegistrationBean overlayRegistrationBean() {
|
public ServletRegistrationBean overlayRegistrationBean() {
|
||||||
|
|
||||||
AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
|
AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext =
|
||||||
|
new AnnotationConfigWebApplicationContext();
|
||||||
annotationConfigWebApplicationContext.register(FhirTesterConfig.class);
|
annotationConfigWebApplicationContext.register(FhirTesterConfig.class);
|
||||||
|
|
||||||
DispatcherServlet dispatcherServlet = new DispatcherServlet(
|
DispatcherServlet dispatcherServlet = new DispatcherServlet(annotationConfigWebApplicationContext);
|
||||||
annotationConfigWebApplicationContext);
|
|
||||||
dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
|
dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
|
||||||
dispatcherServlet.setContextConfigLocation(FhirTesterConfig.class.getName());
|
dispatcherServlet.setContextConfigLocation(FhirTesterConfig.class.getName());
|
||||||
|
|
||||||
@@ -93,11 +89,10 @@ public class Application extends SpringBootServletInitializer {
|
|||||||
registrationBean.addUrlMappings("/*");
|
registrationBean.addUrlMappings("/*");
|
||||||
registrationBean.setLoadOnStartup(1);
|
registrationBean.setLoadOnStartup(1);
|
||||||
return registrationBean;
|
return registrationBean;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Bean
|
// @Bean
|
||||||
// IRepositoryFactory repositoryFactory(DaoRegistry theDaoRegistry, RestfulServer theRestfulServer) {
|
// IRepositoryFactory repositoryFactory(DaoRegistry theDaoRegistry, RestfulServer theRestfulServer) {
|
||||||
// return rd -> new HapiFhirRepository(theDaoRegistry, rd, theRestfulServer);
|
// return rd -> new HapiFhirRepository(theDaoRegistry, rd, theRestfulServer);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,33 +19,32 @@ public class ExtraStaticFilesConfigurer implements WebMvcConfigurer {
|
|||||||
public ExtraStaticFilesConfigurer(AppProperties appProperties) {
|
public ExtraStaticFilesConfigurer(AppProperties appProperties) {
|
||||||
|
|
||||||
rootContextPath = appProperties.getStaticLocationPrefix();
|
rootContextPath = appProperties.getStaticLocationPrefix();
|
||||||
if(rootContextPath.endsWith("/"))
|
if (rootContextPath.endsWith("/"))
|
||||||
rootContextPath = rootContextPath.substring(0, rootContextPath.lastIndexOf('/'));
|
rootContextPath = rootContextPath.substring(0, rootContextPath.lastIndexOf('/'));
|
||||||
|
|
||||||
staticLocation = appProperties.getStaticLocation();
|
staticLocation = appProperties.getStaticLocation();
|
||||||
if(staticLocation.endsWith("/"))
|
if (staticLocation.endsWith("/")) staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/'));
|
||||||
staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/'));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
|
||||||
|
theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation);
|
String path = URI.create(staticLocation).getPath();
|
||||||
}
|
String lastSegment = path.substring(path.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
@Override
|
registry.addViewController(rootContextPath)
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
||||||
String path = URI.create(staticLocation).getPath();
|
|
||||||
String lastSegment = path.substring(path.lastIndexOf('/') + 1);
|
|
||||||
|
|
||||||
registry.addViewController(rootContextPath).setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
registry.addViewController(rootContextPath + "/*")
|
||||||
|
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
||||||
|
|
||||||
registry.addViewController(rootContextPath + "/*").setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
registry.addViewController(rootContextPath + "/" + lastSegment + "/")
|
||||||
|
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
||||||
registry.addViewController(rootContextPath + "/" + lastSegment + "/").setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
|
|
||||||
|
|
||||||
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,9 @@ public class OnCorsPresent implements Condition {
|
|||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
|
|
||||||
AppProperties config = Binder.get(conditionContext.getEnvironment()).bind("hapi.fhir", AppProperties.class).orElse(null);
|
AppProperties config = Binder.get(conditionContext.getEnvironment())
|
||||||
|
.bind("hapi.fhir", AppProperties.class)
|
||||||
|
.orElse(null);
|
||||||
if (config == null) return false;
|
if (config == null) return false;
|
||||||
if (config.getCors() == null) return false;
|
if (config.getCors() == null) return false;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
|
|||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
public class OnDSTU2Condition implements Condition {
|
public class OnDSTU2Condition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
|
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
|
||||||
getEnvironment()
|
.getEnvironment()
|
||||||
.getProperty("hapi.fhir.fhir_version")
|
.getProperty("hapi.fhir.fhir_version")
|
||||||
.toUpperCase());
|
.toUpperCase());
|
||||||
|
|
||||||
return version == FhirVersionEnum.DSTU2;
|
return version == FhirVersionEnum.DSTU2;
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
|
|||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
public class OnDSTU3Condition implements Condition {
|
public class OnDSTU3Condition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
|
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
|
||||||
getEnvironment()
|
.getEnvironment()
|
||||||
.getProperty("hapi.fhir.fhir_version")
|
.getProperty("hapi.fhir.fhir_version")
|
||||||
.toUpperCase());
|
.toUpperCase());
|
||||||
|
|
||||||
return version == FhirVersionEnum.DSTU3;
|
return version == FhirVersionEnum.DSTU3;
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,34 +6,28 @@ import org.springframework.context.annotation.Conditional;
|
|||||||
|
|
||||||
public class OnEitherVersion extends AnyNestedCondition {
|
public class OnEitherVersion extends AnyNestedCondition {
|
||||||
|
|
||||||
OnEitherVersion() {
|
OnEitherVersion() {
|
||||||
super(ConfigurationPhase.REGISTER_BEAN);
|
super(ConfigurationPhase.REGISTER_BEAN);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConditionOutcome getFinalMatchOutcome(MemberMatchOutcomes memberOutcomes) {
|
|
||||||
ConditionOutcome result = super.getFinalMatchOutcome(memberOutcomes);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Conditional(OnDSTU2Condition.class)
|
|
||||||
static class OnDSTU2 {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Conditional(OnDSTU3Condition.class)
|
|
||||||
static class OnDSTU3 {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Conditional(OnR4Condition.class)
|
|
||||||
static class OnR4 {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Conditional(OnR4BCondition.class)
|
|
||||||
static class OnR4B {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Conditional(OnR5Condition.class)
|
@Override
|
||||||
static class OnR5 {
|
protected ConditionOutcome getFinalMatchOutcome(MemberMatchOutcomes memberOutcomes) {
|
||||||
}
|
ConditionOutcome result = super.getFinalMatchOutcome(memberOutcomes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Conditional(OnDSTU2Condition.class)
|
||||||
|
static class OnDSTU2 {}
|
||||||
|
|
||||||
|
@Conditional(OnDSTU3Condition.class)
|
||||||
|
static class OnDSTU3 {}
|
||||||
|
|
||||||
|
@Conditional(OnR4Condition.class)
|
||||||
|
static class OnR4 {}
|
||||||
|
|
||||||
|
@Conditional(OnR4BCondition.class)
|
||||||
|
static class OnR4B {}
|
||||||
|
|
||||||
|
@Conditional(OnR5Condition.class)
|
||||||
|
static class OnR5 {}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,9 @@ public class OnImplementationGuidesPresent implements Condition {
|
|||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
|
|
||||||
AppProperties config = Binder.get(conditionContext.getEnvironment()).bind("hapi.fhir", AppProperties.class).orElse(null);
|
AppProperties config = Binder.get(conditionContext.getEnvironment())
|
||||||
|
.bind("hapi.fhir", AppProperties.class)
|
||||||
|
.orElse(null);
|
||||||
if (config == null) return false;
|
if (config == null) return false;
|
||||||
if (config.getImplementationGuides() == null) return false;
|
if (config.getImplementationGuides() == null) return false;
|
||||||
return !config.getImplementationGuides().isEmpty();
|
return !config.getImplementationGuides().isEmpty();
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
|||||||
public class OnR4BCondition implements Condition {
|
public class OnR4BCondition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
String version = conditionContext.
|
String version = conditionContext
|
||||||
getEnvironment()
|
.getEnvironment()
|
||||||
.getProperty("hapi.fhir.fhir_version")
|
.getProperty("hapi.fhir.fhir_version")
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
|
|
||||||
return FhirVersionEnum.R4B.name().equals(version);
|
return FhirVersionEnum.R4B.name().equals(version);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
|
|||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
public class OnR4Condition implements Condition {
|
public class OnR4Condition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
|
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
|
||||||
getEnvironment()
|
.getEnvironment()
|
||||||
.getProperty("hapi.fhir.fhir_version")
|
.getProperty("hapi.fhir.fhir_version")
|
||||||
.toUpperCase());
|
.toUpperCase());
|
||||||
|
|
||||||
return version == FhirVersionEnum.R4;
|
return version == FhirVersionEnum.R4;
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
|
|||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
public class OnR5Condition implements Condition {
|
public class OnR5Condition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
|
FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
|
||||||
getEnvironment()
|
.getEnvironment()
|
||||||
.getProperty("hapi.fhir.fhir_version")
|
.getProperty("hapi.fhir.fhir_version")
|
||||||
.toUpperCase());
|
.toUpperCase());
|
||||||
|
|
||||||
return version == FhirVersionEnum.R5;
|
return version == FhirVersionEnum.R5;
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
|||||||
|
|
||||||
public class CdsHooksConfigCondition implements Condition {
|
public class CdsHooksConfigCondition implements Condition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
|
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
|
||||||
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cdshooks.enabled");
|
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cdshooks.enabled");
|
||||||
return Boolean.parseBoolean(property);
|
return Boolean.parseBoolean(property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,5 @@ package ca.uhn.fhir.jpa.starter.cdshooks;
|
|||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
@JsonIgnoreProperties({ "extension" })
|
@JsonIgnoreProperties({"extension"})
|
||||||
public class CdsHooksRequest extends CdsServiceRequestJson {
|
public class CdsHooksRequest extends CdsServiceRequestJson {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,24 +1,5 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.http.entity.ContentType;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Configurable;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.starter.AppProperties;
|
import ca.uhn.fhir.jpa.starter.AppProperties;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
@@ -26,6 +7,22 @@ import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
|||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServicesJson;
|
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServicesJson;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Configurable;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import static ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig.CDS_HOOKS_OBJECT_MAPPER_FACTORY;
|
import static ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig.CDS_HOOKS_OBJECT_MAPPER_FACTORY;
|
||||||
|
|
||||||
@@ -36,12 +33,16 @@ public class CdsHooksServlet extends HttpServlet {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AppProperties appProperties;
|
private AppProperties appProperties;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProviderConfiguration providerConfiguration;
|
private ProviderConfiguration providerConfiguration;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
ICdsServiceRegistry cdsServiceRegistry;
|
ICdsServiceRegistry cdsServiceRegistry;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
RestfulServer restfulServer;
|
RestfulServer restfulServer;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY)
|
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY)
|
||||||
ObjectMapper objectMapper;
|
ObjectMapper objectMapper;
|
||||||
@@ -70,8 +71,11 @@ public class CdsHooksServlet extends HttpServlet {
|
|||||||
}
|
}
|
||||||
ErrorHandling.setAccessControlHeaders(response, appProperties);
|
ErrorHandling.setAccessControlHeaders(response, appProperties);
|
||||||
response.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType());
|
response.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType());
|
||||||
response.getWriter().println(new GsonBuilder().setPrettyPrinting().create().toJson(
|
response.getWriter()
|
||||||
JsonParser.parseString(objectMapper.writeValueAsString(getServices()))));
|
.println(new GsonBuilder()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
.create()
|
||||||
|
.toJson(JsonParser.parseString(objectMapper.writeValueAsString(getServices()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,8 +83,8 @@ public class CdsHooksServlet extends HttpServlet {
|
|||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
try {
|
try {
|
||||||
if (request.getContentType() == null || !request.getContentType().startsWith("application/json")) {
|
if (request.getContentType() == null || !request.getContentType().startsWith("application/json")) {
|
||||||
throw new ServletException(String.format("Invalid content type %s. Please use application/json.",
|
throw new ServletException(String.format(
|
||||||
request.getContentType()));
|
"Invalid content type %s. Please use application/json.", request.getContentType()));
|
||||||
}
|
}
|
||||||
logger.info(request.getRequestURI());
|
logger.info(request.getRequestURI());
|
||||||
String service = request.getPathInfo().replace("/", "");
|
String service = request.getPathInfo().replace("/", "");
|
||||||
@@ -92,7 +96,10 @@ public class CdsHooksServlet extends HttpServlet {
|
|||||||
CdsServiceResponseJson serviceResponseJson = cdsServiceRegistry.callService(service, cdsHooksRequest);
|
CdsServiceResponseJson serviceResponseJson = cdsServiceRegistry.callService(service, cdsHooksRequest);
|
||||||
|
|
||||||
// Using GSON pretty print format as Jackson's is ugly
|
// Using GSON pretty print format as Jackson's is ugly
|
||||||
String jsonResponse = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create()
|
String jsonResponse = new GsonBuilder()
|
||||||
|
.disableHtmlEscaping()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
.create()
|
||||||
.toJson(JsonParser.parseString(objectMapper.writeValueAsString(serviceResponseJson)));
|
.toJson(JsonParser.parseString(objectMapper.writeValueAsString(serviceResponseJson)));
|
||||||
logger.info(jsonResponse);
|
logger.info(jsonResponse);
|
||||||
response.setContentType("text/json;charset=UTF-8");
|
response.setContentType("text/json;charset=UTF-8");
|
||||||
@@ -111,7 +118,9 @@ public class CdsHooksServlet extends HttpServlet {
|
|||||||
logger.info("cds-hooks hook instance: {}", request.getHookInstance());
|
logger.info("cds-hooks hook instance: {}", request.getHookInstance());
|
||||||
logger.info("cds-hooks local server address: {}", appProperties.getServer_address());
|
logger.info("cds-hooks local server address: {}", appProperties.getServer_address());
|
||||||
logger.info("cds-hooks fhir server address: {}", request.getFhirServer());
|
logger.info("cds-hooks fhir server address: {}", request.getFhirServer());
|
||||||
logger.info("cds-hooks cql_logging_enabled: {}", this.getProviderConfiguration().getCqlLoggingEnabled());
|
logger.info(
|
||||||
|
"cds-hooks cql_logging_enabled: {}",
|
||||||
|
this.getProviderConfiguration().getCqlLoggingEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CdsServicesJson getServices() {
|
private CdsServicesJson getServices() {
|
||||||
|
|||||||
@@ -1,91 +1,105 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.starter.AppProperties;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.starter.AppProperties;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
|
||||||
|
|
||||||
public class ErrorHandling {
|
public class ErrorHandling {
|
||||||
|
|
||||||
private ErrorHandling() {}
|
private ErrorHandling() {}
|
||||||
|
|
||||||
public static void handleError(HttpServletResponse response, String message,
|
public static void handleError(
|
||||||
Exception e, AppProperties myAppProperties)
|
HttpServletResponse response, String message, Exception e, AppProperties myAppProperties)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
setAccessControlHeaders(response, myAppProperties);
|
setAccessControlHeaders(response, myAppProperties);
|
||||||
response.setStatus(500); // This will be overwritten with the correct status code downstream if needed.
|
response.setStatus(500); // This will be overwritten with the correct status code downstream if needed.
|
||||||
response.getWriter().println(message);
|
response.getWriter().println(message);
|
||||||
printMessageAndCause(e, response);
|
printMessageAndCause(e, response);
|
||||||
if (e instanceof BaseServerResponseException) {
|
if (e instanceof BaseServerResponseException) {
|
||||||
handleServerResponseException((BaseServerResponseException) e, response);
|
handleServerResponseException((BaseServerResponseException) e, response);
|
||||||
} else if (e.getCause() instanceof BaseServerResponseException) {
|
} else if (e.getCause() instanceof BaseServerResponseException) {
|
||||||
handleServerResponseException((BaseServerResponseException) e.getCause(), response);
|
handleServerResponseException((BaseServerResponseException) e.getCause(), response);
|
||||||
}
|
}
|
||||||
printStackTrack(e, response);
|
printStackTrack(e, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void handleServerResponseException(BaseServerResponseException e, HttpServletResponse response)
|
private static void handleServerResponseException(BaseServerResponseException e, HttpServletResponse response)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
switch (e.getStatusCode()) {
|
switch (e.getStatusCode()) {
|
||||||
case 401:
|
case 401:
|
||||||
case 403:
|
case 403:
|
||||||
response.getWriter().println("Precondition Failed. Remote FHIR server returned: " + e.getStatusCode());
|
response.getWriter().println("Precondition Failed. Remote FHIR server returned: " + e.getStatusCode());
|
||||||
response.getWriter().println(
|
response.getWriter()
|
||||||
"Ensure that the fhirAuthorization token is set or that the remote server allows unauthenticated access.");
|
.println(
|
||||||
response.setStatus(412);
|
"Ensure that the fhirAuthorization token is set or that the remote server allows unauthenticated access.");
|
||||||
break;
|
response.setStatus(412);
|
||||||
case 404:
|
break;
|
||||||
response.getWriter().println("Precondition Failed. Remote FHIR server returned: " + e.getStatusCode());
|
case 404:
|
||||||
response.getWriter().println("Ensure the resource exists on the remote server.");
|
response.getWriter().println("Precondition Failed. Remote FHIR server returned: " + e.getStatusCode());
|
||||||
response.setStatus(412);
|
response.getWriter().println("Ensure the resource exists on the remote server.");
|
||||||
break;
|
response.setStatus(412);
|
||||||
default:
|
break;
|
||||||
response.getWriter().println("Unhandled Error in Remote FHIR server: " + e.getStatusCode());
|
default:
|
||||||
}
|
response.getWriter().println("Unhandled Error in Remote FHIR server: " + e.getStatusCode());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void printMessageAndCause(Exception e, HttpServletResponse response) throws IOException {
|
private static void printMessageAndCause(Exception e, HttpServletResponse response) throws IOException {
|
||||||
if (e.getMessage() != null) {
|
if (e.getMessage() != null) {
|
||||||
response.getWriter().println(e.getMessage());
|
response.getWriter().println(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.getCause() != null && e.getCause().getMessage() != null) {
|
if (e.getCause() != null && e.getCause().getMessage() != null) {
|
||||||
response.getWriter().println(e.getCause().getMessage());
|
response.getWriter().println(e.getCause().getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printStackTrack(Exception e, HttpServletResponse response) throws IOException {
|
private static void printStackTrack(Exception e, HttpServletResponse response) throws IOException {
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
e.printStackTrace(new PrintWriter(sw));
|
e.printStackTrace(new PrintWriter(sw));
|
||||||
String exceptionAsString = sw.toString();
|
String exceptionAsString = sw.toString();
|
||||||
response.getWriter().println(exceptionAsString);
|
response.getWriter().println(exceptionAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setAccessControlHeaders(HttpServletResponse resp, AppProperties myAppProperties) {
|
public static void setAccessControlHeaders(HttpServletResponse resp, AppProperties myAppProperties) {
|
||||||
if (myAppProperties.getCors() != null) {
|
if (myAppProperties.getCors() != null) {
|
||||||
if (myAppProperties.getCors().getAllow_Credentials()) {
|
if (myAppProperties.getCors().getAllow_Credentials()) {
|
||||||
resp.setHeader("Access-Control-Allow-Origin",
|
resp.setHeader(
|
||||||
myAppProperties.getCors().getAllowed_origin().stream().findFirst().get());
|
"Access-Control-Allow-Origin",
|
||||||
resp.setHeader("Access-Control-Allow-Methods",
|
myAppProperties.getCors().getAllowed_origin().stream()
|
||||||
String.join(", ", Arrays.asList("GET", "HEAD", "POST", "OPTIONS")));
|
.findFirst()
|
||||||
resp.setHeader("Access-Control-Allow-Headers",
|
.get());
|
||||||
String.join(", ", Arrays.asList("x-fhir-starter", "Origin",
|
resp.setHeader(
|
||||||
"Accept", "X-Requested-With", "Content-Type", "Authorization", "Cache-Control")));
|
"Access-Control-Allow-Methods",
|
||||||
resp.setHeader("Access-Control-Expose-Headers",
|
String.join(", ", Arrays.asList("GET", "HEAD", "POST", "OPTIONS")));
|
||||||
String.join(", ", Arrays.asList("Location", "Content-Location")));
|
resp.setHeader(
|
||||||
resp.setHeader("Access-Control-Max-Age", "86400");
|
"Access-Control-Allow-Headers",
|
||||||
}
|
String.join(
|
||||||
}
|
", ",
|
||||||
}
|
Arrays.asList(
|
||||||
|
"x-fhir-starter",
|
||||||
|
"Origin",
|
||||||
|
"Accept",
|
||||||
|
"X-Requested-With",
|
||||||
|
"Content-Type",
|
||||||
|
"Authorization",
|
||||||
|
"Cache-Control")));
|
||||||
|
resp.setHeader(
|
||||||
|
"Access-Control-Expose-Headers",
|
||||||
|
String.join(", ", Arrays.asList("Location", "Content-Location")));
|
||||||
|
resp.setHeader("Access-Control-Max-Age", "86400");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class CdsHooksError extends RuntimeException {
|
public static class CdsHooksError extends RuntimeException {
|
||||||
public CdsHooksError(String message) {
|
public CdsHooksError(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
|||||||
|
|
||||||
public class ProviderConfiguration {
|
public class ProviderConfiguration {
|
||||||
|
|
||||||
public static final ProviderConfiguration DEFAULT_PROVIDER_CONFIGURATION = new ProviderConfiguration(false, "client_id");
|
public static final ProviderConfiguration DEFAULT_PROVIDER_CONFIGURATION =
|
||||||
|
new ProviderConfiguration(false, "client_id");
|
||||||
|
|
||||||
private final String clientIdHeaderName;
|
private final String clientIdHeaderName;
|
||||||
private final boolean cqlLoggingEnabled;
|
private final boolean cqlLoggingEnabled;
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.starter.cr.CrConfigCondition;
|
||||||
|
import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.api.ICdsHooksDaoAuthorizationSvc;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.CdsHooksContextBooter;
|
||||||
|
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrSettings;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||||
@@ -8,15 +14,8 @@ import org.springframework.context.annotation.Conditional;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.starter.cr.CrConfigCondition;
|
|
||||||
import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
|
||||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsHooksDaoAuthorizationSvc;
|
|
||||||
import ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig;
|
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.CdsHooksContextBooter;
|
|
||||||
import ca.uhn.hapi.fhir.cdshooks.svc.cr.CdsCrSettings;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional({ CdsHooksConfigCondition.class, CrConfigCondition.class })
|
@Conditional({CdsHooksConfigCondition.class, CrConfigCondition.class})
|
||||||
@Import(CdsHooksConfig.class)
|
@Import(CdsHooksConfig.class)
|
||||||
public class StarterCdsHooksConfig {
|
public class StarterCdsHooksConfig {
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
@@ -10,18 +10,20 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class ElasticsearchConfig {
|
public class ElasticsearchConfig {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElasticsearchConfig.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElasticsearchConfig.class);
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ElasticsearchSvcImpl elasticsearchSvc(ConfigurableEnvironment configurableEnvironment) {
|
public ElasticsearchSvcImpl elasticsearchSvc(ConfigurableEnvironment configurableEnvironment) {
|
||||||
if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) {
|
if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) {
|
||||||
String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment);
|
String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment);
|
||||||
if (elasticsearchUrl.startsWith("http")) {
|
if (elasticsearchUrl.startsWith("http")) {
|
||||||
elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3);
|
elasticsearchUrl = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3);
|
||||||
}
|
}
|
||||||
String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment);
|
String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment);
|
||||||
String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment);
|
String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment);
|
||||||
String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment);
|
String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment);
|
||||||
ourLog.info("Configuring elasticsearch {} {}", elasticsearchProtocol, elasticsearchUrl);
|
ourLog.info("Configuring elasticsearch {} {}", elasticsearchProtocol, elasticsearchUrl);
|
||||||
return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword);
|
return new ElasticsearchSvcImpl(
|
||||||
|
elasticsearchProtocol, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,8 @@ import ca.uhn.fhir.jpa.subscription.match.deliver.email.EmailSenderImpl;
|
|||||||
import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender;
|
import ca.uhn.fhir.jpa.subscription.match.deliver.email.IEmailSender;
|
||||||
import ca.uhn.fhir.rest.server.mail.MailConfig;
|
import ca.uhn.fhir.rest.server.mail.MailConfig;
|
||||||
import ca.uhn.fhir.rest.server.mail.MailSvc;
|
import ca.uhn.fhir.rest.server.mail.MailSvc;
|
||||||
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import org.cqframework.cql.cql2elm.CqlTranslatorOptions;
|
|
||||||
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
import org.hl7.fhir.r4.model.Bundle.BundleType;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import org.springframework.boot.env.YamlPropertySourceLoader;
|
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -39,21 +35,34 @@ public class FhirServerConfigCommon {
|
|||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirServerConfigCommon.class);
|
||||||
|
|
||||||
public FhirServerConfigCommon(AppProperties appProperties) {
|
public FhirServerConfigCommon(AppProperties appProperties) {
|
||||||
ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny") + " contains searches");
|
ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny")
|
||||||
ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny") + " multiple deletes");
|
+ " contains searches");
|
||||||
ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny") + " external references");
|
ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny")
|
||||||
ourLog.info("Server configured to " + (appProperties.getDao_scheduling_enabled() ? "enable" : "disable") + " DAO scheduling");
|
+ " multiple deletes");
|
||||||
ourLog.info("Server configured to " + (appProperties.getDelete_expunge_enabled() ? "enable" : "disable") + " delete expunges");
|
ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny")
|
||||||
ourLog.info("Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges");
|
+ " external references");
|
||||||
ourLog.info("Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny") + " overriding default search params");
|
ourLog.info("Server configured to " + (appProperties.getDao_scheduling_enabled() ? "enable" : "disable")
|
||||||
ourLog.info("Server configured to " + (appProperties.getAuto_create_placeholder_reference_targets() ? "allow" : "disable") + " auto-creating placeholder references");
|
+ " DAO scheduling");
|
||||||
ourLog.info("Server configured to auto-version references at paths {}", appProperties.getAuto_version_reference_at_paths());
|
ourLog.info("Server configured to " + (appProperties.getDelete_expunge_enabled() ? "enable" : "disable")
|
||||||
|
+ " delete expunges");
|
||||||
|
ourLog.info(
|
||||||
|
"Server configured to " + (appProperties.getExpunge_enabled() ? "enable" : "disable") + " expunges");
|
||||||
|
ourLog.info(
|
||||||
|
"Server configured to " + (appProperties.getAllow_override_default_search_params() ? "allow" : "deny")
|
||||||
|
+ " overriding default search params");
|
||||||
|
ourLog.info("Server configured to "
|
||||||
|
+ (appProperties.getAuto_create_placeholder_reference_targets() ? "allow" : "disable")
|
||||||
|
+ " auto-creating placeholder references");
|
||||||
|
ourLog.info(
|
||||||
|
"Server configured to auto-version references at paths {}",
|
||||||
|
appProperties.getAuto_version_reference_at_paths());
|
||||||
|
|
||||||
if (appProperties.getSubscription().getEmail() != null) {
|
if (appProperties.getSubscription().getEmail() != null) {
|
||||||
AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
|
AppProperties.Subscription.Email email =
|
||||||
ourLog.info(
|
appProperties.getSubscription().getEmail();
|
||||||
"Server is configured to enable email with host '" + email.getHost() + "' and port " + email.getPort());
|
ourLog.info("Server is configured to enable email with host '" + email.getHost() + "' and port "
|
||||||
|
+ email.getPort());
|
||||||
ourLog.info("Server will use '" + email.getFrom() + "' as the from email address");
|
ourLog.info("Server will use '" + email.getFrom() + "' as the from email address");
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty(email.getUsername())) {
|
if (!Strings.isNullOrEmpty(email.getUsername())) {
|
||||||
@@ -85,19 +94,27 @@ public class FhirServerConfigCommon {
|
|||||||
public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {
|
public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {
|
||||||
JpaStorageSettings jpaStorageSettings = new JpaStorageSettings();
|
JpaStorageSettings jpaStorageSettings = new JpaStorageSettings();
|
||||||
|
|
||||||
jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? StorageSettings.IndexEnabledEnum.ENABLED : StorageSettings.IndexEnabledEnum.DISABLED);
|
jpaStorageSettings.setIndexMissingFields(
|
||||||
jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets());
|
appProperties.getEnable_index_missing_fields()
|
||||||
jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths());
|
? StorageSettings.IndexEnabledEnum.ENABLED
|
||||||
jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write());
|
: StorageSettings.IndexEnabledEnum.DISABLED);
|
||||||
jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete());
|
jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(
|
||||||
jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
|
appProperties.getAuto_create_placeholder_reference_targets());
|
||||||
jpaStorageSettings.setAllowMultipleDelete(appProperties.getAllow_multiple_delete());
|
jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths());
|
||||||
jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references());
|
jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(
|
||||||
jpaStorageSettings.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled());
|
appProperties.getEnforce_referential_integrity_on_write());
|
||||||
jpaStorageSettings.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled());
|
jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(
|
||||||
jpaStorageSettings.setExpungeEnabled(appProperties.getExpunge_enabled());
|
appProperties.getEnforce_referential_integrity_on_delete());
|
||||||
if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
|
jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
|
||||||
jpaStorageSettings.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());
|
jpaStorageSettings.setAllowMultipleDelete(appProperties.getAllow_multiple_delete());
|
||||||
|
jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references());
|
||||||
|
jpaStorageSettings.setSchedulingDisabled(!appProperties.getDao_scheduling_enabled());
|
||||||
|
jpaStorageSettings.setDeleteExpungeEnabled(appProperties.getDelete_expunge_enabled());
|
||||||
|
jpaStorageSettings.setExpungeEnabled(appProperties.getExpunge_enabled());
|
||||||
|
if (appProperties.getSubscription() != null
|
||||||
|
&& appProperties.getSubscription().getEmail() != null)
|
||||||
|
jpaStorageSettings.setEmailFromAddress(
|
||||||
|
appProperties.getSubscription().getEmail().getFrom());
|
||||||
|
|
||||||
Integer maxFetchSize = appProperties.getMax_page_size();
|
Integer maxFetchSize = appProperties.getMax_page_size();
|
||||||
jpaStorageSettings.setFetchSizeDefaultMaximum(maxFetchSize);
|
jpaStorageSettings.setFetchSizeDefaultMaximum(maxFetchSize);
|
||||||
@@ -115,13 +132,13 @@ public class FhirServerConfigCommon {
|
|||||||
// Subscriptions are enabled by channel type
|
// Subscriptions are enabled by channel type
|
||||||
if (appProperties.getSubscription().getResthook_enabled()) {
|
if (appProperties.getSubscription().getResthook_enabled()) {
|
||||||
ourLog.info("Enabling REST-hook subscriptions");
|
ourLog.info("Enabling REST-hook subscriptions");
|
||||||
jpaStorageSettings
|
jpaStorageSettings.addSupportedSubscriptionType(
|
||||||
.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
|
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
|
||||||
}
|
}
|
||||||
if (appProperties.getSubscription().getEmail() != null) {
|
if (appProperties.getSubscription().getEmail() != null) {
|
||||||
ourLog.info("Enabling email subscriptions");
|
ourLog.info("Enabling email subscriptions");
|
||||||
jpaStorageSettings
|
jpaStorageSettings.addSupportedSubscriptionType(
|
||||||
.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
|
org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
|
||||||
}
|
}
|
||||||
if (appProperties.getSubscription().getWebsocket_enabled()) {
|
if (appProperties.getSubscription().getWebsocket_enabled()) {
|
||||||
ourLog.info("Enabling websocket subscriptions");
|
ourLog.info("Enabling websocket subscriptions");
|
||||||
@@ -130,120 +147,125 @@ public class FhirServerConfigCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
|
jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
|
||||||
jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing());
|
jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing());
|
||||||
jpaStorageSettings.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls()));
|
jpaStorageSettings.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls()));
|
||||||
|
|
||||||
if (appProperties.getLastn_enabled()) {
|
if (appProperties.getLastn_enabled()) {
|
||||||
jpaStorageSettings.setLastNEnabled(true);
|
jpaStorageSettings.setLastNEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(appProperties.getInline_resource_storage_below_size() != 0){
|
if (appProperties.getInline_resource_storage_below_size() != 0) {
|
||||||
jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size());
|
jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled());
|
jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled());
|
||||||
jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
|
jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
|
||||||
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
|
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
|
||||||
|
|
||||||
|
if (appProperties.getAllowed_bundle_types() != null) {
|
||||||
|
jpaStorageSettings.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream()
|
||||||
|
.map(BundleType::toCode)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
|
||||||
|
jpaStorageSettings.setDeferIndexingForCodesystemsOfSize(
|
||||||
|
appProperties.getDefer_indexing_for_codesystems_of_size());
|
||||||
|
|
||||||
if (appProperties.getAllowed_bundle_types() != null) {
|
if (appProperties.getClient_id_strategy() == JpaStorageSettings.ClientIdStrategyEnum.ANY) {
|
||||||
jpaStorageSettings.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet()));
|
jpaStorageSettings.setResourceServerIdStrategy(JpaStorageSettings.IdStrategyEnum.UUID);
|
||||||
}
|
jpaStorageSettings.setResourceClientIdStrategy(appProperties.getClient_id_strategy());
|
||||||
|
}
|
||||||
|
// Parallel Batch GET execution settings
|
||||||
|
jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size());
|
||||||
|
jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size());
|
||||||
|
|
||||||
jpaStorageSettings.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size());
|
storageSettings(appProperties, jpaStorageSettings);
|
||||||
|
return jpaStorageSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public YamlPropertySourceLoader yamlPropertySourceLoader() {
|
||||||
|
return new YamlPropertySourceLoader();
|
||||||
|
}
|
||||||
|
|
||||||
if (appProperties.getClient_id_strategy() == JpaStorageSettings.ClientIdStrategyEnum.ANY) {
|
@Bean
|
||||||
jpaStorageSettings.setResourceServerIdStrategy(JpaStorageSettings.IdStrategyEnum.UUID);
|
public PartitionSettings partitionSettings(AppProperties appProperties) {
|
||||||
jpaStorageSettings.setResourceClientIdStrategy(appProperties.getClient_id_strategy());
|
PartitionSettings retVal = new PartitionSettings();
|
||||||
}
|
|
||||||
//Parallel Batch GET execution settings
|
|
||||||
jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_size());
|
|
||||||
jpaStorageSettings.setBundleBatchPoolSize(appProperties.getBundle_batch_pool_max_size());
|
|
||||||
|
|
||||||
storageSettings(appProperties, jpaStorageSettings);
|
// Partitioning
|
||||||
return jpaStorageSettings;
|
if (appProperties.getPartitioning() != null) {
|
||||||
}
|
retVal.setPartitioningEnabled(true);
|
||||||
|
retVal.setIncludePartitionInSearchHashes(
|
||||||
|
appProperties.getPartitioning().getPartitioning_include_in_search_hashes());
|
||||||
|
if (appProperties.getPartitioning().getAllow_references_across_partitions()) {
|
||||||
|
retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED);
|
||||||
|
} else {
|
||||||
|
retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
return retVal;
|
||||||
public YamlPropertySourceLoader yamlPropertySourceLoader() {
|
}
|
||||||
return new YamlPropertySourceLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Primary
|
||||||
public PartitionSettings partitionSettings(AppProperties appProperties) {
|
@Bean
|
||||||
PartitionSettings retVal = new PartitionSettings();
|
public HibernatePropertiesProvider jpaStarterDialectProvider(
|
||||||
|
LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
|
||||||
|
return new JpaHibernatePropertiesProvider(myEntityManagerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
// Partitioning
|
protected StorageSettings storageSettings(AppProperties appProperties, JpaStorageSettings jpaStorageSettings) {
|
||||||
if (appProperties.getPartitioning() != null) {
|
jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
|
||||||
retVal.setPartitioningEnabled(true);
|
jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references());
|
||||||
retVal.setIncludePartitionInSearchHashes(appProperties.getPartitioning().getPartitioning_include_in_search_hashes());
|
jpaStorageSettings.setDefaultSearchParamsCanBeOverridden(
|
||||||
if(appProperties.getPartitioning().getAllow_references_across_partitions()) {
|
appProperties.getAllow_override_default_search_params());
|
||||||
retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.ALLOWED_UNQUALIFIED);
|
if (appProperties.getSubscription() != null
|
||||||
} else {
|
&& appProperties.getSubscription().getEmail() != null)
|
||||||
retVal.setAllowReferencesAcrossPartitions(CrossPartitionReferenceMode.NOT_ALLOWED);
|
jpaStorageSettings.setEmailFromAddress(
|
||||||
}
|
appProperties.getSubscription().getEmail().getFrom());
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
|
||||||
}
|
|
||||||
|
|
||||||
|
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
|
||||||
|
jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
|
||||||
|
return jpaStorageSettings;
|
||||||
|
}
|
||||||
|
|
||||||
@Primary
|
@Lazy
|
||||||
@Bean
|
@Bean
|
||||||
public HibernatePropertiesProvider jpaStarterDialectProvider(LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
|
public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
|
||||||
return new JpaHibernatePropertiesProvider(myEntityManagerFactory);
|
DatabaseBlobBinaryStorageSvcImpl binaryStorageSvc = new DatabaseBlobBinaryStorageSvcImpl();
|
||||||
}
|
|
||||||
|
|
||||||
|
if (appProperties.getMax_binary_size() != null) {
|
||||||
|
binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
|
||||||
|
}
|
||||||
|
|
||||||
protected StorageSettings storageSettings(AppProperties appProperties, JpaStorageSettings jpaStorageSettings) {
|
return binaryStorageSvc;
|
||||||
jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
|
}
|
||||||
jpaStorageSettings.setAllowExternalReferences(appProperties.getAllow_external_references());
|
|
||||||
jpaStorageSettings.setDefaultSearchParamsCanBeOverridden(appProperties.getAllow_override_default_search_params());
|
|
||||||
if(appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null)
|
|
||||||
jpaStorageSettings.setEmailFromAddress(appProperties.getSubscription().getEmail().getFrom());
|
|
||||||
|
|
||||||
jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
|
@Bean
|
||||||
|
public IEmailSender emailSender(AppProperties appProperties) {
|
||||||
|
if (appProperties.getSubscription() != null
|
||||||
|
&& appProperties.getSubscription().getEmail() != null) {
|
||||||
|
|
||||||
jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
|
return buildEmailSender(appProperties.getSubscription().getEmail());
|
||||||
jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
|
}
|
||||||
return jpaStorageSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lazy
|
// Return a dummy anonymous function instead of null. Spring does not like null beans.
|
||||||
@Bean
|
// TODO Get the signature of
|
||||||
public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
|
// ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory
|
||||||
DatabaseBlobBinaryStorageSvcImpl binaryStorageSvc = new DatabaseBlobBinaryStorageSvcImpl();
|
// changed so it does not require an instance of an IEmailSender
|
||||||
|
return theDetails -> {};
|
||||||
if (appProperties.getMax_binary_size() != null) {
|
}
|
||||||
binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
|
|
||||||
}
|
|
||||||
|
|
||||||
return binaryStorageSvc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public IEmailSender emailSender(AppProperties appProperties) {
|
|
||||||
if (appProperties.getSubscription() != null && appProperties.getSubscription().getEmail() != null) {
|
|
||||||
|
|
||||||
return buildEmailSender(appProperties.getSubscription().getEmail());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a dummy anonymous function instead of null. Spring does not like null beans.
|
|
||||||
// TODO Get the signature of ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory
|
|
||||||
// changed so it does not require an instance of an IEmailSender
|
|
||||||
return theDetails -> {};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEmailSender buildEmailSender(AppProperties.Subscription.Email email) {
|
private static IEmailSender buildEmailSender(AppProperties.Subscription.Email email) {
|
||||||
|
|
||||||
return new EmailSenderImpl(new MailSvc(new MailConfig()
|
return new EmailSenderImpl(new MailSvc(new MailConfig()
|
||||||
.setSmtpHostname(email.getHost())
|
.setSmtpHostname(email.getHost())
|
||||||
.setSmtpPort(email.getPort())
|
.setSmtpPort(email.getPort())
|
||||||
.setSmtpUsername(email.getUsername())
|
.setSmtpUsername(email.getUsername())
|
||||||
.setSmtpPassword(email.getPassword())
|
.setSmtpPassword(email.getPassword())
|
||||||
.setSmtpUseStartTLS(email.getStartTlsEnable())));
|
.setSmtpUseStartTLS(email.getStartTlsEnable())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,11 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional(OnDSTU2Condition.class)
|
@Conditional(OnDSTU2Condition.class)
|
||||||
@Import({
|
@Import({JpaDstu2Config.class, StarterJpaConfig.class})
|
||||||
JpaDstu2Config.class,
|
|
||||||
StarterJpaConfig.class
|
|
||||||
})
|
|
||||||
public class FhirServerConfigDstu2 {
|
public class FhirServerConfigDstu2 {
|
||||||
@Bean
|
@Bean
|
||||||
public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStorageSvc, ITermCodeSystemStorageSvc theCodeSystemStorageSvc) {
|
public ITermLoaderSvc termLoaderService(
|
||||||
|
ITermDeferredStorageSvc theDeferredStorageSvc, ITermCodeSystemStorageSvc theCodeSystemStorageSvc) {
|
||||||
return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc);
|
return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,5 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional(OnDSTU3Condition.class)
|
@Conditional(OnDSTU3Condition.class)
|
||||||
@Import({
|
@Import({JpaDstu3Config.class, StarterJpaConfig.class, StarterCrDstu3Config.class, ElasticsearchConfig.class})
|
||||||
JpaDstu3Config.class,
|
public class FhirServerConfigDstu3 {}
|
||||||
StarterJpaConfig.class,
|
|
||||||
StarterCrDstu3Config.class,
|
|
||||||
ElasticsearchConfig.class})
|
|
||||||
public class FhirServerConfigDstu3 {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import ca.uhn.fhir.jpa.config.r4.JpaR4Config;
|
|||||||
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
|
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
|
||||||
import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config;
|
import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config;
|
||||||
import ca.uhn.fhir.jpa.starter.ips.StarterIpsConfig;
|
import ca.uhn.fhir.jpa.starter.ips.StarterIpsConfig;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
@@ -18,5 +17,4 @@ import org.springframework.context.annotation.Import;
|
|||||||
ElasticsearchConfig.class,
|
ElasticsearchConfig.class,
|
||||||
StarterIpsConfig.class
|
StarterIpsConfig.class
|
||||||
})
|
})
|
||||||
public class FhirServerConfigR4 {
|
public class FhirServerConfigR4 {}
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,11 +9,5 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional(OnR4BCondition.class)
|
@Conditional(OnR4BCondition.class)
|
||||||
@Import({
|
@Import({JpaR4BConfig.class, SubscriptionTopicConfig.class, StarterJpaConfig.class, ElasticsearchConfig.class})
|
||||||
JpaR4BConfig.class,
|
public class FhirServerConfigR4B {}
|
||||||
SubscriptionTopicConfig.class,
|
|
||||||
StarterJpaConfig.class,
|
|
||||||
ElasticsearchConfig.class
|
|
||||||
})
|
|
||||||
public class FhirServerConfigR4B {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,11 +9,5 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional(OnR5Condition.class)
|
@Conditional(OnR5Condition.class)
|
||||||
@Import({
|
@Import({StarterJpaConfig.class, JpaR5Config.class, SubscriptionTopicConfig.class, ElasticsearchConfig.class})
|
||||||
StarterJpaConfig.class,
|
public class FhirServerConfigR5 {}
|
||||||
JpaR5Config.class,
|
|
||||||
SubscriptionTopicConfig.class,
|
|
||||||
ElasticsearchConfig.class
|
|
||||||
})
|
|
||||||
public class FhirServerConfigR5 {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import ca.uhn.fhir.jpa.starter.AppProperties;
|
|||||||
import ca.uhn.fhir.to.FhirTesterMvcConfig;
|
import ca.uhn.fhir.to.FhirTesterMvcConfig;
|
||||||
import ca.uhn.fhir.to.TesterConfig;
|
import ca.uhn.fhir.to.TesterConfig;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
//@formatter:off
|
// @formatter:off
|
||||||
/**
|
/**
|
||||||
* This spring config file configures the web testing module. It serves two
|
* This spring config file configures the web testing module. It serves two
|
||||||
* purposes:
|
* purposes:
|
||||||
@@ -19,7 +18,7 @@ import org.springframework.context.annotation.Import;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(FhirTesterMvcConfig.class)
|
@Import(FhirTesterMvcConfig.class)
|
||||||
//@Conditional(FhirTesterConfigCondition.class)
|
// @Conditional(FhirTesterConfigCondition.class)
|
||||||
public class FhirTesterConfig {
|
public class FhirTesterConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,22 +35,18 @@ public class FhirTesterConfig {
|
|||||||
* deploying your server to a place with a fully qualified domain name,
|
* deploying your server to a place with a fully qualified domain name,
|
||||||
* you might want to use that instead of using the variable.
|
* you might want to use that instead of using the variable.
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public TesterConfig testerConfig(AppProperties appProperties) {
|
public TesterConfig testerConfig(AppProperties appProperties) {
|
||||||
TesterConfig retVal = new TesterConfig();
|
TesterConfig retVal = new TesterConfig();
|
||||||
appProperties.getTester().forEach((key, value) -> {
|
appProperties.getTester().forEach((key, value) -> {
|
||||||
retVal
|
retVal.addServer()
|
||||||
.addServer()
|
.withId(key)
|
||||||
.withId(key)
|
.withFhirVersion(value.getFhir_version())
|
||||||
.withFhirVersion(value.getFhir_version())
|
.withBaseUrl(value.getServer_address())
|
||||||
.withBaseUrl(value.getServer_address())
|
.withName(value.getName());
|
||||||
.withName(value.getName());
|
retVal.setRefuseToFetchThirdPartyUrls(value.getRefuse_to_fetch_third_party_urls());
|
||||||
retVal.setRefuseToFetchThirdPartyUrls(
|
});
|
||||||
value.getRefuse_to_fetch_third_party_urls());
|
return retVal;
|
||||||
|
}
|
||||||
});
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//@formatter:on
|
// @formatter:on
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ public class FhirTesterConfigCondition implements Condition {
|
|||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
|
|
||||||
var properties = EnvironmentHelper.getPropertiesStartingWith((ConfigurableEnvironment) conditionContext.getEnvironment(), "hapi.fhir.tester");
|
var properties = EnvironmentHelper.getPropertiesStartingWith(
|
||||||
|
(ConfigurableEnvironment) conditionContext.getEnvironment(), "hapi.fhir.tester");
|
||||||
return !properties.isEmpty();
|
return !properties.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.common;
|
package ca.uhn.fhir.jpa.starter.common;
|
||||||
|
|
||||||
import ca.uhn.fhir.batch2.coordinator.JobDefinitionRegistry;
|
import ca.uhn.fhir.batch2.coordinator.JobDefinitionRegistry;
|
||||||
|
import ca.uhn.fhir.batch2.jobs.export.BulkDataExportProvider;
|
||||||
import ca.uhn.fhir.batch2.jobs.imprt.BulkDataImportProvider;
|
import ca.uhn.fhir.batch2.jobs.imprt.BulkDataImportProvider;
|
||||||
import ca.uhn.fhir.batch2.jobs.reindex.ReindexJobParameters;
|
import ca.uhn.fhir.batch2.jobs.reindex.ReindexJobParameters;
|
||||||
import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider;
|
import ca.uhn.fhir.batch2.jobs.reindex.ReindexProvider;
|
||||||
@@ -9,7 +10,6 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||||
|
|
||||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||||
import ca.uhn.fhir.jpa.api.IDaoRegistry;
|
import ca.uhn.fhir.jpa.api.IDaoRegistry;
|
||||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||||
@@ -18,7 +18,6 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor;
|
import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor;
|
||||||
import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider;
|
import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider;
|
||||||
import ca.uhn.fhir.batch2.jobs.export.BulkDataExportProvider;
|
|
||||||
import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil;
|
import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil;
|
||||||
import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil;
|
import ca.uhn.fhir.jpa.config.util.ResourceCountCacheUtil;
|
||||||
import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil;
|
import ca.uhn.fhir.jpa.config.util.ValidationSupportConfigUtil;
|
||||||
@@ -34,8 +33,8 @@ import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
|
|||||||
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
|
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
|
||||||
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
|
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
|
||||||
import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
|
import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
|
||||||
import ca.uhn.fhir.jpa.provider.*;
|
|
||||||
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
|
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
|
||||||
|
import ca.uhn.fhir.jpa.provider.*;
|
||||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||||
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
|
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
|
||||||
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
||||||
@@ -43,8 +42,8 @@ import ca.uhn.fhir.jpa.starter.AppProperties;
|
|||||||
import ca.uhn.fhir.jpa.starter.annotations.OnCorsPresent;
|
import ca.uhn.fhir.jpa.starter.annotations.OnCorsPresent;
|
||||||
import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent;
|
import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent;
|
||||||
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
|
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
|
||||||
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
|
|
||||||
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
|
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
|
||||||
|
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
|
||||||
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
|
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
|
||||||
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
import ca.uhn.fhir.jpa.util.ResourceCountCache;
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
||||||
@@ -53,9 +52,9 @@ import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
|||||||
import ca.uhn.fhir.narrative2.NullNarrativeGenerator;
|
import ca.uhn.fhir.narrative2.NullNarrativeGenerator;
|
||||||
import ca.uhn.fhir.rest.api.IResourceSupportedSvc;
|
import ca.uhn.fhir.rest.api.IResourceSupportedSvc;
|
||||||
import ca.uhn.fhir.rest.openapi.OpenApiInterceptor;
|
import ca.uhn.fhir.rest.openapi.OpenApiInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.*;
|
import ca.uhn.fhir.rest.server.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.*;
|
import ca.uhn.fhir.rest.server.interceptor.*;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
|
|
||||||
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
||||||
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
|
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
|
||||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||||
@@ -75,18 +74,16 @@ import org.springframework.orm.jpa.JpaTransactionManager;
|
|||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR;
|
import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
//allow users to configure custom packages to scan for additional beans
|
// allow users to configure custom packages to scan for additional beans
|
||||||
@ComponentScan(basePackages = { "${hapi.fhir.custom-bean-packages:}" })
|
@ComponentScan(basePackages = {"${hapi.fhir.custom-bean-packages:}"})
|
||||||
@Import(
|
@Import(ThreadPoolFactoryConfig.class)
|
||||||
ThreadPoolFactoryConfig.class
|
|
||||||
)
|
|
||||||
public class StarterJpaConfig {
|
public class StarterJpaConfig {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StarterJpaConfig.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StarterJpaConfig.class);
|
||||||
@@ -107,12 +104,9 @@ public class StarterJpaConfig {
|
|||||||
return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain);
|
return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConfigurableEnvironment configurableEnvironment;
|
private ConfigurableEnvironment configurableEnvironment;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customize the default/max page sizes for search results. You can set these however
|
* Customize the default/max page sizes for search results. You can set these however
|
||||||
* you want, although very large page sizes will require a lot of RAM.
|
* you want, although very large page sizes will require a lot of RAM.
|
||||||
@@ -125,7 +119,6 @@ public class StarterJpaConfig {
|
|||||||
return pagingProvider;
|
return pagingProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) {
|
public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) {
|
||||||
return new DaoRegistryResourceSupportedSvc(theDaoRegistry);
|
return new DaoRegistryResourceSupportedSvc(theDaoRegistry);
|
||||||
@@ -138,8 +131,12 @@ public class StarterJpaConfig {
|
|||||||
|
|
||||||
@Primary
|
@Primary
|
||||||
@Bean
|
@Bean
|
||||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource myDataSource, ConfigurableListableBeanFactory myConfigurableListableBeanFactory, FhirContext theFhirContext) {
|
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
|
||||||
LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext);
|
DataSource myDataSource,
|
||||||
|
ConfigurableListableBeanFactory myConfigurableListableBeanFactory,
|
||||||
|
FhirContext theFhirContext) {
|
||||||
|
LocalContainerEntityManagerFactoryBean retVal =
|
||||||
|
HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext);
|
||||||
retVal.setPersistenceUnitName("HAPI_PU");
|
retVal.setPersistenceUnitName("HAPI_PU");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -147,7 +144,8 @@ public class StarterJpaConfig {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ConfigurationException("Could not set the data source due to a configuration issue", e);
|
throw new ConfigurationException("Could not set the data source due to a configuration issue", e);
|
||||||
}
|
}
|
||||||
retVal.setJpaProperties(EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory));
|
retVal.setJpaProperties(
|
||||||
|
EnvironmentHelper.getHibernateProperties(configurableEnvironment, myConfigurableListableBeanFactory));
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,10 +162,10 @@ public class StarterJpaConfig {
|
|||||||
return new HSearchSortHelperImpl(mySearchParamRegistry);
|
return new HSearchSortHelperImpl(mySearchParamRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true")
|
@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true")
|
||||||
public RepositoryValidatingInterceptor repositoryValidatingInterceptor(IRepositoryValidationInterceptorFactory factory) {
|
public RepositoryValidatingInterceptor repositoryValidatingInterceptor(
|
||||||
|
IRepositoryValidationInterceptorFactory factory) {
|
||||||
return factory.buildUsingStoredStructureDefinitions();
|
return factory.buildUsingStoredStructureDefinitions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,8 +187,11 @@ public class StarterJpaConfig {
|
|||||||
@Bean("packageInstaller")
|
@Bean("packageInstaller")
|
||||||
@Primary
|
@Primary
|
||||||
@Conditional(OnImplementationGuidesPresent.class)
|
@Conditional(OnImplementationGuidesPresent.class)
|
||||||
public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDefinition<ReindexJobParameters> reindexJobParametersJobDefinition, JobDefinitionRegistry jobDefinitionRegistry, IPackageInstallerSvc packageInstallerSvc)
|
public IPackageInstallerSvc packageInstaller(
|
||||||
{
|
AppProperties appProperties,
|
||||||
|
JobDefinition<ReindexJobParameters> reindexJobParametersJobDefinition,
|
||||||
|
JobDefinitionRegistry jobDefinitionRegistry,
|
||||||
|
IPackageInstallerSvc packageInstallerSvc) {
|
||||||
jobDefinitionRegistry.addJobDefinitionIfNotRegistered(reindexJobParametersJobDefinition);
|
jobDefinitionRegistry.addJobDefinitionIfNotRegistered(reindexJobParametersJobDefinition);
|
||||||
|
|
||||||
if (appProperties.getImplementationGuides() != null) {
|
if (appProperties.getImplementationGuides() != null) {
|
||||||
@@ -199,10 +200,11 @@ public class StarterJpaConfig {
|
|||||||
PackageInstallationSpec packageInstallationSpec = guidesEntry.getValue();
|
PackageInstallationSpec packageInstallationSpec = guidesEntry.getValue();
|
||||||
if (appProperties.getInstall_transitive_ig_dependencies()) {
|
if (appProperties.getInstall_transitive_ig_dependencies()) {
|
||||||
|
|
||||||
packageInstallationSpec.addDependencyExclude("hl7.fhir.r2.core")
|
packageInstallationSpec
|
||||||
.addDependencyExclude("hl7.fhir.r3.core")
|
.addDependencyExclude("hl7.fhir.r2.core")
|
||||||
.addDependencyExclude("hl7.fhir.r4.core")
|
.addDependencyExclude("hl7.fhir.r3.core")
|
||||||
.addDependencyExclude("hl7.fhir.r5.core");
|
.addDependencyExclude("hl7.fhir.r4.core")
|
||||||
|
.addDependencyExclude("hl7.fhir.r5.core");
|
||||||
}
|
}
|
||||||
packageInstallerSvc.install(packageInstallationSpec);
|
packageInstallerSvc.install(packageInstallationSpec);
|
||||||
}
|
}
|
||||||
@@ -238,11 +240,40 @@ public class StarterJpaConfig {
|
|||||||
|
|
||||||
// Create the interceptor and register it
|
// Create the interceptor and register it
|
||||||
return new CorsInterceptor(config);
|
return new CorsInterceptor(config);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public RestfulServer restfulServer(IFhirSystemDao<?, ?> fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional<MdmProviderLoader> mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional<TerminologyUploaderProvider> terminologyUploaderProvider, Optional<SubscriptionTriggeringProvider> subscriptionTriggeringProvider, Optional<CorsInterceptor> corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional<BinaryAccessProvider> binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional<GraphQLProvider> graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional<RepositoryValidatingInterceptor> repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional<IpsOperationProvider> theIpsOperationProvider, Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
|
public RestfulServer restfulServer(
|
||||||
|
IFhirSystemDao<?, ?> fhirSystemDao,
|
||||||
|
AppProperties appProperties,
|
||||||
|
DaoRegistry daoRegistry,
|
||||||
|
Optional<MdmProviderLoader> mdmProviderProvider,
|
||||||
|
IJpaSystemProvider jpaSystemProvider,
|
||||||
|
ResourceProviderFactory resourceProviderFactory,
|
||||||
|
JpaStorageSettings jpaStorageSettings,
|
||||||
|
ISearchParamRegistry searchParamRegistry,
|
||||||
|
IValidationSupport theValidationSupport,
|
||||||
|
DatabaseBackedPagingProvider databaseBackedPagingProvider,
|
||||||
|
LoggingInterceptor loggingInterceptor,
|
||||||
|
Optional<TerminologyUploaderProvider> terminologyUploaderProvider,
|
||||||
|
Optional<SubscriptionTriggeringProvider> subscriptionTriggeringProvider,
|
||||||
|
Optional<CorsInterceptor> corsInterceptor,
|
||||||
|
IInterceptorBroadcaster interceptorBroadcaster,
|
||||||
|
Optional<BinaryAccessProvider> binaryAccessProvider,
|
||||||
|
BinaryStorageInterceptor binaryStorageInterceptor,
|
||||||
|
IValidatorModule validatorModule,
|
||||||
|
Optional<GraphQLProvider> graphQLProvider,
|
||||||
|
BulkDataExportProvider bulkDataExportProvider,
|
||||||
|
BulkDataImportProvider bulkDataImportProvider,
|
||||||
|
ValueSetOperationProvider theValueSetOperationProvider,
|
||||||
|
ReindexProvider reindexProvider,
|
||||||
|
PartitionManagementProvider partitionManagementProvider,
|
||||||
|
Optional<RepositoryValidatingInterceptor> repositoryValidatingInterceptor,
|
||||||
|
IPackageInstallerSvc packageInstallerSvc,
|
||||||
|
ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
|
||||||
|
ApplicationContext appContext,
|
||||||
|
Optional<IpsOperationProvider> theIpsOperationProvider,
|
||||||
|
Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
|
||||||
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
|
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
|
||||||
|
|
||||||
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
|
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
|
||||||
@@ -264,7 +295,8 @@ public class StarterJpaConfig {
|
|||||||
|
|
||||||
fhirServer.registerProviders(resourceProviderFactory.createProviders());
|
fhirServer.registerProviders(resourceProviderFactory.createProviders());
|
||||||
fhirServer.registerProvider(jpaSystemProvider);
|
fhirServer.registerProvider(jpaSystemProvider);
|
||||||
fhirServer.setServerConformanceProvider(calculateConformanceProvider(fhirSystemDao, fhirServer, jpaStorageSettings, searchParamRegistry, theValidationSupport));
|
fhirServer.setServerConformanceProvider(calculateConformanceProvider(
|
||||||
|
fhirSystemDao, fhirServer, jpaStorageSettings, searchParamRegistry, theValidationSupport));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ETag Support
|
* ETag Support
|
||||||
@@ -272,7 +304,6 @@ public class StarterJpaConfig {
|
|||||||
|
|
||||||
if (!appProperties.getEtag_support_enabled()) fhirServer.setETagSupport(ETagSupportEnum.DISABLED);
|
if (!appProperties.getEtag_support_enabled()) fhirServer.setETagSupport(ETagSupportEnum.DISABLED);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default to JSON and pretty printing
|
* Default to JSON and pretty printing
|
||||||
*/
|
*/
|
||||||
@@ -318,7 +349,8 @@ public class StarterJpaConfig {
|
|||||||
fhirServer.setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
|
fhirServer.setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
|
||||||
} else if (appProperties.getUse_apache_address_strategy()) {
|
} else if (appProperties.getUse_apache_address_strategy()) {
|
||||||
boolean useHttps = appProperties.getUse_apache_address_strategy_https();
|
boolean useHttps = appProperties.getUse_apache_address_strategy_https();
|
||||||
fhirServer.setServerAddressStrategy(useHttps ? ApacheProxyAddressStrategy.forHttps() : ApacheProxyAddressStrategy.forHttp());
|
fhirServer.setServerAddressStrategy(
|
||||||
|
useHttps ? ApacheProxyAddressStrategy.forHttps() : ApacheProxyAddressStrategy.forHttp());
|
||||||
} else {
|
} else {
|
||||||
fhirServer.setServerAddressStrategy(new IncomingRequestAddressStrategy());
|
fhirServer.setServerAddressStrategy(new IncomingRequestAddressStrategy());
|
||||||
}
|
}
|
||||||
@@ -330,7 +362,11 @@ public class StarterJpaConfig {
|
|||||||
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
|
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
|
||||||
* with this feature.
|
* with this feature.
|
||||||
*/
|
*/
|
||||||
if (fhirSystemDao.getContext().getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { // <-- ENABLED RIGHT NOW
|
if (fhirSystemDao
|
||||||
|
.getContext()
|
||||||
|
.getVersion()
|
||||||
|
.getVersion()
|
||||||
|
.isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { // <-- ENABLED RIGHT NOW
|
||||||
fhirServer.registerProvider(terminologyUploaderProvider.get());
|
fhirServer.registerProvider(terminologyUploaderProvider.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +384,8 @@ public class StarterJpaConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (appProperties.getAllow_cascading_deletes()) {
|
if (appProperties.getAllow_cascading_deletes()) {
|
||||||
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(fhirSystemDao.getContext(), daoRegistry, interceptorBroadcaster, theThreadSafeResourceDeleterSvc);
|
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(
|
||||||
|
fhirSystemDao.getContext(), daoRegistry, interceptorBroadcaster, theThreadSafeResourceDeleterSvc);
|
||||||
fhirServer.registerInterceptor(cascadingDeleteInterceptor);
|
fhirServer.registerInterceptor(cascadingDeleteInterceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,16 +428,15 @@ public class StarterJpaConfig {
|
|||||||
fhirServer.registerProvider(bulkDataExportProvider);
|
fhirServer.registerProvider(bulkDataExportProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bulk Import
|
// Bulk Import
|
||||||
if (appProperties.getBulk_import_enabled()) {
|
if (appProperties.getBulk_import_enabled()) {
|
||||||
fhirServer.registerProvider(bulkDataImportProvider);
|
fhirServer.registerProvider(bulkDataImportProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// valueSet Operations i.e $expand
|
// valueSet Operations i.e $expand
|
||||||
fhirServer.registerProvider(theValueSetOperationProvider);
|
fhirServer.registerProvider(theValueSetOperationProvider);
|
||||||
|
|
||||||
//reindex Provider $reindex
|
// reindex Provider $reindex
|
||||||
fhirServer.registerProvider(reindexProvider);
|
fhirServer.registerProvider(reindexProvider);
|
||||||
|
|
||||||
// Partitioning
|
// Partitioning
|
||||||
@@ -414,8 +450,7 @@ public class StarterJpaConfig {
|
|||||||
// register custom interceptors
|
// register custom interceptors
|
||||||
registerCustomInterceptors(fhirServer, appContext, appProperties.getCustomInterceptorClasses());
|
registerCustomInterceptors(fhirServer, appContext, appProperties.getCustomInterceptorClasses());
|
||||||
|
|
||||||
|
// register the IPS Provider
|
||||||
//register the IPS Provider
|
|
||||||
if (!theIpsOperationProvider.isEmpty()) {
|
if (!theIpsOperationProvider.isEmpty()) {
|
||||||
fhirServer.registerProvider(theIpsOperationProvider.get());
|
fhirServer.registerProvider(theIpsOperationProvider.get());
|
||||||
}
|
}
|
||||||
@@ -426,8 +461,9 @@ public class StarterJpaConfig {
|
|||||||
/**
|
/**
|
||||||
* check the properties for custom interceptor classes and registers them.
|
* check the properties for custom interceptor classes and registers them.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
private void registerCustomInterceptors(RestfulServer fhirServer, ApplicationContext theAppContext, List<String> customInterceptorClasses) {
|
private void registerCustomInterceptors(
|
||||||
|
RestfulServer fhirServer, ApplicationContext theAppContext, List<String> customInterceptorClasses) {
|
||||||
|
|
||||||
if (customInterceptorClasses == null) {
|
if (customInterceptorClasses == null) {
|
||||||
return;
|
return;
|
||||||
@@ -461,30 +497,40 @@ public class StarterJpaConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServerConformanceProvider<?> calculateConformanceProvider(IFhirSystemDao fhirSystemDao, RestfulServer fhirServer, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport) {
|
public static IServerConformanceProvider<?> calculateConformanceProvider(
|
||||||
|
IFhirSystemDao fhirSystemDao,
|
||||||
|
RestfulServer fhirServer,
|
||||||
|
JpaStorageSettings jpaStorageSettings,
|
||||||
|
ISearchParamRegistry searchParamRegistry,
|
||||||
|
IValidationSupport theValidationSupport) {
|
||||||
FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion();
|
FhirVersionEnum fhirVersion = fhirSystemDao.getContext().getVersion().getVersion();
|
||||||
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
||||||
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, jpaStorageSettings);
|
JpaConformanceProviderDstu2 confProvider =
|
||||||
|
new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, jpaStorageSettings);
|
||||||
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
|
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
|
||||||
return confProvider;
|
return confProvider;
|
||||||
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
||||||
|
|
||||||
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry);
|
JpaConformanceProviderDstu3 confProvider =
|
||||||
|
new JpaConformanceProviderDstu3(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry);
|
||||||
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
|
confProvider.setImplementationDescription("HAPI FHIR DSTU3 Server");
|
||||||
return confProvider;
|
return confProvider;
|
||||||
} else if (fhirVersion == FhirVersionEnum.R4) {
|
} else if (fhirVersion == FhirVersionEnum.R4) {
|
||||||
|
|
||||||
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport);
|
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(
|
||||||
|
fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport);
|
||||||
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
|
confProvider.setImplementationDescription("HAPI FHIR R4 Server");
|
||||||
return confProvider;
|
return confProvider;
|
||||||
} else if (fhirVersion == FhirVersionEnum.R4B) {
|
} else if (fhirVersion == FhirVersionEnum.R4B) {
|
||||||
|
|
||||||
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport);
|
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(
|
||||||
|
fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport);
|
||||||
confProvider.setImplementationDescription("HAPI FHIR R4B Server");
|
confProvider.setImplementationDescription("HAPI FHIR R4B Server");
|
||||||
return confProvider;
|
return confProvider;
|
||||||
} else if (fhirVersion == FhirVersionEnum.R5) {
|
} else if (fhirVersion == FhirVersionEnum.R5) {
|
||||||
|
|
||||||
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport);
|
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(
|
||||||
|
fhirServer, fhirSystemDao, jpaStorageSettings, searchParamRegistry, theValidationSupport);
|
||||||
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
|
confProvider.setImplementationDescription("HAPI FHIR R5 Server");
|
||||||
return confProvider;
|
return confProvider;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor;
|
|||||||
public interface IRepositoryValidationInterceptorFactory {
|
public interface IRepositoryValidationInterceptorFactory {
|
||||||
|
|
||||||
String ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR = "enable_repository_validating_interceptor";
|
String ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR = "enable_repository_validating_interceptor";
|
||||||
|
|
||||||
RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions();
|
RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions();
|
||||||
|
|
||||||
RepositoryValidatingInterceptor build();
|
RepositoryValidatingInterceptor build();
|
||||||
|
|||||||
@@ -37,24 +37,28 @@ public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryV
|
|||||||
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
||||||
private final IFhirResourceDao structureDefinitionResourceProvider;
|
private final IFhirResourceDao structureDefinitionResourceProvider;
|
||||||
|
|
||||||
public RepositoryValidationInterceptorFactoryDstu3(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
public RepositoryValidationInterceptorFactoryDstu3(
|
||||||
|
RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
||||||
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
||||||
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
||||||
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
Map<String, List<StructureDefinition>> structureDefinitions = results.getResources(0, results.size())
|
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
.stream()
|
Map<String, List<StructureDefinition>> structureDefinitions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|
||||||
structureDefinitions.forEach((key, value) -> {
|
structureDefinitions.forEach((key, value) -> {
|
||||||
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType(key)
|
||||||
|
.requireAtLeastOneProfileOf(urls)
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
@@ -65,11 +69,14 @@ public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryV
|
|||||||
|
|
||||||
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
||||||
// of enabling validation for all Patient resources
|
// of enabling validation for all Patient resources
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType("Patient").requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient").and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType("Patient")
|
||||||
|
.requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient")
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
|
|
||||||
// Do not customize below this line
|
// Do not customize below this line
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,25 +37,29 @@ public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryVali
|
|||||||
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
||||||
private final IFhirResourceDao structureDefinitionResourceProvider;
|
private final IFhirResourceDao structureDefinitionResourceProvider;
|
||||||
|
|
||||||
public RepositoryValidationInterceptorFactoryR4(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
public RepositoryValidationInterceptorFactoryR4(
|
||||||
|
RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
||||||
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
||||||
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
||||||
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size())
|
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
.stream()
|
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|
||||||
structureDefintions.forEach((key, value) -> {
|
structureDefintions.forEach((key, value) -> {
|
||||||
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType(key)
|
||||||
|
.requireAtLeastOneProfileOf(urls)
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
@@ -67,11 +71,14 @@ public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryVali
|
|||||||
|
|
||||||
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
||||||
// of enabling validation for all Patient resources
|
// of enabling validation for all Patient resources
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType("Patient").requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient").and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType("Patient")
|
||||||
|
.requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient")
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
|
|
||||||
// Do not customize below this line
|
// Do not customize below this line
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,25 +37,29 @@ public class RepositoryValidationInterceptorFactoryR4B implements IRepositoryVal
|
|||||||
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
||||||
private final IFhirResourceDao structureDefinitionResourceProvider;
|
private final IFhirResourceDao structureDefinitionResourceProvider;
|
||||||
|
|
||||||
public RepositoryValidationInterceptorFactoryR4B(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
public RepositoryValidationInterceptorFactoryR4B(
|
||||||
|
RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
||||||
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
||||||
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
||||||
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size())
|
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
.stream()
|
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|
||||||
structureDefintions.forEach((key, value) -> {
|
structureDefintions.forEach((key, value) -> {
|
||||||
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType(key)
|
||||||
|
.requireAtLeastOneProfileOf(urls)
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
@@ -67,11 +71,14 @@ public class RepositoryValidationInterceptorFactoryR4B implements IRepositoryVal
|
|||||||
|
|
||||||
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
||||||
// of enabling validation for all Patient resources
|
// of enabling validation for all Patient resources
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType("Patient").requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient").and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType("Patient")
|
||||||
|
.requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient")
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
|
|
||||||
// Do not customize below this line
|
// Do not customize below this line
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,24 +37,28 @@ public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryVali
|
|||||||
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
|
||||||
private final IFhirResourceDao structureDefinitionResourceProvider;
|
private final IFhirResourceDao structureDefinitionResourceProvider;
|
||||||
|
|
||||||
public RepositoryValidationInterceptorFactoryR5(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
public RepositoryValidationInterceptorFactoryR5(
|
||||||
|
RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
|
||||||
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
|
||||||
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
this.fhirContext = daoRegistry.getSystemDao().getContext();
|
||||||
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
|
||||||
|
|
||||||
IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
IBundleProvider results = structureDefinitionResourceProvider.search(
|
||||||
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size())
|
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
|
||||||
.stream()
|
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
|
||||||
.map(StructureDefinition.class::cast)
|
.map(StructureDefinition.class::cast)
|
||||||
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
.collect(Collectors.groupingBy(StructureDefinition::getType));
|
||||||
|
|
||||||
structureDefintions.forEach((key, value) -> {
|
structureDefintions.forEach((key, value) -> {
|
||||||
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
String[] urls = value.stream().map(StructureDefinition::getUrl).toArray(String[]::new);
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType(key).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType(key)
|
||||||
|
.requireAtLeastOneProfileOf(urls)
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
@@ -65,11 +69,14 @@ public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryVali
|
|||||||
|
|
||||||
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
// Customize the ruleBuilder here to have the rules you want! We will give a simple example
|
||||||
// of enabling validation for all Patient resources
|
// of enabling validation for all Patient resources
|
||||||
repositoryValidatingRuleBuilder.forResourcesOfType("Patient").requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient").and().requireValidationToDeclaredProfiles();
|
repositoryValidatingRuleBuilder
|
||||||
|
.forResourcesOfType("Patient")
|
||||||
|
.requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient")
|
||||||
|
.and()
|
||||||
|
.requireValidationToDeclaredProfiles();
|
||||||
|
|
||||||
// Do not customize below this line
|
// Do not customize below this line
|
||||||
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
List<IRepositoryValidatingRule> rules = repositoryValidatingRuleBuilder.build();
|
||||||
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
return new RepositoryValidatingInterceptor(fhirContext, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ public class CrConfigCondition implements Condition {
|
|||||||
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
|
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
|
||||||
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr.enabled");
|
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr.enabled");
|
||||||
return Boolean.parseBoolean(property);
|
return Boolean.parseBoolean(property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
@ConfigurationProperties(prefix = "hapi.fhir.cr")
|
@ConfigurationProperties(prefix = "hapi.fhir.cr")
|
||||||
public class CrProperties {
|
public class CrProperties {
|
||||||
private Boolean enabled;
|
private Boolean enabled;
|
||||||
//cql settings
|
// cql settings
|
||||||
private Boolean cql_use_embedded_libraries = true;
|
private Boolean cql_use_embedded_libraries = true;
|
||||||
private Boolean cql_runtime_debug_logging_enabled = false;
|
private Boolean cql_runtime_debug_logging_enabled = false;
|
||||||
private Boolean cql_runtime_enable_validation = false;
|
private Boolean cql_runtime_enable_validation = false;
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cr;
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.provider.IResourceProviderFactoryObserver;
|
import ca.uhn.fhir.rest.server.provider.IResourceProviderFactoryObserver;
|
||||||
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class PostInitProviderRegisterer {
|
public class PostInitProviderRegisterer {
|
||||||
public PostInitProviderRegisterer(RestfulServer restfulServer,
|
public PostInitProviderRegisterer(RestfulServer restfulServer, ResourceProviderFactory resourceProviderFactory) {
|
||||||
ResourceProviderFactory resourceProviderFactory) {
|
|
||||||
resourceProviderFactory.attach(new Observer(restfulServer));
|
resourceProviderFactory.attach(new Observer(restfulServer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +29,6 @@ public class PostInitProviderRegisterer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.restfulServer.registerProvider(provider);
|
this.restfulServer.registerProvider(provider);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(Supplier<Object> theSupplier) {
|
public void remove(Supplier<Object> theSupplier) {
|
||||||
@@ -45,7 +43,5 @@ public class PostInitProviderRegisterer {
|
|||||||
|
|
||||||
this.restfulServer.unregisterProvider(provider);
|
this.restfulServer.unregisterProvider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional({ OnDSTU3Condition.class, CrConfigCondition.class })
|
@Conditional({OnDSTU3Condition.class, CrConfigCondition.class})
|
||||||
@Import({
|
@Import({
|
||||||
//BaseCrConfig.class,
|
// BaseCrConfig.class,
|
||||||
CrDstu3Config.class,
|
CrDstu3Config.class,
|
||||||
ApplyOperationConfig.class,
|
ApplyOperationConfig.class,
|
||||||
ExtractOperationConfig.class,
|
ExtractOperationConfig.class,
|
||||||
@@ -48,11 +48,12 @@ public class StarterCrDstu3Config {
|
|||||||
private static final Logger ourLogger = LoggerFactory.getLogger(StarterCrDstu3Config.class);
|
private static final Logger ourLogger = LoggerFactory.getLogger(StarterCrDstu3Config.class);
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
MeasureEvaluationOptions measureEvaluationOptions(EvaluationSettings theEvaluationSettings, Map<String, ValidationProfile> theValidationProfiles){
|
MeasureEvaluationOptions measureEvaluationOptions(
|
||||||
|
EvaluationSettings theEvaluationSettings, Map<String, ValidationProfile> theValidationProfiles) {
|
||||||
MeasureEvaluationOptions measureEvalOptions = new MeasureEvaluationOptions();
|
MeasureEvaluationOptions measureEvalOptions = new MeasureEvaluationOptions();
|
||||||
measureEvalOptions.setEvaluationSettings(theEvaluationSettings);
|
measureEvalOptions.setEvaluationSettings(theEvaluationSettings);
|
||||||
|
|
||||||
if(measureEvalOptions.isValidationEnabled()) {
|
if (measureEvalOptions.isValidationEnabled()) {
|
||||||
measureEvalOptions.setValidationProfiles(theValidationProfiles);
|
measureEvalOptions.setValidationProfiles(theValidationProfiles);
|
||||||
}
|
}
|
||||||
return measureEvalOptions;
|
return measureEvalOptions;
|
||||||
@@ -60,10 +61,10 @@ public class StarterCrDstu3Config {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public EvaluationSettings evaluationSettings(
|
public EvaluationSettings evaluationSettings(
|
||||||
CrProperties theCrProperties,
|
CrProperties theCrProperties,
|
||||||
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
||||||
Map<ModelIdentifier, Model> theGlobalModelCache,
|
Map<ModelIdentifier, Model> theGlobalModelCache,
|
||||||
Map<String, List<Code>> theGlobalValueSetCache) {
|
Map<String, List<Code>> theGlobalValueSetCache) {
|
||||||
var evaluationSettings = EvaluationSettings.getDefault();
|
var evaluationSettings = EvaluationSettings.getDefault();
|
||||||
var cqlOptions = evaluationSettings.getCqlOptions();
|
var cqlOptions = evaluationSettings.getCqlOptions();
|
||||||
|
|
||||||
@@ -135,9 +136,10 @@ public class StarterCrDstu3Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PostInitProviderRegisterer postInitProviderRegisterer(RestfulServer theRestfulServer,
|
public PostInitProviderRegisterer postInitProviderRegisterer(
|
||||||
ResourceProviderFactory theResourceProviderFactory) {
|
RestfulServer theRestfulServer, ResourceProviderFactory theResourceProviderFactory) {
|
||||||
return new PostInitProviderRegisterer(theRestfulServer, theResourceProviderFactory);}
|
return new PostInitProviderRegisterer(theRestfulServer, theResourceProviderFactory);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CrProperties crProperties() {
|
public CrProperties crProperties() {
|
||||||
@@ -161,26 +163,27 @@ public class StarterCrDstu3Config {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ElmCacheResourceChangeListener elmCacheResourceChangeListener(
|
public ElmCacheResourceChangeListener elmCacheResourceChangeListener(
|
||||||
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
||||||
DaoRegistry theDaoRegistry,
|
DaoRegistry theDaoRegistry,
|
||||||
EvaluationSettings theEvaluationSettings) {
|
EvaluationSettings theEvaluationSettings) {
|
||||||
ElmCacheResourceChangeListener listener =
|
ElmCacheResourceChangeListener listener =
|
||||||
new ElmCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getLibraryCache());
|
new ElmCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getLibraryCache());
|
||||||
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
||||||
"Library", SearchParameterMap.newSynchronous(), listener, 1000);
|
"Library", SearchParameterMap.newSynchronous(), listener, 1000);
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CodeCacheResourceChangeListener codeCacheResourceChangeListener(
|
public CodeCacheResourceChangeListener codeCacheResourceChangeListener(
|
||||||
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
||||||
EvaluationSettings theEvaluationSettings,
|
EvaluationSettings theEvaluationSettings,
|
||||||
DaoRegistry theDaoRegistry) {
|
DaoRegistry theDaoRegistry) {
|
||||||
|
|
||||||
CodeCacheResourceChangeListener listener = new CodeCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getValueSetCache());
|
CodeCacheResourceChangeListener listener =
|
||||||
//registry
|
new CodeCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getValueSetCache());
|
||||||
|
// registry
|
||||||
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
||||||
"ValueSet", SearchParameterMap.newSynchronous(), listener,1000);
|
"ValueSet", SearchParameterMap.newSynchronous(), listener, 1000);
|
||||||
|
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.cr;
|
package ca.uhn.fhir.jpa.starter.cr;
|
||||||
|
|
||||||
import ca.uhn.fhir.cr.common.CodeCacheResourceChangeListener;
|
import ca.uhn.fhir.cr.common.CodeCacheResourceChangeListener;
|
||||||
|
import ca.uhn.fhir.cr.common.CqlThreadFactory;
|
||||||
import ca.uhn.fhir.cr.common.ElmCacheResourceChangeListener;
|
import ca.uhn.fhir.cr.common.ElmCacheResourceChangeListener;
|
||||||
import ca.uhn.fhir.cr.config.r4.ApplyOperationConfig;
|
import ca.uhn.fhir.cr.config.r4.ApplyOperationConfig;
|
||||||
import ca.uhn.fhir.cr.config.r4.CrR4Config;
|
import ca.uhn.fhir.cr.config.r4.CrR4Config;
|
||||||
@@ -14,8 +15,6 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
|||||||
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
|
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
||||||
import ca.uhn.fhir.cr.common.CqlThreadFactory;
|
|
||||||
|
|
||||||
import org.cqframework.cql.cql2elm.CqlCompilerOptions;
|
import org.cqframework.cql.cql2elm.CqlCompilerOptions;
|
||||||
import org.cqframework.cql.cql2elm.model.CompiledLibrary;
|
import org.cqframework.cql.cql2elm.model.CompiledLibrary;
|
||||||
import org.cqframework.cql.cql2elm.model.Model;
|
import org.cqframework.cql.cql2elm.model.Model;
|
||||||
@@ -45,7 +44,7 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Conditional({ OnR4Condition.class, CrConfigCondition.class })
|
@Conditional({OnR4Condition.class, CrConfigCondition.class})
|
||||||
@Import({
|
@Import({
|
||||||
CrR4Config.class,
|
CrR4Config.class,
|
||||||
ApplyOperationConfig.class,
|
ApplyOperationConfig.class,
|
||||||
@@ -60,16 +59,14 @@ public class StarterCrR4Config {
|
|||||||
@Bean
|
@Bean
|
||||||
public ExecutorService cqlExecutor() {
|
public ExecutorService cqlExecutor() {
|
||||||
CqlThreadFactory factory = new CqlThreadFactory();
|
CqlThreadFactory factory = new CqlThreadFactory();
|
||||||
ExecutorService executor = Executors.
|
ExecutorService executor = Executors.newFixedThreadPool(2, factory);
|
||||||
newFixedThreadPool(2
|
|
||||||
, factory);
|
|
||||||
executor = new DelegatingSecurityContextExecutorService(executor);
|
executor = new DelegatingSecurityContextExecutorService(executor);
|
||||||
|
|
||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
|
CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
|
||||||
var careGapsProperties = new CareGapsProperties();
|
var careGapsProperties = new CareGapsProperties();
|
||||||
careGapsProperties.setThreadedCareGapsEnabled(false);
|
careGapsProperties.setThreadedCareGapsEnabled(false);
|
||||||
careGapsProperties.setCareGapsReporter(theCrProperties.getCareGapsReporter());
|
careGapsProperties.setCareGapsReporter(theCrProperties.getCareGapsReporter());
|
||||||
@@ -78,10 +75,11 @@ public class StarterCrR4Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
MeasureEvaluationOptions measureEvaluationOptions(EvaluationSettings theEvaluationSettings, Map<String, ValidationProfile> theValidationProfiles){
|
MeasureEvaluationOptions measureEvaluationOptions(
|
||||||
|
EvaluationSettings theEvaluationSettings, Map<String, ValidationProfile> theValidationProfiles) {
|
||||||
MeasureEvaluationOptions measureEvalOptions = new MeasureEvaluationOptions();
|
MeasureEvaluationOptions measureEvalOptions = new MeasureEvaluationOptions();
|
||||||
measureEvalOptions.setEvaluationSettings(theEvaluationSettings);
|
measureEvalOptions.setEvaluationSettings(theEvaluationSettings);
|
||||||
if(measureEvalOptions.isValidationEnabled()) {
|
if (measureEvalOptions.isValidationEnabled()) {
|
||||||
measureEvalOptions.setValidationProfiles(theValidationProfiles);
|
measureEvalOptions.setValidationProfiles(theValidationProfiles);
|
||||||
}
|
}
|
||||||
return measureEvalOptions;
|
return measureEvalOptions;
|
||||||
@@ -89,10 +87,10 @@ public class StarterCrR4Config {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public EvaluationSettings evaluationSettings(
|
public EvaluationSettings evaluationSettings(
|
||||||
CrProperties theCrProperties,
|
CrProperties theCrProperties,
|
||||||
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
||||||
Map<ModelIdentifier, Model> theGlobalModelCache,
|
Map<ModelIdentifier, Model> theGlobalModelCache,
|
||||||
Map<String, List<Code>> theGlobalValueSetCache) {
|
Map<String, List<Code>> theGlobalValueSetCache) {
|
||||||
var evaluationSettings = EvaluationSettings.getDefault();
|
var evaluationSettings = EvaluationSettings.getDefault();
|
||||||
var cqlOptions = evaluationSettings.getCqlOptions();
|
var cqlOptions = evaluationSettings.getCqlOptions();
|
||||||
|
|
||||||
@@ -164,8 +162,8 @@ public class StarterCrR4Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PostInitProviderRegisterer postInitProviderRegisterer(RestfulServer theRestfulServer,
|
public PostInitProviderRegisterer postInitProviderRegisterer(
|
||||||
ResourceProviderFactory theResourceProviderFactory) {
|
RestfulServer theRestfulServer, ResourceProviderFactory theResourceProviderFactory) {
|
||||||
return new PostInitProviderRegisterer(theRestfulServer, theResourceProviderFactory);
|
return new PostInitProviderRegisterer(theRestfulServer, theResourceProviderFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,26 +189,27 @@ public class StarterCrR4Config {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ElmCacheResourceChangeListener elmCacheResourceChangeListener(
|
public ElmCacheResourceChangeListener elmCacheResourceChangeListener(
|
||||||
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
||||||
DaoRegistry theDaoRegistry,
|
DaoRegistry theDaoRegistry,
|
||||||
EvaluationSettings theEvaluationSettings) {
|
EvaluationSettings theEvaluationSettings) {
|
||||||
ElmCacheResourceChangeListener listener =
|
ElmCacheResourceChangeListener listener =
|
||||||
new ElmCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getLibraryCache());
|
new ElmCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getLibraryCache());
|
||||||
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
||||||
"Library", SearchParameterMap.newSynchronous(), listener, 1000);
|
"Library", SearchParameterMap.newSynchronous(), listener, 1000);
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CodeCacheResourceChangeListener codeCacheResourceChangeListener(
|
public CodeCacheResourceChangeListener codeCacheResourceChangeListener(
|
||||||
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
IResourceChangeListenerRegistry theResourceChangeListenerRegistry,
|
||||||
EvaluationSettings theEvaluationSettings,
|
EvaluationSettings theEvaluationSettings,
|
||||||
DaoRegistry theDaoRegistry) {
|
DaoRegistry theDaoRegistry) {
|
||||||
|
|
||||||
CodeCacheResourceChangeListener listener = new CodeCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getValueSetCache());
|
CodeCacheResourceChangeListener listener =
|
||||||
//registry
|
new CodeCacheResourceChangeListener(theDaoRegistry, theEvaluationSettings.getValueSetCache());
|
||||||
|
// registry
|
||||||
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
theResourceChangeListenerRegistry.registerResourceResourceChangeListener(
|
||||||
"ValueSet", SearchParameterMap.newSynchronous(), listener,1000);
|
"ValueSet", SearchParameterMap.newSynchronous(), listener, 1000);
|
||||||
|
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
@@ -219,5 +218,4 @@ public class StarterCrR4Config {
|
|||||||
public ResourceChangeListenerRegistryInterceptor resourceChangeListenerRegistryInterceptor() {
|
public ResourceChangeListenerRegistryInterceptor resourceChangeListenerRegistryInterceptor() {
|
||||||
return new ResourceChangeListenerRegistryInterceptor();
|
return new ResourceChangeListenerRegistryInterceptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,16 @@ import java.io.IOException;
|
|||||||
public interface IImplementationGuideOperationProvider {
|
public interface IImplementationGuideOperationProvider {
|
||||||
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
|
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
|
||||||
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
|
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
|
||||||
return new PackageInstallationSpec().setName(npmPackage.name()).setPackageContents(npmPackageAsByteArray).setVersion(npmPackage.version()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL).setFetchDependencies(false);
|
return new PackageInstallationSpec()
|
||||||
|
.setName(npmPackage.name())
|
||||||
|
.setPackageContents(npmPackageAsByteArray)
|
||||||
|
.setVersion(npmPackage.version())
|
||||||
|
.setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)
|
||||||
|
.setFetchDependencies(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//The following declaration is the one that counts but cannot be used across different versions as stating Base64BinaryType would bind to a separate version
|
// The following declaration is the one that counts but cannot be used across different versions as stating
|
||||||
//@Operation(name = "$install", typeName = "ImplementationGuide")
|
// Base64BinaryType would bind to a separate version
|
||||||
//Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);
|
// @Operation(name = "$install", typeName = "ImplementationGuide")
|
||||||
|
// Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,15 @@ public class ImplementationGuideR4OperationProvider implements IImplementationGu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = "$install", typeName = "ImplementationGuide")
|
@Operation(name = "$install", typeName = "ImplementationGuide")
|
||||||
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
public Parameters install(
|
||||||
|
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
packageInstallerSvc.install(
|
||||||
|
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return new Parameters();
|
return new Parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,15 +22,15 @@ public class ImplementationGuideR5OperationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = "$install", typeName = "ImplementationGuide")
|
@Operation(name = "$install", typeName = "ImplementationGuide")
|
||||||
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
public Parameters install(
|
||||||
|
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
packageInstallerSvc.install(
|
||||||
|
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return new Parameters();
|
return new Parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
|||||||
public class IpsConfigCondition implements Condition {
|
public class IpsConfigCondition implements Condition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
|
public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
|
||||||
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.ips_enabled");
|
String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.ips_enabled");
|
||||||
return Boolean.parseBoolean(property);
|
return Boolean.parseBoolean(property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,30 @@
|
|||||||
package ca.uhn.fhir.jpa.starter.ips;
|
package ca.uhn.fhir.jpa.starter.ips;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||||
import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy;
|
import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy;
|
||||||
import ca.uhn.fhir.jpa.ips.strategy.DefaultIpsGenerationStrategy;
|
|
||||||
import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc;
|
import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc;
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
|
|
||||||
import ca.uhn.fhir.jpa.ips.generator.IpsGeneratorSvcImpl;
|
import ca.uhn.fhir.jpa.ips.generator.IpsGeneratorSvcImpl;
|
||||||
|
import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
|
||||||
|
import ca.uhn.fhir.jpa.ips.strategy.DefaultIpsGenerationStrategy;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
|
||||||
@Conditional(IpsConfigCondition.class)
|
@Conditional(IpsConfigCondition.class)
|
||||||
public class StarterIpsConfig {
|
public class StarterIpsConfig {
|
||||||
@Bean
|
@Bean
|
||||||
IIpsGenerationStrategy ipsGenerationStrategy()
|
IIpsGenerationStrategy ipsGenerationStrategy() {
|
||||||
{
|
|
||||||
return new DefaultIpsGenerationStrategy();
|
return new DefaultIpsGenerationStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public IpsOperationProvider ipsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc){
|
public IpsOperationProvider ipsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc) {
|
||||||
return new IpsOperationProvider(theIpsGeneratorSvc);
|
return new IpsOperationProvider(theIpsGeneratorSvc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public IIpsGeneratorSvc ipsGeneratorSvcImpl(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry)
|
public IIpsGeneratorSvc ipsGeneratorSvcImpl(
|
||||||
{
|
FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) {
|
||||||
return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry);
|
return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,13 @@ import java.nio.charset.StandardCharsets;
|
|||||||
public class MdmConfig {
|
public class MdmConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
IMdmSettings mdmSettings(@Autowired MdmRuleValidator theMdmRuleValidator, AppProperties appProperties) throws IOException {
|
IMdmSettings mdmSettings(@Autowired MdmRuleValidator theMdmRuleValidator, AppProperties appProperties)
|
||||||
|
throws IOException {
|
||||||
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
|
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
Resource resource = resourceLoader.getResource("mdm-rules.json");
|
Resource resource = resourceLoader.getResource("mdm-rules.json");
|
||||||
String json = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
|
String json = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
|
||||||
return new MdmSettings(theMdmRuleValidator).setEnabled(appProperties.getMdm_enabled()).setScriptText(json);
|
return new MdmSettings(theMdmRuleValidator)
|
||||||
|
.setEnabled(appProperties.getMdm_enabled())
|
||||||
|
.setScriptText(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import org.springframework.context.annotation.ConditionContext;
|
|||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
public class MdmConfigCondition implements Condition {
|
public class MdmConfigCondition implements Condition {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
|
||||||
String property = conditionContext.getEnvironment().getProperty("hapi.fhir.mdm_enabled");
|
String property = conditionContext.getEnvironment().getProperty("hapi.fhir.mdm_enabled");
|
||||||
return Boolean.parseBoolean(property);
|
return Boolean.parseBoolean(property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import static java.util.Objects.requireNonNullElse;
|
|||||||
|
|
||||||
public class EnvironmentHelper {
|
public class EnvironmentHelper {
|
||||||
|
|
||||||
public static Properties getHibernateProperties(ConfigurableEnvironment environment,
|
public static Properties getHibernateProperties(
|
||||||
ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
|
ConfigurableEnvironment environment, ConfigurableListableBeanFactory myConfigurableListableBeanFactory) {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
Map<String, Object> jpaProps = getPropertiesStartingWith(environment, "spring.jpa.properties");
|
Map<String, Object> jpaProps = getPropertiesStartingWith(environment, "spring.jpa.properties");
|
||||||
for (Map.Entry<String, Object> entry : jpaProps.entrySet()) {
|
for (Map.Entry<String, Object> entry : jpaProps.entrySet()) {
|
||||||
@@ -40,18 +40,23 @@ public class EnvironmentHelper {
|
|||||||
properties.put(strippedKey, entry.getValue().toString());
|
properties.put(strippedKey, entry.getValue().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
//Spring Boot Autoconfiguration defaults
|
// Spring Boot Autoconfiguration defaults
|
||||||
properties.putIfAbsent(AvailableSettings.SCANNER, "org.hibernate.boot.archive.scan.internal.DisabledScanner");
|
properties.putIfAbsent(AvailableSettings.SCANNER, "org.hibernate.boot.archive.scan.internal.DisabledScanner");
|
||||||
properties.putIfAbsent(AvailableSettings.IMPLICIT_NAMING_STRATEGY, SpringImplicitNamingStrategy.class.getName());
|
properties.putIfAbsent(
|
||||||
properties.putIfAbsent(AvailableSettings.PHYSICAL_NAMING_STRATEGY, CamelCaseToUnderscoresNamingStrategy.class.getName());
|
AvailableSettings.IMPLICIT_NAMING_STRATEGY, SpringImplicitNamingStrategy.class.getName());
|
||||||
//TODO The bean factory should be added as parameter but that requires that it can be injected from the entityManagerFactory bean from xBaseConfig
|
properties.putIfAbsent(
|
||||||
//properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
|
AvailableSettings.PHYSICAL_NAMING_STRATEGY, CamelCaseToUnderscoresNamingStrategy.class.getName());
|
||||||
|
// TODO The bean factory should be added as parameter but that requires that it can be injected from the
|
||||||
|
// entityManagerFactory bean from xBaseConfig
|
||||||
|
// properties.putIfAbsent(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
|
||||||
|
|
||||||
//hapi-fhir-jpaserver-base "sensible defaults"
|
// hapi-fhir-jpaserver-base "sensible defaults"
|
||||||
Map<String, Object> hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(myConfigurableListableBeanFactory).getJpaPropertyMap();
|
Map<String, Object> hapiJpaPropertyMap = new HapiFhirLocalContainerEntityManagerFactoryBean(
|
||||||
|
myConfigurableListableBeanFactory)
|
||||||
|
.getJpaPropertyMap();
|
||||||
hapiJpaPropertyMap.forEach(properties::putIfAbsent);
|
hapiJpaPropertyMap.forEach(properties::putIfAbsent);
|
||||||
|
|
||||||
//hapi-fhir-jpaserver-starter defaults
|
// hapi-fhir-jpaserver-starter defaults
|
||||||
properties.putIfAbsent(AvailableSettings.FORMAT_SQL, false);
|
properties.putIfAbsent(AvailableSettings.FORMAT_SQL, false);
|
||||||
properties.putIfAbsent(AvailableSettings.SHOW_SQL, false);
|
properties.putIfAbsent(AvailableSettings.SHOW_SQL, false);
|
||||||
properties.putIfAbsent(AvailableSettings.HBM2DDL_AUTO, "update");
|
properties.putIfAbsent(AvailableSettings.HBM2DDL_AUTO, "update");
|
||||||
@@ -61,43 +66,60 @@ public class EnvironmentHelper {
|
|||||||
properties.putIfAbsent(AvailableSettings.USE_STRUCTURED_CACHE, false);
|
properties.putIfAbsent(AvailableSettings.USE_STRUCTURED_CACHE, false);
|
||||||
properties.putIfAbsent(AvailableSettings.USE_MINIMAL_PUTS, false);
|
properties.putIfAbsent(AvailableSettings.USE_MINIMAL_PUTS, false);
|
||||||
|
|
||||||
//Hibernate Search defaults
|
// Hibernate Search defaults
|
||||||
properties.putIfAbsent(HibernateOrmMapperSettings.ENABLED, false);
|
properties.putIfAbsent(HibernateOrmMapperSettings.ENABLED, false);
|
||||||
if (Boolean.parseBoolean(String.valueOf(properties.get(HibernateOrmMapperSettings.ENABLED)))) {
|
if (Boolean.parseBoolean(String.valueOf(properties.get(HibernateOrmMapperSettings.ENABLED)))) {
|
||||||
if (isElasticsearchEnabled(environment)) {
|
if (isElasticsearchEnabled(environment)) {
|
||||||
properties.putIfAbsent(BackendSettings.backendKey(BackendSettings.TYPE), ElasticsearchBackendSettings.TYPE_NAME);
|
properties.putIfAbsent(
|
||||||
|
BackendSettings.backendKey(BackendSettings.TYPE), ElasticsearchBackendSettings.TYPE_NAME);
|
||||||
} else {
|
} else {
|
||||||
properties.putIfAbsent(BackendSettings.backendKey(BackendSettings.TYPE), LuceneBackendSettings.TYPE_NAME);
|
properties.putIfAbsent(
|
||||||
|
BackendSettings.backendKey(BackendSettings.TYPE), LuceneBackendSettings.TYPE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.get(BackendSettings.backendKey(BackendSettings.TYPE)).equals(LuceneBackendSettings.TYPE_NAME)) {
|
if (properties
|
||||||
properties.putIfAbsent(BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_TYPE), LocalFileSystemDirectoryProvider.NAME);
|
.get(BackendSettings.backendKey(BackendSettings.TYPE))
|
||||||
properties.putIfAbsent(BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_ROOT), "target/lucenefiles");
|
.equals(LuceneBackendSettings.TYPE_NAME)) {
|
||||||
properties.putIfAbsent(BackendSettings.backendKey(LuceneBackendSettings.ANALYSIS_CONFIGURER),
|
properties.putIfAbsent(
|
||||||
HapiHSearchAnalysisConfigurers.HapiLuceneAnalysisConfigurer.class.getName());
|
BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_TYPE),
|
||||||
properties.putIfAbsent(BackendSettings.backendKey(LuceneBackendSettings.LUCENE_VERSION), Version.LATEST);
|
LocalFileSystemDirectoryProvider.NAME);
|
||||||
|
properties.putIfAbsent(
|
||||||
|
BackendSettings.backendKey(LuceneIndexSettings.DIRECTORY_ROOT), "target/lucenefiles");
|
||||||
|
properties.putIfAbsent(
|
||||||
|
BackendSettings.backendKey(LuceneBackendSettings.ANALYSIS_CONFIGURER),
|
||||||
|
HapiHSearchAnalysisConfigurers.HapiLuceneAnalysisConfigurer.class.getName());
|
||||||
|
properties.putIfAbsent(
|
||||||
|
BackendSettings.backendKey(LuceneBackendSettings.LUCENE_VERSION), Version.LATEST);
|
||||||
|
|
||||||
} else if (properties.get(BackendSettings.backendKey(BackendSettings.TYPE)).equals(ElasticsearchBackendSettings.TYPE_NAME)) {
|
} else if (properties
|
||||||
|
.get(BackendSettings.backendKey(BackendSettings.TYPE))
|
||||||
|
.equals(ElasticsearchBackendSettings.TYPE_NAME)) {
|
||||||
ElasticsearchHibernatePropertiesBuilder builder = new ElasticsearchHibernatePropertiesBuilder();
|
ElasticsearchHibernatePropertiesBuilder builder = new ElasticsearchHibernatePropertiesBuilder();
|
||||||
IndexStatus requiredIndexStatus = environment.getProperty("elasticsearch.required_index_status", IndexStatus.class);
|
IndexStatus requiredIndexStatus =
|
||||||
|
environment.getProperty("elasticsearch.required_index_status", IndexStatus.class);
|
||||||
builder.setRequiredIndexStatus(requireNonNullElse(requiredIndexStatus, IndexStatus.YELLOW));
|
builder.setRequiredIndexStatus(requireNonNullElse(requiredIndexStatus, IndexStatus.YELLOW));
|
||||||
builder.setHosts(getElasticsearchServerUrl(environment));
|
builder.setHosts(getElasticsearchServerUrl(environment));
|
||||||
builder.setUsername(getElasticsearchServerUsername(environment));
|
builder.setUsername(getElasticsearchServerUsername(environment));
|
||||||
builder.setPassword(getElasticsearchServerPassword(environment));
|
builder.setPassword(getElasticsearchServerPassword(environment));
|
||||||
builder.setProtocol(getElasticsearchServerProtocol(environment));
|
builder.setProtocol(getElasticsearchServerProtocol(environment));
|
||||||
SchemaManagementStrategyName indexSchemaManagementStrategy = environment.getProperty("elasticsearch.schema_management_strategy", SchemaManagementStrategyName.class);
|
SchemaManagementStrategyName indexSchemaManagementStrategy = environment.getProperty(
|
||||||
builder.setIndexSchemaManagementStrategy(requireNonNullElse(indexSchemaManagementStrategy, SchemaManagementStrategyName.CREATE));
|
"elasticsearch.schema_management_strategy", SchemaManagementStrategyName.class);
|
||||||
Boolean refreshAfterWrite = environment.getProperty("elasticsearch.debug.refresh_after_write", Boolean.class);
|
builder.setIndexSchemaManagementStrategy(
|
||||||
|
requireNonNullElse(indexSchemaManagementStrategy, SchemaManagementStrategyName.CREATE));
|
||||||
|
Boolean refreshAfterWrite =
|
||||||
|
environment.getProperty("elasticsearch.debug.refresh_after_write", Boolean.class);
|
||||||
if (refreshAfterWrite == null || !refreshAfterWrite) {
|
if (refreshAfterWrite == null || !refreshAfterWrite) {
|
||||||
builder.setDebugIndexSyncStrategy(AutomaticIndexingSynchronizationStrategyNames.ASYNC);
|
builder.setDebugIndexSyncStrategy(AutomaticIndexingSynchronizationStrategyNames.ASYNC);
|
||||||
} else {
|
} else {
|
||||||
builder.setDebugIndexSyncStrategy(AutomaticIndexingSynchronizationStrategyNames.READ_SYNC);
|
builder.setDebugIndexSyncStrategy(AutomaticIndexingSynchronizationStrategyNames.READ_SYNC);
|
||||||
}
|
}
|
||||||
builder.setDebugPrettyPrintJsonLog(requireNonNullElse(environment.getProperty("elasticsearch.debug.pretty_print_json_log", Boolean.class), false));
|
builder.setDebugPrettyPrintJsonLog(requireNonNullElse(
|
||||||
|
environment.getProperty("elasticsearch.debug.pretty_print_json_log", Boolean.class), false));
|
||||||
builder.apply(properties);
|
builder.apply(properties);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException("Unsupported Hibernate Search backend: " + properties.get(BackendSettings.backendKey(BackendSettings.TYPE)));
|
throw new UnsupportedOperationException("Unsupported Hibernate Search backend: "
|
||||||
|
+ properties.get(BackendSettings.backendKey(BackendSettings.TYPE)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,8 +150,7 @@ public class EnvironmentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Object> getPropertiesStartingWith(ConfigurableEnvironment aEnv,
|
public static Map<String, Object> getPropertiesStartingWith(ConfigurableEnvironment aEnv, String aKeyPrefix) {
|
||||||
String aKeyPrefix) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
Map<String, Object> map = getAllProperties(aEnv);
|
Map<String, Object> map = getAllProperties(aEnv);
|
||||||
@@ -167,7 +188,6 @@ public class EnvironmentHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addAll(Map<String, Object> aBase, Map<String, Object> aToBeAdded) {
|
private static void addAll(Map<String, Object> aBase, Map<String, Object> aToBeAdded) {
|
||||||
|
|||||||
@@ -7,27 +7,26 @@ import org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver;
|
|||||||
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
|
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
|
||||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
public class JpaHibernatePropertiesProvider extends HibernatePropertiesProvider {
|
public class JpaHibernatePropertiesProvider extends HibernatePropertiesProvider {
|
||||||
|
|
||||||
private final Dialect dialect;
|
private final Dialect dialect;
|
||||||
|
|
||||||
public JpaHibernatePropertiesProvider(LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
|
public JpaHibernatePropertiesProvider(LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
|
||||||
DataSource connection = myEntityManagerFactory.getDataSource();
|
DataSource connection = myEntityManagerFactory.getDataSource();
|
||||||
try ( Connection dbConnection = connection.getConnection()){
|
try (Connection dbConnection = connection.getConnection()) {
|
||||||
dialect = new StandardDialectResolver()
|
dialect = new StandardDialectResolver()
|
||||||
.resolveDialect(new DatabaseMetaDataDialectResolutionInfoAdapter(dbConnection.getMetaData()));
|
.resolveDialect(new DatabaseMetaDataDialectResolutionInfoAdapter(dbConnection.getMetaData()));
|
||||||
} catch (SQLException sqlException) {
|
} catch (SQLException sqlException) {
|
||||||
throw new ConfigurationException(sqlException.getMessage(), sqlException);
|
throw new ConfigurationException(sqlException.getMessage(), sqlException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialect getDialect() {
|
public Dialect getDialect() {
|
||||||
return dialect;
|
return dialect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user