diff --git a/README.md b/README.md
index 75f18c2..6bc5789 100644
--- a/README.md
+++ b/README.md
@@ -336,12 +336,12 @@ NOTE: MS SQL Server by default uses a case-insensitive codepage. This will cause
It is recommended to deploy a case-sensitive database prior to running HAPI FHIR when using MS SQL Server to avoid these and potentially other issues.
## Adding custom interceptors
-Custom interceptors can be registered with the server by including the property `hapi.fhir.custom-interceptor-classes`. This will take a comma separated list of fully-qualified class names which will be registered with the server.
-Interceptors will be discovered in one of two ways:
+Custom interceptors can be registered with the server by including the property `hapi.fhir.custom-interceptor-classes`. This will take a comma separated list of fully-qualified class names which will be registered with the server.
+Interceptors will be discovered in one of two ways:
1) discovered from the Spring application context as existing Beans (can be used in conjunction with `hapi.fhir.custom-bean-packages`) or registered with Spring via other methods
-or
+or
2) classes will be instantiated via reflection if no matching Bean is found
diff --git a/pom.xml b/pom.xml
index 25964e6..f750d54 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,6 +131,16 @@
hapi-fhir-jpaserver-mdm
${project.version}
+
+ org.springframework
+ spring-context
+
+
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-server-cds-hooks
+ ${project.version}
+
ca.uhn.hapi.fhir
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
index 6c93d15..a724ef2 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
@@ -865,4 +865,4 @@ public class AppProperties {
public void setEnable_index_of_type(boolean enable_index_of_type) {
this.enable_index_of_type = enable_index_of_type;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java
index 42faf1c..9131f8d 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java
@@ -3,7 +3,10 @@ package ca.uhn.fhir.jpa.starter;
import ca.uhn.fhir.batch2.jobs.config.Batch2JobsConfig;
import ca.uhn.fhir.jpa.batch2.JpaBatch2Config;
import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion;
+import ca.uhn.fhir.jpa.starter.cdshooks.StarterCdsHooksConfig;
import ca.uhn.fhir.jpa.starter.common.FhirTesterConfig;
+import ca.uhn.fhir.jpa.starter.cr.StarterCrDstu3Config;
+import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config;
import ca.uhn.fhir.jpa.starter.mdm.MdmConfig;
import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig;
@@ -29,6 +32,9 @@ import org.springframework.web.servlet.DispatcherServlet;
@ServletComponentScan(basePackageClasses = {RestfulServer.class})
@SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class, ThymeleafAutoConfiguration.class})
@Import({
+ StarterCrR4Config.class,
+ StarterCrDstu3Config.class,
+ StarterCdsHooksConfig.class,
SubscriptionSubmitterConfig.class,
SubscriptionProcessorConfig.class,
SubscriptionChannelConfig.class,
@@ -39,51 +45,54 @@ import org.springframework.web.servlet.DispatcherServlet;
})
public class Application extends SpringBootServletInitializer {
- public static void main(String[] args) {
+ public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
+ SpringApplication.run(Application.class, args);
- //Server is now accessible at eg. http://localhost:8080/fhir/metadata
- //UI is now accessible at http://localhost:8080/
- }
+ // Server is now accessible at eg. http://localhost:8080/fhir/metadata
+ // UI is now accessible at http://localhost:8080/
+ }
- @Override
- protected SpringApplicationBuilder configure(
- SpringApplicationBuilder builder) {
- return builder.sources(Application.class);
- }
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+ return builder.sources(Application.class);
+ }
- @Autowired
- AutowireCapableBeanFactory beanFactory;
+ @Autowired
+ AutowireCapableBeanFactory beanFactory;
- @Bean
- @Conditional(OnEitherVersion.class)
- public ServletRegistrationBean hapiServletRegistration(RestfulServer restfulServer) {
- ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
- beanFactory.autowireBean(restfulServer);
- servletRegistrationBean.setServlet(restfulServer);
- servletRegistrationBean.addUrlMappings("/fhir/*");
- servletRegistrationBean.setLoadOnStartup(1);
+ @Bean
+ @Conditional(OnEitherVersion.class)
+ public ServletRegistrationBean hapiServletRegistration(RestfulServer restfulServer) {
+ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
+ beanFactory.autowireBean(restfulServer);
+ servletRegistrationBean.setServlet(restfulServer);
+ servletRegistrationBean.addUrlMappings("/fhir/*");
+ servletRegistrationBean.setLoadOnStartup(1);
- return servletRegistrationBean;
- }
+ return servletRegistrationBean;
+ }
- @Bean
- public ServletRegistrationBean overlayRegistrationBean() {
+ @Bean
+ public ServletRegistrationBean overlayRegistrationBean() {
- AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
- annotationConfigWebApplicationContext.register(FhirTesterConfig.class);
+ AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext =
+ new AnnotationConfigWebApplicationContext();
+ annotationConfigWebApplicationContext.register(FhirTesterConfig.class);
- DispatcherServlet dispatcherServlet = new DispatcherServlet(
- annotationConfigWebApplicationContext);
- dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
- dispatcherServlet.setContextConfigLocation(FhirTesterConfig.class.getName());
+ DispatcherServlet dispatcherServlet = new DispatcherServlet(annotationConfigWebApplicationContext);
+ dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
+ dispatcherServlet.setContextConfigLocation(FhirTesterConfig.class.getName());
- ServletRegistrationBean registrationBean = new ServletRegistrationBean();
- registrationBean.setServlet(dispatcherServlet);
- registrationBean.addUrlMappings("/*");
- registrationBean.setLoadOnStartup(1);
- return registrationBean;
+ ServletRegistrationBean registrationBean = new ServletRegistrationBean();
+ registrationBean.setServlet(dispatcherServlet);
+ registrationBean.addUrlMappings("/*");
+ registrationBean.setLoadOnStartup(1);
+ return registrationBean;
+ }
- }
+ // @Bean
+ // IRepositoryFactory repositoryFactory(DaoRegistry theDaoRegistry, RestfulServer theRestfulServer) {
+ // return rd -> new HapiFhirRepository(theDaoRegistry, rd, theRestfulServer);
+ // }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java
index a3b528c..2edb3aa 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/ExtraStaticFilesConfigurer.java
@@ -19,33 +19,32 @@ public class ExtraStaticFilesConfigurer implements WebMvcConfigurer {
public ExtraStaticFilesConfigurer(AppProperties appProperties) {
rootContextPath = appProperties.getStaticLocationPrefix();
- if(rootContextPath.endsWith("/"))
+ if (rootContextPath.endsWith("/"))
rootContextPath = rootContextPath.substring(0, rootContextPath.lastIndexOf('/'));
staticLocation = appProperties.getStaticLocation();
- if(staticLocation.endsWith("/"))
- staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/'));
-
+ if (staticLocation.endsWith("/")) staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/'));
}
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
+ theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation);
+ }
@Override
- public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
- theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation);
- }
+ public void addViewControllers(ViewControllerRegistry registry) {
+ String path = URI.create(staticLocation).getPath();
+ String lastSegment = path.substring(path.lastIndexOf('/') + 1);
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- 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 + "/*").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);
- }
-
-}
\ No newline at end of file
+ registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java
index e4a44d7..15a2490 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnCorsPresent.java
@@ -10,9 +10,11 @@ public class OnCorsPresent implements Condition {
@Override
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.getCors() == null) return false;
return true;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU2Condition.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU2Condition.java
index 2c2419c..2f27323 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU2Condition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU2Condition.java
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class OnDSTU2Condition implements Condition {
- @Override
- public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
- FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
- getEnvironment()
- .getProperty("hapi.fhir.fhir_version")
- .toUpperCase());
+ @Override
+ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
+ FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
+ .getEnvironment()
+ .getProperty("hapi.fhir.fhir_version")
+ .toUpperCase());
- return version == FhirVersionEnum.DSTU2;
-
- }
+ return version == FhirVersionEnum.DSTU2;
+ }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU3Condition.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU3Condition.java
index 1196245..7e5e117 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU3Condition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnDSTU3Condition.java
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class OnDSTU3Condition implements Condition {
- @Override
- public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
- FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
- getEnvironment()
- .getProperty("hapi.fhir.fhir_version")
- .toUpperCase());
+ @Override
+ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
+ FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
+ .getEnvironment()
+ .getProperty("hapi.fhir.fhir_version")
+ .toUpperCase());
- return version == FhirVersionEnum.DSTU3;
-
- }
+ return version == FhirVersionEnum.DSTU3;
+ }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java
index 463f779..98af287 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnEitherVersion.java
@@ -6,34 +6,28 @@ import org.springframework.context.annotation.Conditional;
public class OnEitherVersion extends AnyNestedCondition {
- OnEitherVersion() {
- 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 {
+ OnEitherVersion() {
+ super(ConfigurationPhase.REGISTER_BEAN);
}
- @Conditional(OnR5Condition.class)
- static class OnR5 {
- }
+ @Override
+ protected ConditionOutcome getFinalMatchOutcome(MemberMatchOutcomes memberOutcomes) {
+ ConditionOutcome result = super.getFinalMatchOutcome(memberOutcomes);
+ return result;
+ }
-}
\ No newline at end of file
+ @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 {}
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java
index 7b11df1..c320801 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnImplementationGuidesPresent.java
@@ -10,9 +10,11 @@ public class OnImplementationGuidesPresent implements Condition {
@Override
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.getImplementationGuides() == null) return false;
return !config.getImplementationGuides().isEmpty();
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java
index e323a22..76833cf 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4BCondition.java
@@ -8,10 +8,10 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
public class OnR4BCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
- String version = conditionContext.
- getEnvironment()
- .getProperty("hapi.fhir.fhir_version")
- .toUpperCase();
+ String version = conditionContext
+ .getEnvironment()
+ .getProperty("hapi.fhir.fhir_version")
+ .toUpperCase();
return FhirVersionEnum.R4B.name().equals(version);
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4Condition.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4Condition.java
index e362aea..73f6061 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4Condition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR4Condition.java
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class OnR4Condition implements Condition {
- @Override
- public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
- FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
- getEnvironment()
- .getProperty("hapi.fhir.fhir_version")
- .toUpperCase());
+ @Override
+ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
+ FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
+ .getEnvironment()
+ .getProperty("hapi.fhir.fhir_version")
+ .toUpperCase());
- return version == FhirVersionEnum.R4;
-
- }
+ return version == FhirVersionEnum.R4;
+ }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR5Condition.java b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR5Condition.java
index 1ecca66..f30d9dc 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR5Condition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/annotations/OnR5Condition.java
@@ -6,14 +6,13 @@ import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class OnR5Condition implements Condition {
- @Override
- public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
- FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext.
- getEnvironment()
- .getProperty("hapi.fhir.fhir_version")
- .toUpperCase());
+ @Override
+ public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata metadata) {
+ FhirVersionEnum version = FhirVersionEnum.forVersionString(conditionContext
+ .getEnvironment()
+ .getProperty("hapi.fhir.fhir_version")
+ .toUpperCase());
- return version == FhirVersionEnum.R5;
-
- }
+ return version == FhirVersionEnum.R5;
+ }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksConfigCondition.java
new file mode 100644
index 0000000..b90e1db
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksConfigCondition.java
@@ -0,0 +1,14 @@
+package ca.uhn.fhir.jpa.starter.cdshooks;
+
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+public class CdsHooksConfigCondition implements Condition {
+
+ @Override
+ public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
+ String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cdshooks.enabled");
+ return Boolean.parseBoolean(property);
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksProperties.java
new file mode 100644
index 0000000..147336f
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksProperties.java
@@ -0,0 +1,27 @@
+package ca.uhn.fhir.jpa.starter.cdshooks;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties(prefix = "hapi.fhir.cdshooks")
+public class CdsHooksProperties {
+
+ private boolean enabled;
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ private String clientIdHeaderName;
+
+ public String getClientIdHeaderName() {
+ return clientIdHeaderName;
+ }
+
+ public void setClientIdHeaderName(String clientIdHeaderName) {
+ this.clientIdHeaderName = clientIdHeaderName;
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksRequest.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksRequest.java
new file mode 100644
index 0000000..088eab2
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksRequest.java
@@ -0,0 +1,7 @@
+package ca.uhn.fhir.jpa.starter.cdshooks;
+
+import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties({"extension"})
+public class CdsHooksRequest extends CdsServiceRequestJson {}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java
new file mode 100644
index 0000000..5849ec5
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java
@@ -0,0 +1,129 @@
+package ca.uhn.fhir.jpa.starter.cdshooks;
+
+import ca.uhn.fhir.jpa.starter.AppProperties;
+import ca.uhn.fhir.rest.server.RestfulServer;
+import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
+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.CdsServiceResponseJson;
+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;
+
+@Configurable
+public class CdsHooksServlet extends HttpServlet {
+ private static final Logger logger = LoggerFactory.getLogger(CdsHooksServlet.class);
+ private static final long serialVersionUID = 1L;
+
+ @Autowired
+ private AppProperties appProperties;
+
+ @Autowired
+ private ProviderConfiguration providerConfiguration;
+
+ @Autowired
+ ICdsServiceRegistry cdsServiceRegistry;
+
+ @Autowired
+ RestfulServer restfulServer;
+
+ @Autowired
+ @Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY)
+ ObjectMapper objectMapper;
+
+ protected ProviderConfiguration getProviderConfiguration() {
+ return this.providerConfiguration;
+ }
+
+ // CORS Pre-flight
+ @Override
+ protected void doOptions(HttpServletRequest req, HttpServletResponse resp) {
+ ErrorHandling.setAccessControlHeaders(resp, appProperties);
+ resp.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType());
+ resp.setHeader("X-Content-Type-Options", "nosniff");
+ resp.setStatus(HttpServletResponse.SC_OK);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ logger.info(request.getRequestURI());
+ if (!request.getRequestURL().toString().endsWith("/cds-services")
+ && !request.getRequestURL().toString().endsWith("/cds-services/")) {
+ logger.error(request.getRequestURI());
+ throw new ServletException("This servlet is not configured to handle GET requests.");
+ }
+ ErrorHandling.setAccessControlHeaders(response, appProperties);
+ response.setHeader("Content-Type", ContentType.APPLICATION_JSON.getMimeType());
+ response.getWriter()
+ .println(new GsonBuilder()
+ .setPrettyPrinting()
+ .create()
+ .toJson(JsonParser.parseString(objectMapper.writeValueAsString(getServices()))));
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ try {
+ if (request.getContentType() == null || !request.getContentType().startsWith("application/json")) {
+ throw new ServletException(String.format(
+ "Invalid content type %s. Please use application/json.", request.getContentType()));
+ }
+ logger.info(request.getRequestURI());
+ String service = request.getPathInfo().replace("/", "");
+
+ String requestJson = request.getReader().lines().collect(Collectors.joining());
+ CdsHooksRequest cdsHooksRequest = objectMapper.readValue(requestJson, CdsHooksRequest.class);
+ logRequestInfo(cdsHooksRequest, requestJson);
+
+ CdsServiceResponseJson serviceResponseJson = cdsServiceRegistry.callService(service, cdsHooksRequest);
+
+ // Using GSON pretty print format as Jackson's is ugly
+ String jsonResponse = new GsonBuilder()
+ .disableHtmlEscaping()
+ .setPrettyPrinting()
+ .create()
+ .toJson(JsonParser.parseString(objectMapper.writeValueAsString(serviceResponseJson)));
+ logger.info(jsonResponse);
+ response.setContentType("text/json;charset=UTF-8");
+ response.getWriter().println(jsonResponse);
+ } catch (BaseServerResponseException e) {
+ ErrorHandling.handleError(response, "ERROR: Exception connecting to remote server.", e, appProperties);
+ logger.error(e.toString());
+ } catch (Exception e) {
+ logger.error(e.toString());
+ throw new ServletException("ERROR: Exception in cds-hooks processing.", e);
+ }
+ }
+
+ private void logRequestInfo(CdsServiceRequestJson request, String jsonRequest) {
+ logger.info(jsonRequest);
+ logger.info("cds-hooks hook instance: {}", request.getHookInstance());
+ logger.info("cds-hooks local server address: {}", appProperties.getServer_address());
+ logger.info("cds-hooks fhir server address: {}", request.getFhirServer());
+ logger.info(
+ "cds-hooks cql_logging_enabled: {}",
+ this.getProviderConfiguration().getCqlLoggingEnabled());
+ }
+
+ private CdsServicesJson getServices() {
+ return cdsServiceRegistry.getCdsServicesJson();
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java
new file mode 100644
index 0000000..38e8d7b
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java
@@ -0,0 +1,105 @@
+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.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import javax.servlet.http.HttpServletResponse;
+
+public class ErrorHandling {
+
+ private ErrorHandling() {}
+
+ public static void handleError(
+ HttpServletResponse response, String message, Exception e, AppProperties myAppProperties)
+ throws IOException {
+ setAccessControlHeaders(response, myAppProperties);
+ response.setStatus(500); // This will be overwritten with the correct status code downstream if needed.
+ response.getWriter().println(message);
+ printMessageAndCause(e, response);
+ if (e instanceof BaseServerResponseException) {
+ handleServerResponseException((BaseServerResponseException) e, response);
+ } else if (e.getCause() instanceof BaseServerResponseException) {
+ handleServerResponseException((BaseServerResponseException) e.getCause(), response);
+ }
+ printStackTrack(e, response);
+ }
+
+ private static void handleServerResponseException(BaseServerResponseException e, HttpServletResponse response)
+ throws IOException {
+ switch (e.getStatusCode()) {
+ case 401:
+ case 403:
+ response.getWriter().println("Precondition Failed. Remote FHIR server returned: " + e.getStatusCode());
+ response.getWriter()
+ .println(
+ "Ensure that the fhirAuthorization token is set or that the remote server allows unauthenticated access.");
+ response.setStatus(412);
+ break;
+ case 404:
+ response.getWriter().println("Precondition Failed. Remote FHIR server returned: " + e.getStatusCode());
+ response.getWriter().println("Ensure the resource exists on the remote server.");
+ response.setStatus(412);
+ break;
+ default:
+ response.getWriter().println("Unhandled Error in Remote FHIR server: " + e.getStatusCode());
+ }
+ }
+
+ private static void printMessageAndCause(Exception e, HttpServletResponse response) throws IOException {
+ if (e.getMessage() != null) {
+ response.getWriter().println(e.getMessage());
+ }
+
+ if (e.getCause() != null && e.getCause().getMessage() != null) {
+ response.getWriter().println(e.getCause().getMessage());
+ }
+ }
+
+ private static void printStackTrack(Exception e, HttpServletResponse response) throws IOException {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ String exceptionAsString = sw.toString();
+ response.getWriter().println(exceptionAsString);
+ }
+
+ public static void setAccessControlHeaders(HttpServletResponse resp, AppProperties myAppProperties) {
+ if (myAppProperties.getCors() != null) {
+ if (myAppProperties.getCors().getAllow_Credentials()) {
+ resp.setHeader(
+ "Access-Control-Allow-Origin",
+ myAppProperties.getCors().getAllowed_origin().stream()
+ .findFirst()
+ .get());
+ resp.setHeader(
+ "Access-Control-Allow-Methods",
+ String.join(", ", Arrays.asList("GET", "HEAD", "POST", "OPTIONS")));
+ resp.setHeader(
+ "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 CdsHooksError(String message) {
+ super(message);
+ }
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ProviderConfiguration.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ProviderConfiguration.java
new file mode 100644
index 0000000..edb4a89
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ProviderConfiguration.java
@@ -0,0 +1,30 @@
+package ca.uhn.fhir.jpa.starter.cdshooks;
+
+import ca.uhn.fhir.jpa.starter.cr.CrProperties;
+
+public class ProviderConfiguration {
+
+ public static final ProviderConfiguration DEFAULT_PROVIDER_CONFIGURATION =
+ new ProviderConfiguration(false, "client_id");
+
+ private final String clientIdHeaderName;
+ private final boolean cqlLoggingEnabled;
+
+ public ProviderConfiguration(boolean cqlLoggingEnabled, String clientIdHeaderName) {
+ this.cqlLoggingEnabled = cqlLoggingEnabled;
+ this.clientIdHeaderName = clientIdHeaderName;
+ }
+
+ public ProviderConfiguration(CdsHooksProperties cdsProperties, CrProperties crProperties) {
+ this.clientIdHeaderName = cdsProperties.getClientIdHeaderName();
+ this.cqlLoggingEnabled = crProperties.isCqlRuntimeDebugLoggingEnabled();
+ }
+
+ public String getClientIdHeaderName() {
+ return this.clientIdHeaderName;
+ }
+
+ public boolean getCqlLoggingEnabled() {
+ return this.cqlLoggingEnabled;
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/StarterCdsHooksConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/StarterCdsHooksConfig.java
new file mode 100644
index 0000000..cb1371f
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/StarterCdsHooksConfig.java
@@ -0,0 +1,66 @@
+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.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Configuration
+@Conditional({CdsHooksConfigCondition.class, CrConfigCondition.class})
+@Import(CdsHooksConfig.class)
+public class StarterCdsHooksConfig {
+ @Bean
+ public CdsHooksProperties cdsHooksProperties() {
+ return new CdsHooksProperties();
+ }
+
+ @Bean
+ public CdsCrSettings cdsCrSettings(CdsHooksProperties cdsHooksProperties) {
+ CdsCrSettings settings = CdsCrSettings.getDefault();
+ settings.setClientIdHeaderName(cdsHooksProperties.getClientIdHeaderName());
+ return settings;
+ }
+
+ @Bean
+ public CdsHooksContextBooter cdsHooksContextBooter() {
+ // ourLog.info("No Spring Context provided. Assuming all CDS Services will be registered dynamically.");
+ return new CdsHooksContextBooter();
+ }
+
+ public static class CdsHooksDaoAuthorizationSvc implements ICdsHooksDaoAuthorizationSvc {
+ @Override
+ public void authorizePreShow(IBaseResource theResource) {}
+ }
+
+ @Bean
+ public ProviderConfiguration providerConfiguration(CdsHooksProperties cdsProperties, CrProperties crProperties) {
+ return new ProviderConfiguration(cdsProperties, crProperties);
+ }
+
+ @Bean
+ ICdsHooksDaoAuthorizationSvc cdsHooksDaoAuthorizationSvc() {
+ return new CdsHooksDaoAuthorizationSvc();
+ }
+
+ @Bean
+ public ServletRegistrationBean cdsHooksRegistrationBean(AutowireCapableBeanFactory beanFactory) {
+ CdsHooksServlet cdsHooksServlet = new CdsHooksServlet();
+ beanFactory.autowireBean(cdsHooksServlet);
+
+ ServletRegistrationBean registrationBean = new ServletRegistrationBean<>();
+ registrationBean.setName("cds-hooks servlet");
+ registrationBean.setServlet(cdsHooksServlet);
+ registrationBean.addUrlMappings("/cds-services/*");
+ registrationBean.setLoadOnStartup(1);
+ return registrationBean;
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java
index 78de890..df8ce49 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/ElasticsearchConfig.java
@@ -10,18 +10,20 @@ import org.springframework.core.env.ConfigurableEnvironment;
@Configuration
public class ElasticsearchConfig {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElasticsearchConfig.class);
+
@Bean
public ElasticsearchSvcImpl elasticsearchSvc(ConfigurableEnvironment configurableEnvironment) {
if (EnvironmentHelper.isElasticsearchEnabled(configurableEnvironment)) {
String elasticsearchUrl = EnvironmentHelper.getElasticsearchServerUrl(configurableEnvironment);
if (elasticsearchUrl.startsWith("http")) {
- elasticsearchUrl =elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3);
+ elasticsearchUrl = elasticsearchUrl.substring(elasticsearchUrl.indexOf("://") + 3);
}
String elasticsearchProtocol = EnvironmentHelper.getElasticsearchServerProtocol(configurableEnvironment);
String elasticsearchUsername = EnvironmentHelper.getElasticsearchServerUsername(configurableEnvironment);
String elasticsearchPassword = EnvironmentHelper.getElasticsearchServerPassword(configurableEnvironment);
ourLog.info("Configuring elasticsearch {} {}", elasticsearchProtocol, elasticsearchUrl);
- return new ElasticsearchSvcImpl(elasticsearchProtocol, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword);
+ return new ElasticsearchSvcImpl(
+ elasticsearchProtocol, elasticsearchUrl, elasticsearchUsername, elasticsearchPassword);
} else {
return null;
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java
index d01df5b..b0267d4 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigCommon.java
@@ -15,7 +15,6 @@ import ca.uhn.fhir.rest.server.mail.MailConfig;
import ca.uhn.fhir.rest.server.mail.MailSvc;
import com.google.common.base.Strings;
import org.hl7.fhir.r4.model.Bundle.BundleType;
-
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -24,6 +23,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
+import java.util.HashSet;
import java.util.stream.Collectors;
/**
@@ -33,210 +33,239 @@ import java.util.stream.Collectors;
@EnableTransactionManagement
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) {
+ ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny")
+ + " contains searches");
+ ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny")
+ + " multiple deletes");
+ ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny")
+ + " external references");
+ ourLog.info("Server configured to " + (appProperties.getDao_scheduling_enabled() ? "enable" : "disable")
+ + " DAO scheduling");
+ 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());
- public FhirServerConfigCommon(AppProperties appProperties) {
- ourLog.info("Server configured to " + (appProperties.getAllow_contains_searches() ? "allow" : "deny") + " contains searches");
- ourLog.info("Server configured to " + (appProperties.getAllow_multiple_delete() ? "allow" : "deny") + " multiple deletes");
- ourLog.info("Server configured to " + (appProperties.getAllow_external_references() ? "allow" : "deny") + " external references");
- ourLog.info("Server configured to " + (appProperties.getDao_scheduling_enabled() ? "enable" : "disable") + " DAO scheduling");
- 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) {
+ AppProperties.Subscription.Email email =
+ appProperties.getSubscription().getEmail();
+ 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");
- if (appProperties.getSubscription().getEmail() != null) {
- AppProperties.Subscription.Email email = appProperties.getSubscription().getEmail();
- 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");
+ if (!Strings.isNullOrEmpty(email.getUsername())) {
+ ourLog.info("Server is configured to use username '" + email.getUsername() + "' for email");
+ }
- if (!Strings.isNullOrEmpty(email.getUsername())) {
- ourLog.info("Server is configured to use username '" + email.getUsername() + "' for email");
- }
+ if (!Strings.isNullOrEmpty(email.getPassword())) {
+ ourLog.info("Server is configured to use a password for email");
+ }
+ }
- if (!Strings.isNullOrEmpty(email.getPassword())) {
- ourLog.info("Server is configured to use a password for email");
- }
- }
+ if (appProperties.getSubscription().getResthook_enabled()) {
+ ourLog.info("REST-hook subscriptions enabled");
+ }
- if (appProperties.getSubscription().getResthook_enabled()) {
- ourLog.info("REST-hook subscriptions enabled");
- }
+ if (appProperties.getSubscription().getEmail() != null) {
+ ourLog.info("Email subscriptions enabled");
+ }
- if (appProperties.getSubscription().getEmail() != null) {
- ourLog.info("Email subscriptions enabled");
- }
+ if (appProperties.getEnable_index_contained_resource() == Boolean.TRUE) {
+ ourLog.info("Indexed on contained resource enabled");
+ }
+ }
- if (appProperties.getEnable_index_contained_resource() == Boolean.TRUE) {
- ourLog.info("Indexed on contained resource enabled");
- }
- }
+ /**
+ * Configure FHIR properties around the the JPA server via this bean
+ */
+ @Bean
+ public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {
+ JpaStorageSettings jpaStorageSettings = new JpaStorageSettings();
- /**
- * Configure FHIR properties around the the JPA server via this bean
- */
- @Bean
- public JpaStorageSettings jpaStorageSettings(AppProperties appProperties) {
- JpaStorageSettings jpaStorageSettings = new JpaStorageSettings();
+ jpaStorageSettings.setIndexMissingFields(
+ appProperties.getEnable_index_missing_fields()
+ ? StorageSettings.IndexEnabledEnum.ENABLED
+ : StorageSettings.IndexEnabledEnum.DISABLED);
+ jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(
+ appProperties.getAuto_create_placeholder_reference_targets());
+ jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths());
+ jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(
+ appProperties.getEnforce_referential_integrity_on_write());
+ jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(
+ appProperties.getEnforce_referential_integrity_on_delete());
+ jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
+ 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());
- jpaStorageSettings.setIndexMissingFields(appProperties.getEnable_index_missing_fields() ? StorageSettings.IndexEnabledEnum.ENABLED : StorageSettings.IndexEnabledEnum.DISABLED);
- jpaStorageSettings.setAutoCreatePlaceholderReferenceTargets(appProperties.getAuto_create_placeholder_reference_targets());
- jpaStorageSettings.setAutoVersionReferenceAtPaths(appProperties.getAuto_version_reference_at_paths());
- jpaStorageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write());
- jpaStorageSettings.setEnforceReferentialIntegrityOnDelete(appProperties.getEnforce_referential_integrity_on_delete());
- jpaStorageSettings.setAllowContainsSearches(appProperties.getAllow_contains_searches());
- 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();
+ jpaStorageSettings.setFetchSizeDefaultMaximum(maxFetchSize);
+ ourLog.info("Server configured to have a maximum fetch size of "
+ + (maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize));
- Integer maxFetchSize = appProperties.getMax_page_size();
- jpaStorageSettings.setFetchSizeDefaultMaximum(maxFetchSize);
- ourLog.info("Server configured to have a maximum fetch size of " + (maxFetchSize == Integer.MAX_VALUE ? "'unlimited'" : maxFetchSize));
+ Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis();
+ jpaStorageSettings.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis);
+ ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis);
- Long reuseCachedSearchResultsMillis = appProperties.getReuse_cached_search_results_millis();
- jpaStorageSettings.setReuseCachedSearchResultsForMillis(reuseCachedSearchResultsMillis);
- ourLog.info("Server configured to cache search results for {} milliseconds", reuseCachedSearchResultsMillis);
+ Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins();
+ jpaStorageSettings.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000);
+ if (appProperties.getSubscription() != null) {
+ // Subscriptions are enabled by channel type
+ if (appProperties.getSubscription().getResthook_enabled()) {
+ ourLog.info("Enabling REST-hook subscriptions");
+ jpaStorageSettings.addSupportedSubscriptionType(
+ org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
+ }
+ if (appProperties.getSubscription().getEmail() != null) {
+ ourLog.info("Enabling email subscriptions");
+ jpaStorageSettings.addSupportedSubscriptionType(
+ org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
+ }
+ if (appProperties.getSubscription().getWebsocket_enabled()) {
+ ourLog.info("Enabling websocket subscriptions");
+ jpaStorageSettings.addSupportedSubscriptionType(
+ org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET);
+ }
+ }
- Long retainCachedSearchesMinutes = appProperties.getRetain_cached_searches_mins();
- jpaStorageSettings.setExpireSearchResultsAfterMillis(retainCachedSearchesMinutes * 60 * 1000);
+ jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
+ jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing());
+ jpaStorageSettings.setTreatBaseUrlsAsLocal(new HashSet<>(appProperties.getLocal_base_urls()));
- if(appProperties.getSubscription() != null) {
- // Subscriptions are enabled by channel type
- if (appProperties.getSubscription().getResthook_enabled()) {
- ourLog.info("Enabling REST-hook subscriptions");
- jpaStorageSettings.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.RESTHOOK);
- }
- if (appProperties.getSubscription().getEmail() != null) {
- ourLog.info("Enabling email subscriptions");
- jpaStorageSettings.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.EMAIL);
- }
- if (appProperties.getSubscription().getWebsocket_enabled()) {
- ourLog.info("Enabling websocket subscriptions");
- jpaStorageSettings.addSupportedSubscriptionType(org.hl7.fhir.dstu2.model.Subscription.SubscriptionChannelType.WEBSOCKET);
- }
- }
+ if (appProperties.getLastn_enabled()) {
+ jpaStorageSettings.setLastNEnabled(true);
+ }
- jpaStorageSettings.setFilterParameterEnabled(appProperties.getFilter_search_enabled());
- jpaStorageSettings.setAdvancedHSearchIndexing(appProperties.getAdvanced_lucene_indexing());
- jpaStorageSettings.setTreatBaseUrlsAsLocal(appProperties.getLocal_base_urls());
+ if (appProperties.getInline_resource_storage_below_size() != 0) {
+ jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size());
+ }
- if (appProperties.getLastn_enabled()) {
- jpaStorageSettings.setLastNEnabled(true);
- }
+ jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled());
+ jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
+ jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
- if(appProperties.getInline_resource_storage_below_size() != 0){
- jpaStorageSettings.setInlineResourceTextBelowSize(appProperties.getInline_resource_storage_below_size());
- }
+ if (appProperties.getAllowed_bundle_types() != null) {
+ jpaStorageSettings.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream()
+ .map(BundleType::toCode)
+ .collect(Collectors.toSet()));
+ }
- jpaStorageSettings.setStoreResourceInHSearchIndex(appProperties.getStore_resource_in_lucene_index_enabled());
- jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
- jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
+ jpaStorageSettings.setDeferIndexingForCodesystemsOfSize(
+ appProperties.getDefer_indexing_for_codesystems_of_size());
+ if (appProperties.getClient_id_strategy() == JpaStorageSettings.ClientIdStrategyEnum.ANY) {
+ 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());
+ storageSettings(appProperties, jpaStorageSettings);
+ return jpaStorageSettings;
+ }
- if (appProperties.getAllowed_bundle_types() != null) {
- jpaStorageSettings.setBundleTypesAllowedForStorage(appProperties.getAllowed_bundle_types().stream().map(BundleType::toCode).collect(Collectors.toSet()));
- }
+ @Bean
+ public YamlPropertySourceLoader yamlPropertySourceLoader() {
+ return new YamlPropertySourceLoader();
+ }
- jpaStorageSettings.setDeferIndexingForCodesystemsOfSize(appProperties.getDefer_indexing_for_codesystems_of_size());
+ @Bean
+ public PartitionSettings partitionSettings(AppProperties appProperties) {
+ PartitionSettings retVal = new PartitionSettings();
+ // Partitioning
+ 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);
+ }
+ }
- if (appProperties.getClient_id_strategy() == JpaStorageSettings.ClientIdStrategyEnum.ANY) {
- 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());
+ return retVal;
+ }
- storageSettings(appProperties, jpaStorageSettings);
- return jpaStorageSettings;
- }
+ @Primary
+ @Bean
+ public HibernatePropertiesProvider jpaStarterDialectProvider(
+ LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
+ return new JpaHibernatePropertiesProvider(myEntityManagerFactory);
+ }
- @Bean
- public YamlPropertySourceLoader yamlPropertySourceLoader() {
- return new YamlPropertySourceLoader();
- }
+ protected StorageSettings storageSettings(AppProperties appProperties, JpaStorageSettings jpaStorageSettings) {
+ 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());
- @Bean
- public PartitionSettings partitionSettings(AppProperties appProperties) {
- PartitionSettings retVal = new PartitionSettings();
+ jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
- // Partitioning
- 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);
- }
- }
+ jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
+ jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
+ return jpaStorageSettings;
+ }
- return retVal;
- }
+ @Lazy
+ @Bean
+ public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
+ DatabaseBlobBinaryStorageSvcImpl binaryStorageSvc = new DatabaseBlobBinaryStorageSvcImpl();
+ if (appProperties.getMax_binary_size() != null) {
+ binaryStorageSvc.setMaximumBinarySize(appProperties.getMax_binary_size());
+ }
- @Primary
- @Bean
- public HibernatePropertiesProvider jpaStarterDialectProvider(LocalContainerEntityManagerFactoryBean myEntityManagerFactory) {
- return new JpaHibernatePropertiesProvider(myEntityManagerFactory);
- }
+ return binaryStorageSvc;
+ }
+ @Bean
+ public IEmailSender emailSender(AppProperties appProperties) {
+ if (appProperties.getSubscription() != null
+ && appProperties.getSubscription().getEmail() != null) {
- protected StorageSettings storageSettings(AppProperties appProperties, JpaStorageSettings jpaStorageSettings) {
- 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());
+ return buildEmailSender(appProperties.getSubscription().getEmail());
+ }
- jpaStorageSettings.setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level());
-
- jpaStorageSettings.setIndexOnContainedResources(appProperties.getEnable_index_contained_resource());
- jpaStorageSettings.setIndexIdentifierOfType(appProperties.getEnable_index_of_type());
- return jpaStorageSettings;
- }
-
- @Lazy
- @Bean
- public IBinaryStorageSvc binaryStorageSvc(AppProperties appProperties) {
- DatabaseBlobBinaryStorageSvcImpl binaryStorageSvc = new DatabaseBlobBinaryStorageSvcImpl();
-
- 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 -> {};
- }
+ // 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) {
return new EmailSenderImpl(new MailSvc(new MailConfig()
- .setSmtpHostname(email.getHost())
- .setSmtpPort(email.getPort())
- .setSmtpUsername(email.getUsername())
- .setSmtpPassword(email.getPassword())
- .setSmtpUseStartTLS(email.getStartTlsEnable())));
+ .setSmtpHostname(email.getHost())
+ .setSmtpPort(email.getPort())
+ .setSmtpUsername(email.getUsername())
+ .setSmtpPassword(email.getPassword())
+ .setSmtpUseStartTLS(email.getStartTlsEnable())));
}
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java
index 9416d28..0047fa4 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu2.java
@@ -13,14 +13,11 @@ import org.springframework.context.annotation.Import;
@Configuration
@Conditional(OnDSTU2Condition.class)
-@Import({
- JpaDstu2Config.class,
- StarterJpaConfig.class
-})
+@Import({JpaDstu2Config.class, StarterJpaConfig.class})
public class FhirServerConfigDstu2 {
@Bean
- public ITermLoaderSvc termLoaderService(ITermDeferredStorageSvc theDeferredStorageSvc, ITermCodeSystemStorageSvc theCodeSystemStorageSvc) {
+ public ITermLoaderSvc termLoaderService(
+ ITermDeferredStorageSvc theDeferredStorageSvc, ITermCodeSystemStorageSvc theCodeSystemStorageSvc) {
return new TermLoaderSvcImpl(theDeferredStorageSvc, theCodeSystemStorageSvc);
}
-
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java
index 085764d..a029d11 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigDstu3.java
@@ -9,10 +9,5 @@ import org.springframework.context.annotation.Import;
@Configuration
@Conditional(OnDSTU3Condition.class)
-@Import({
- JpaDstu3Config.class,
- StarterJpaConfig.class,
- StarterCrDstu3Config.class,
- ElasticsearchConfig.class})
-public class FhirServerConfigDstu3 {
-}
+@Import({JpaDstu3Config.class, StarterJpaConfig.class, StarterCrDstu3Config.class, ElasticsearchConfig.class})
+public class FhirServerConfigDstu3 {}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java
index 61dbab5..55dce56 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4.java
@@ -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.cr.StarterCrR4Config;
import ca.uhn.fhir.jpa.starter.ips.StarterIpsConfig;
-
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -18,5 +17,4 @@ import org.springframework.context.annotation.Import;
ElasticsearchConfig.class,
StarterIpsConfig.class
})
-public class FhirServerConfigR4 {
-}
+public class FhirServerConfigR4 {}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java
index 4272017..ab267de 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR4B.java
@@ -9,11 +9,5 @@ import org.springframework.context.annotation.Import;
@Configuration
@Conditional(OnR4BCondition.class)
-@Import({
- JpaR4BConfig.class,
- SubscriptionTopicConfig.class,
- StarterJpaConfig.class,
- ElasticsearchConfig.class
-})
-public class FhirServerConfigR4B {
-}
+@Import({JpaR4BConfig.class, SubscriptionTopicConfig.class, StarterJpaConfig.class, ElasticsearchConfig.class})
+public class FhirServerConfigR4B {}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java
index 5e2e430..0aaa650 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirServerConfigR5.java
@@ -9,11 +9,5 @@ import org.springframework.context.annotation.Import;
@Configuration
@Conditional(OnR5Condition.class)
-@Import({
- StarterJpaConfig.class,
- JpaR5Config.class,
- SubscriptionTopicConfig.class,
- ElasticsearchConfig.class
-})
-public class FhirServerConfigR5 {
-}
+@Import({StarterJpaConfig.class, JpaR5Config.class, SubscriptionTopicConfig.class, ElasticsearchConfig.class})
+public class FhirServerConfigR5 {}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java
index c8c8925..7e2b679 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfig.java
@@ -4,11 +4,10 @@ import ca.uhn.fhir.jpa.starter.AppProperties;
import ca.uhn.fhir.to.FhirTesterMvcConfig;
import ca.uhn.fhir.to.TesterConfig;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-//@formatter:off
+// @formatter:off
/**
* This spring config file configures the web testing module. It serves two
* purposes:
@@ -19,7 +18,7 @@ import org.springframework.context.annotation.Import;
*/
@Configuration
@Import(FhirTesterMvcConfig.class)
-@Conditional(FhirTesterConfigCondition.class)
+// @Conditional(FhirTesterConfigCondition.class)
public class FhirTesterConfig {
/**
@@ -36,22 +35,18 @@ public class FhirTesterConfig {
* deploying your server to a place with a fully qualified domain name,
* you might want to use that instead of using the variable.
*/
- @Bean
- public TesterConfig testerConfig(AppProperties appProperties) {
- TesterConfig retVal = new TesterConfig();
- appProperties.getTester().forEach((key, value) -> {
- retVal
- .addServer()
- .withId(key)
- .withFhirVersion(value.getFhir_version())
- .withBaseUrl(value.getServer_address())
- .withName(value.getName());
- retVal.setRefuseToFetchThirdPartyUrls(
- value.getRefuse_to_fetch_third_party_urls());
-
- });
- return retVal;
- }
-
+ @Bean
+ public TesterConfig testerConfig(AppProperties appProperties) {
+ TesterConfig retVal = new TesterConfig();
+ appProperties.getTester().forEach((key, value) -> {
+ retVal.addServer()
+ .withId(key)
+ .withFhirVersion(value.getFhir_version())
+ .withBaseUrl(value.getServer_address())
+ .withName(value.getName());
+ retVal.setRefuseToFetchThirdPartyUrls(value.getRefuse_to_fetch_third_party_urls());
+ });
+ return retVal;
+ }
}
-//@formatter:on
+// @formatter:on
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java
index f5670d9..e385b1c 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/FhirTesterConfigCondition.java
@@ -9,8 +9,9 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
public class FhirTesterConfigCondition implements Condition {
@Override
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();
}
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java
index 30c26fe..cc8eb18 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java
@@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.starter.common;
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.reindex.ReindexJobParameters;
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.FhirVersionEnum;
import ca.uhn.fhir.context.support.IValidationSupport;
-
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.jpa.api.IDaoRegistry;
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.binary.interceptor.BinaryStorageInterceptor;
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.ResourceCountCacheUtil;
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.PackageInstallationSpec;
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.*;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
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.OnImplementationGuidesPresent;
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.util.EnvironmentHelper;
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
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.rest.api.IResourceSupportedSvc;
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.interceptor.*;
-import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
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.web.cors.CorsConfiguration;
+import java.util.*;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
-import java.util.*;
import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR;
@Configuration
-//allow users to configure custom packages to scan for additional beans
-@ComponentScan(basePackages = { "${hapi.fhir.custom-bean-packages:}" })
-@Import(
- ThreadPoolFactoryConfig.class
-)
+// allow users to configure custom packages to scan for additional beans
+@ComponentScan(basePackages = {"${hapi.fhir.custom-bean-packages:}"})
+@Import(ThreadPoolFactoryConfig.class)
public class StarterJpaConfig {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StarterJpaConfig.class);
@@ -107,12 +104,9 @@ public class StarterJpaConfig {
return ValidationSupportConfigUtil.newCachingValidationSupport(theJpaValidationSupportChain);
}
-
@Autowired
private ConfigurableEnvironment configurableEnvironment;
-
-
/**
* 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.
@@ -125,7 +119,6 @@ public class StarterJpaConfig {
return pagingProvider;
}
-
@Bean
public IResourceSupportedSvc resourceSupportedSvc(IDaoRegistry theDaoRegistry) {
return new DaoRegistryResourceSupportedSvc(theDaoRegistry);
@@ -138,8 +131,12 @@ public class StarterJpaConfig {
@Primary
@Bean
- public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource myDataSource, ConfigurableListableBeanFactory myConfigurableListableBeanFactory, FhirContext theFhirContext) {
- LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext);
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory(
+ DataSource myDataSource,
+ ConfigurableListableBeanFactory myConfigurableListableBeanFactory,
+ FhirContext theFhirContext) {
+ LocalContainerEntityManagerFactoryBean retVal =
+ HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext);
retVal.setPersistenceUnitName("HAPI_PU");
try {
@@ -147,7 +144,8 @@ public class StarterJpaConfig {
} catch (Exception 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;
}
@@ -164,10 +162,10 @@ public class StarterJpaConfig {
return new HSearchSortHelperImpl(mySearchParamRegistry);
}
-
@Bean
@ConditionalOnProperty(prefix = "hapi.fhir", name = ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR, havingValue = "true")
- public RepositoryValidatingInterceptor repositoryValidatingInterceptor(IRepositoryValidationInterceptorFactory factory) {
+ public RepositoryValidatingInterceptor repositoryValidatingInterceptor(
+ IRepositoryValidationInterceptorFactory factory) {
return factory.buildUsingStoredStructureDefinitions();
}
@@ -189,8 +187,11 @@ public class StarterJpaConfig {
@Bean("packageInstaller")
@Primary
@Conditional(OnImplementationGuidesPresent.class)
- public IPackageInstallerSvc packageInstaller(AppProperties appProperties, JobDefinition reindexJobParametersJobDefinition, JobDefinitionRegistry jobDefinitionRegistry, IPackageInstallerSvc packageInstallerSvc)
- {
+ public IPackageInstallerSvc packageInstaller(
+ AppProperties appProperties,
+ JobDefinition reindexJobParametersJobDefinition,
+ JobDefinitionRegistry jobDefinitionRegistry,
+ IPackageInstallerSvc packageInstallerSvc) {
jobDefinitionRegistry.addJobDefinitionIfNotRegistered(reindexJobParametersJobDefinition);
if (appProperties.getImplementationGuides() != null) {
@@ -199,7 +200,8 @@ public class StarterJpaConfig {
PackageInstallationSpec packageInstallationSpec = guidesEntry.getValue();
if (appProperties.getInstall_transitive_ig_dependencies()) {
- packageInstallationSpec.addDependencyExclude("hl7.fhir.r2.core")
+ packageInstallationSpec
+ .addDependencyExclude("hl7.fhir.r2.core")
.addDependencyExclude("hl7.fhir.r3.core")
.addDependencyExclude("hl7.fhir.r4.core")
.addDependencyExclude("hl7.fhir.r5.core");
@@ -238,11 +240,40 @@ public class StarterJpaConfig {
// Create the interceptor and register it
return new CorsInterceptor(config);
-
}
@Bean
- public RestfulServer restfulServer(IFhirSystemDao, ?> fhirSystemDao, AppProperties appProperties, DaoRegistry daoRegistry, Optional mdmProviderProvider, IJpaSystemProvider jpaSystemProvider, ResourceProviderFactory resourceProviderFactory, JpaStorageSettings jpaStorageSettings, ISearchParamRegistry searchParamRegistry, IValidationSupport theValidationSupport, DatabaseBackedPagingProvider databaseBackedPagingProvider, LoggingInterceptor loggingInterceptor, Optional terminologyUploaderProvider, Optional subscriptionTriggeringProvider, Optional corsInterceptor, IInterceptorBroadcaster interceptorBroadcaster, Optional binaryAccessProvider, BinaryStorageInterceptor binaryStorageInterceptor, IValidatorModule validatorModule, Optional graphQLProvider, BulkDataExportProvider bulkDataExportProvider, BulkDataImportProvider bulkDataImportProvider, ValueSetOperationProvider theValueSetOperationProvider, ReindexProvider reindexProvider, PartitionManagementProvider partitionManagementProvider, Optional repositoryValidatingInterceptor, IPackageInstallerSvc packageInstallerSvc, ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc, ApplicationContext appContext, Optional theIpsOperationProvider, Optional implementationGuideOperationProvider) {
+ public RestfulServer restfulServer(
+ IFhirSystemDao, ?> fhirSystemDao,
+ AppProperties appProperties,
+ DaoRegistry daoRegistry,
+ Optional mdmProviderProvider,
+ IJpaSystemProvider jpaSystemProvider,
+ ResourceProviderFactory resourceProviderFactory,
+ JpaStorageSettings jpaStorageSettings,
+ ISearchParamRegistry searchParamRegistry,
+ IValidationSupport theValidationSupport,
+ DatabaseBackedPagingProvider databaseBackedPagingProvider,
+ LoggingInterceptor loggingInterceptor,
+ Optional terminologyUploaderProvider,
+ Optional subscriptionTriggeringProvider,
+ Optional corsInterceptor,
+ IInterceptorBroadcaster interceptorBroadcaster,
+ Optional binaryAccessProvider,
+ BinaryStorageInterceptor binaryStorageInterceptor,
+ IValidatorModule validatorModule,
+ Optional graphQLProvider,
+ BulkDataExportProvider bulkDataExportProvider,
+ BulkDataImportProvider bulkDataImportProvider,
+ ValueSetOperationProvider theValueSetOperationProvider,
+ ReindexProvider reindexProvider,
+ PartitionManagementProvider partitionManagementProvider,
+ Optional repositoryValidatingInterceptor,
+ IPackageInstallerSvc packageInstallerSvc,
+ ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
+ ApplicationContext appContext,
+ Optional theIpsOperationProvider,
+ Optional implementationGuideOperationProvider) {
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
List supportedResourceTypes = appProperties.getSupported_resource_types();
@@ -264,7 +295,8 @@ public class StarterJpaConfig {
fhirServer.registerProviders(resourceProviderFactory.createProviders());
fhirServer.registerProvider(jpaSystemProvider);
- fhirServer.setServerConformanceProvider(calculateConformanceProvider(fhirSystemDao, fhirServer, jpaStorageSettings, searchParamRegistry, theValidationSupport));
+ fhirServer.setServerConformanceProvider(calculateConformanceProvider(
+ fhirSystemDao, fhirServer, jpaStorageSettings, searchParamRegistry, theValidationSupport));
/*
* ETag Support
@@ -272,7 +304,6 @@ public class StarterJpaConfig {
if (!appProperties.getEtag_support_enabled()) fhirServer.setETagSupport(ETagSupportEnum.DISABLED);
-
/*
* Default to JSON and pretty printing
*/
@@ -318,7 +349,8 @@ public class StarterJpaConfig {
fhirServer.setServerAddressStrategy(new HardcodedServerAddressStrategy(serverAddress));
} else if (appProperties.getUse_apache_address_strategy()) {
boolean useHttps = appProperties.getUse_apache_address_strategy_https();
- fhirServer.setServerAddressStrategy(useHttps ? ApacheProxyAddressStrategy.forHttps() : ApacheProxyAddressStrategy.forHttp());
+ fhirServer.setServerAddressStrategy(
+ useHttps ? ApacheProxyAddressStrategy.forHttps() : ApacheProxyAddressStrategy.forHttp());
} else {
fhirServer.setServerAddressStrategy(new IncomingRequestAddressStrategy());
}
@@ -330,7 +362,11 @@ public class StarterJpaConfig {
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
* 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());
}
@@ -348,7 +384,8 @@ public class StarterJpaConfig {
}
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);
}
@@ -391,16 +428,15 @@ public class StarterJpaConfig {
fhirServer.registerProvider(bulkDataExportProvider);
}
- //Bulk Import
+ // Bulk Import
if (appProperties.getBulk_import_enabled()) {
fhirServer.registerProvider(bulkDataImportProvider);
}
-
// valueSet Operations i.e $expand
fhirServer.registerProvider(theValueSetOperationProvider);
- //reindex Provider $reindex
+ // reindex Provider $reindex
fhirServer.registerProvider(reindexProvider);
// Partitioning
@@ -414,8 +450,7 @@ public class StarterJpaConfig {
// register custom interceptors
registerCustomInterceptors(fhirServer, appContext, appProperties.getCustomInterceptorClasses());
-
- //register the IPS Provider
+ // register the IPS Provider
if (!theIpsOperationProvider.isEmpty()) {
fhirServer.registerProvider(theIpsOperationProvider.get());
}
@@ -426,8 +461,9 @@ public class StarterJpaConfig {
/**
* check the properties for custom interceptor classes and registers them.
*/
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private void registerCustomInterceptors(RestfulServer fhirServer, ApplicationContext theAppContext, List customInterceptorClasses) {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ private void registerCustomInterceptors(
+ RestfulServer fhirServer, ApplicationContext theAppContext, List customInterceptorClasses) {
if (customInterceptorClasses == null) {
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();
if (fhirVersion == FhirVersionEnum.DSTU2) {
- JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, jpaStorageSettings);
+ JpaConformanceProviderDstu2 confProvider =
+ new JpaConformanceProviderDstu2(fhirServer, fhirSystemDao, jpaStorageSettings);
confProvider.setImplementationDescription("HAPI FHIR DSTU2 Server");
return confProvider;
} 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");
return confProvider;
} 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");
return confProvider;
} 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");
return confProvider;
} 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");
return confProvider;
} else {
@@ -492,4 +538,3 @@ public class StarterJpaConfig {
}
}
}
-
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java
index 67a40c7..640a5c5 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/IRepositoryValidationInterceptorFactory.java
@@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor;
public interface IRepositoryValidationInterceptorFactory {
String ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR = "enable_repository_validating_interceptor";
+
RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions();
RepositoryValidatingInterceptor build();
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java
index edaade7..f276b86 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryDstu3.java
@@ -37,24 +37,28 @@ public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryV
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
private final IFhirResourceDao structureDefinitionResourceProvider;
- public RepositoryValidationInterceptorFactoryDstu3(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
+ public RepositoryValidationInterceptorFactoryDstu3(
+ RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
this.fhirContext = daoRegistry.getSystemDao().getContext();
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
-
}
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
- IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
- Map> structureDefinitions = results.getResources(0, results.size())
- .stream()
- .map(StructureDefinition.class::cast)
- .collect(Collectors.groupingBy(StructureDefinition::getType));
+ IBundleProvider results = structureDefinitionResourceProvider.search(
+ new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
+ Map> structureDefinitions = results.getResources(0, results.size()).stream()
+ .map(StructureDefinition.class::cast)
+ .collect(Collectors.groupingBy(StructureDefinition::getType));
structureDefinitions.forEach((key, value) -> {
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 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
// 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
List rules = repositoryValidatingRuleBuilder.build();
return new RepositoryValidatingInterceptor(fhirContext, rules);
}
-
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java
index c4fca01..b7df8b9 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4.java
@@ -37,25 +37,29 @@ public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryVali
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
private final IFhirResourceDao structureDefinitionResourceProvider;
- public RepositoryValidationInterceptorFactoryR4(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
+ public RepositoryValidationInterceptorFactoryR4(
+ RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
this.fhirContext = daoRegistry.getSystemDao().getContext();
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
-
}
@Override
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
- IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
- Map> structureDefintions = results.getResources(0, results.size())
- .stream()
- .map(StructureDefinition.class::cast)
- .collect(Collectors.groupingBy(StructureDefinition::getType));
+ IBundleProvider results = structureDefinitionResourceProvider.search(
+ new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
+ Map> structureDefintions = results.getResources(0, results.size()).stream()
+ .map(StructureDefinition.class::cast)
+ .collect(Collectors.groupingBy(StructureDefinition::getType));
structureDefintions.forEach((key, value) -> {
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 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
// 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
List rules = repositoryValidatingRuleBuilder.build();
return new RepositoryValidatingInterceptor(fhirContext, rules);
}
-
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java
index 277af2f..6f6847e 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR4B.java
@@ -37,25 +37,29 @@ public class RepositoryValidationInterceptorFactoryR4B implements IRepositoryVal
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
private final IFhirResourceDao structureDefinitionResourceProvider;
- public RepositoryValidationInterceptorFactoryR4B(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
+ public RepositoryValidationInterceptorFactoryR4B(
+ RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
this.fhirContext = daoRegistry.getSystemDao().getContext();
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
-
}
@Override
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
- IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
- Map> structureDefintions = results.getResources(0, results.size())
- .stream()
- .map(StructureDefinition.class::cast)
- .collect(Collectors.groupingBy(StructureDefinition::getType));
+ IBundleProvider results = structureDefinitionResourceProvider.search(
+ new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
+ Map> structureDefintions = results.getResources(0, results.size()).stream()
+ .map(StructureDefinition.class::cast)
+ .collect(Collectors.groupingBy(StructureDefinition::getType));
structureDefintions.forEach((key, value) -> {
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 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
// 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
List rules = repositoryValidatingRuleBuilder.build();
return new RepositoryValidatingInterceptor(fhirContext, rules);
}
-
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java
index 594800d..7f3b38b 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/validation/RepositoryValidationInterceptorFactoryR5.java
@@ -37,24 +37,28 @@ public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryVali
private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;
private final IFhirResourceDao structureDefinitionResourceProvider;
- public RepositoryValidationInterceptorFactoryR5(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
+ public RepositoryValidationInterceptorFactoryR5(
+ RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry) {
this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder;
this.fhirContext = daoRegistry.getSystemDao().getContext();
structureDefinitionResourceProvider = daoRegistry.getResourceDao("StructureDefinition");
-
}
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
- IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
- Map> structureDefintions = results.getResources(0, results.size())
- .stream()
- .map(StructureDefinition.class::cast)
- .collect(Collectors.groupingBy(StructureDefinition::getType));
+ IBundleProvider results = structureDefinitionResourceProvider.search(
+ new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
+ Map> structureDefintions = results.getResources(0, results.size()).stream()
+ .map(StructureDefinition.class::cast)
+ .collect(Collectors.groupingBy(StructureDefinition::getType));
structureDefintions.forEach((key, value) -> {
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 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
// 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
List rules = repositoryValidatingRuleBuilder.build();
return new RepositoryValidatingInterceptor(fhirContext, rules);
}
-
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java
index b488bcf..edbe2f7 100644
--- a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrConfigCondition.java
@@ -6,9 +6,9 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
public class CrConfigCondition implements Condition {
- @Override
- public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
- String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr_enabled");
- return Boolean.parseBoolean(property);
- }
+ @Override
+ public boolean matches(ConditionContext theConditionContext, AnnotatedTypeMetadata theAnnotatedTypeMetadata) {
+ String property = theConditionContext.getEnvironment().getProperty("hapi.fhir.cr.enabled");
+ return Boolean.parseBoolean(property);
+ }
}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrProperties.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrProperties.java
new file mode 100644
index 0000000..967dea9
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/CrProperties.java
@@ -0,0 +1,264 @@
+package ca.uhn.fhir.jpa.starter.cr;
+
+import org.cqframework.cql.cql2elm.CqlCompilerException;
+import org.cqframework.cql.cql2elm.CqlTranslator;
+import org.cqframework.cql.cql2elm.LibraryBuilder;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties(prefix = "hapi.fhir.cr")
+public class CrProperties {
+ private Boolean enabled;
+ // cql settings
+ private Boolean cql_use_embedded_libraries = true;
+ private Boolean cql_runtime_debug_logging_enabled = false;
+ private Boolean cql_runtime_enable_validation = false;
+ private Boolean cql_runtime_enable_expression_caching = false;
+ private Boolean cql_compiler_validate_units = true;
+ private Boolean cql_compiler_verify_only = false;
+ private String cql_compiler_compatibility_level = "1.5";
+ private CqlCompilerException.ErrorSeverity cql_compiler_error_level = CqlCompilerException.ErrorSeverity.Info;
+ private LibraryBuilder.SignatureLevel cql_compiler_signature_level = LibraryBuilder.SignatureLevel.All;
+ private Boolean cql_compiler_analyze_data_requirements = false;
+ private Boolean cql_compiler_collapse_data_requirements = false;
+ private CqlTranslator.Format cql_compiler_translator_format = CqlTranslator.Format.JSON;
+ private Boolean cql_compiler_enable_date_range_optimization = false;
+ private Boolean cql_compiler_enable_annotations = false;
+ private Boolean cql_compiler_enable_locators = false;
+ private Boolean cql_compiler_enable_results_type = false;
+ private Boolean cql_compiler_enable_detailed_errors = false;
+ private Boolean cql_compiler_disable_list_traversal = false;
+ private Boolean cql_compiler_disable_list_demotion = false;
+ private Boolean cql_compiler_disable_list_promotion = false;
+ private Boolean cql_compiler_enable_interval_demotion = false;
+ private Boolean cql_compiler_enable_interval_promotion = false;
+ private Boolean cql_compiler_disable_method_invocation = false;
+ private Boolean cql_compiler_require_from_keyword = false;
+ private Boolean cql_compiler_disable_default_model_info_load = false;
+ // Care-gaps Settings
+ private String caregaps_reporter = "default";
+ private String caregaps_section_author = "default";
+
+ public Boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(Boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public boolean isCqlUseEmbeddedLibraries() {
+ return cql_use_embedded_libraries;
+ }
+
+ public void setCqlUseEmbeddedLibraries(boolean cql_use_embedded_libraries) {
+ this.cql_use_embedded_libraries = cql_use_embedded_libraries;
+ }
+
+ public boolean isCqlRuntimeDebugLoggingEnabled() {
+ return cql_runtime_debug_logging_enabled;
+ }
+
+ public void setCqlRuntimeDebugLoggingEnabled(boolean cqlRuntimeDebugLoggingEnabled) {
+ this.cql_runtime_debug_logging_enabled = cqlRuntimeDebugLoggingEnabled;
+ }
+
+ public boolean isCqlCompilerValidateUnits() {
+ return cql_compiler_validate_units;
+ }
+
+ public void setCqlCompilerValidateUnits(boolean cqlCompilerValidateUnits) {
+ this.cql_compiler_validate_units = cqlCompilerValidateUnits;
+ }
+
+ public boolean isCqlCompilerVerifyOnly() {
+ return cql_compiler_verify_only;
+ }
+
+ public void setCqlCompilerVerifyOnly(boolean cqlCompilerVerifyOnly) {
+ this.cql_compiler_verify_only = cqlCompilerVerifyOnly;
+ }
+
+ public String getCqlCompilerCompatibilityLevel() {
+ return cql_compiler_compatibility_level;
+ }
+
+ public void setCqlCompilerCompatibilityLevel(String cqlCompilerCompatibilityLevel) {
+ this.cql_compiler_compatibility_level = cqlCompilerCompatibilityLevel;
+ }
+
+ public CqlCompilerException.ErrorSeverity getCqlCompilerErrorSeverityLevel() {
+ return cql_compiler_error_level;
+ }
+
+ public void setCqlCompilerErrorSeverityLevel(CqlCompilerException.ErrorSeverity cqlCompilerErrorSeverityLevel) {
+ this.cql_compiler_error_level = cqlCompilerErrorSeverityLevel;
+ }
+
+ public LibraryBuilder.SignatureLevel getCqlCompilerSignatureLevel() {
+ return cql_compiler_signature_level;
+ }
+
+ public void setCqlCompilerSignatureLevel(LibraryBuilder.SignatureLevel cqlCompilerSignatureLevel) {
+ this.cql_compiler_signature_level = cqlCompilerSignatureLevel;
+ }
+
+ public boolean isCqlCompilerAnalyzeDataRequirements() {
+ return cql_compiler_analyze_data_requirements;
+ }
+
+ public void setCqlCompilerAnalyzeDataRequirements(boolean cqlCompilerAnalyzeDataRequirements) {
+ this.cql_compiler_analyze_data_requirements = cqlCompilerAnalyzeDataRequirements;
+ }
+
+ public boolean isCqlCompilerCollapseDataRequirements() {
+ return cql_compiler_collapse_data_requirements;
+ }
+
+ public void setCqlCompilerCollapseDataRequirements(boolean cqlCompilerCollapseDataRequirements) {
+ this.cql_compiler_collapse_data_requirements = cqlCompilerCollapseDataRequirements;
+ }
+
+ public boolean isEnableDateRangeOptimization() {
+ return cql_compiler_enable_date_range_optimization;
+ }
+
+ public void setEnableDateRangeOptimization(boolean enableDateRangeOptimization) {
+ this.cql_compiler_enable_date_range_optimization = enableDateRangeOptimization;
+ }
+
+ public boolean isEnableAnnotations() {
+ return cql_compiler_enable_annotations;
+ }
+
+ public void setEnableAnnotations(boolean enableAnnotations) {
+ this.cql_compiler_enable_annotations = enableAnnotations;
+ }
+
+ public boolean isEnableLocators() {
+ return cql_compiler_enable_locators;
+ }
+
+ public void setEnableLocators(boolean enableLocators) {
+ this.cql_compiler_enable_locators = enableLocators;
+ }
+
+ public boolean isEnableResultsType() {
+ return cql_compiler_enable_results_type;
+ }
+
+ public void setEnableResultsType(boolean enableResultsType) {
+ this.cql_compiler_enable_results_type = enableResultsType;
+ }
+
+ public boolean isEnableDetailedErrors() {
+ return cql_compiler_enable_detailed_errors;
+ }
+
+ public void setEnableDetailedErrors(boolean enableDetailedErrors) {
+ this.cql_compiler_enable_detailed_errors = enableDetailedErrors;
+ }
+
+ public boolean isDisableListTraversal() {
+ return cql_compiler_disable_list_traversal;
+ }
+
+ public void setDisableListTraversal(boolean disableListTraversal) {
+ this.cql_compiler_disable_list_traversal = disableListTraversal;
+ }
+
+ public boolean isDisableListDemotion() {
+ return cql_compiler_disable_list_demotion;
+ }
+
+ public void setDisableListDemotion(boolean disableListDemotion) {
+ this.cql_compiler_disable_list_demotion = disableListDemotion;
+ }
+
+ public boolean isDisableListPromotion() {
+ return cql_compiler_disable_list_promotion;
+ }
+
+ public void setDisableListPromotion(boolean disableListPromotion) {
+ this.cql_compiler_disable_list_promotion = disableListPromotion;
+ }
+
+ public boolean isEnableIntervalPromotion() {
+ return cql_compiler_enable_interval_promotion;
+ }
+
+ public void setEnableIntervalPromotion(boolean enableIntervalPromotion) {
+ this.cql_compiler_enable_interval_promotion = enableIntervalPromotion;
+ }
+
+ public boolean isEnableIntervalDemotion() {
+ return cql_compiler_enable_interval_demotion;
+ }
+
+ public void setEnableIntervalDemotion(boolean enableIntervalDemotion) {
+ this.cql_compiler_enable_interval_demotion = enableIntervalDemotion;
+ }
+
+ public boolean isDisableMethodInvocation() {
+ return cql_compiler_disable_method_invocation;
+ }
+
+ public void setDisableMethodInvocation(boolean disableMethodInvocation) {
+ this.cql_compiler_disable_method_invocation = disableMethodInvocation;
+ }
+
+ public boolean isRequireFromKeyword() {
+ return cql_compiler_require_from_keyword;
+ }
+
+ public void setRequireFromKeyword(boolean requireFromKeyword) {
+ this.cql_compiler_require_from_keyword = requireFromKeyword;
+ }
+
+ public boolean isDisableDefaultModelInfoLoad() {
+ return cql_compiler_disable_default_model_info_load;
+ }
+
+ public void setDisableDefaultModelInfoLoad(boolean disableDefaultModelInfoLoad) {
+ this.cql_compiler_disable_default_model_info_load = disableDefaultModelInfoLoad;
+ }
+
+ public boolean isCqlRuntimeEnableExpressionCaching() {
+ return cql_runtime_enable_expression_caching;
+ }
+
+ public void setCqlRuntimeEnableExpressionCaching(boolean cqlRuntimeEnableExpressionCaching) {
+ this.cql_runtime_enable_expression_caching = cqlRuntimeEnableExpressionCaching;
+ }
+
+ public boolean isCqlRuntimeEnableValidation() {
+ return cql_runtime_enable_validation;
+ }
+
+ public void setCqlRuntimeEnableValidation(boolean cqlRuntimeEnableValidation) {
+ this.cql_runtime_enable_validation = cqlRuntimeEnableValidation;
+ }
+
+ public CqlTranslator.Format getCqlTranslatorFormat() {
+ return cql_compiler_translator_format;
+ }
+
+ public void setCqlTranslatorFormat(CqlTranslator.Format cqlTranslatorFormat) {
+ this.cql_compiler_translator_format = cqlTranslatorFormat;
+ }
+
+ public String getCareGapsReporter() {
+ return caregaps_reporter;
+ }
+
+ public String getCareGapsSectionAuthor() {
+ return caregaps_section_author;
+ }
+
+ public void setCareGapsSectionAuthor(String theCareGapsSectionAuthor) {
+ this.caregaps_section_author = theCareGapsSectionAuthor;
+ }
+
+ public void setCareGapsReporter(String theCareGapsReporter) {
+ this.caregaps_reporter = theCareGapsReporter;
+ }
+}
diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cr/PostInitProviderRegisterer.java b/src/main/java/ca/uhn/fhir/jpa/starter/cr/PostInitProviderRegisterer.java
new file mode 100644
index 0000000..a82c876
--- /dev/null
+++ b/src/main/java/ca/uhn/fhir/jpa/starter/cr/PostInitProviderRegisterer.java
@@ -0,0 +1,47 @@
+package ca.uhn.fhir.jpa.starter.cr;
+
+import ca.uhn.fhir.rest.server.RestfulServer;
+import ca.uhn.fhir.rest.server.provider.IResourceProviderFactoryObserver;
+import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
+
+import java.util.function.Supplier;
+
+public class PostInitProviderRegisterer {
+ public PostInitProviderRegisterer(RestfulServer restfulServer, ResourceProviderFactory resourceProviderFactory) {
+ resourceProviderFactory.attach(new Observer(restfulServer));
+ }
+
+ private class Observer implements IResourceProviderFactoryObserver {
+ private RestfulServer restfulServer;
+
+ public Observer(RestfulServer restfulServer) {
+ this.restfulServer = restfulServer;
+ }
+
+ public void update(Supplier