Feature/cds config (#857)
* Added MCP support using SSE on http://localhost:8080/sse * Reverted change that IntelliJ complains about * Pre-rework * Cleaned up the code a fair bit * Renamed * Renamed * Running spotless * Reuse FhirContext in result serialization to make MCP server work with R5 * Added support for transactions * PoC tool for CDS Hooks * some cleanup * Upgrade of model protocol * Added comments * Removed field injection ... CDS to be changed to AutoConfig eventually * Adjusted to new builder pattern * Update src/main/java/ca/uhn/fhir/rest/server/MCPBridge.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * A bit of restructuring * More rework * Removing (suspected unnecessary) formatting * Add more example doc * Added a smoke- / passthrough-test * Applied spotless * Update src/main/java/ca/uhn/fhir/jpa/starter/mcp/RequestBuilder.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/jpa/starter/mcp/RequestBuilder.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/jpa/starter/mcp/ToolFactory.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/rest/server/McpCdsBridge.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/main/java/ca/uhn/fhir/rest/server/McpCdsBridge.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Formatting * Added some documentation * spotless cares about MD? * Reverting back to default values * minor refinements * Fixed CDS hooks configuration * Fixed some wirings * Readded missing elements * getting closer to get test running again ... * applying review * Readded exclude * Bumped spring-ai deps * added agents file * Updated according to review --------- Co-authored-by: Ádám Z. Kövér <adamzkover@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
d29b9f80af
commit
d76662c9e9
@@ -1,7 +1,9 @@
|
||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cdshooks")
|
||||
public class CdsHooksProperties {
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||
|
||||
import ca.uhn.fhir.jpa.starter.AppProperties;
|
||||
import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
|
||||
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.CdsServiceResponseJson;
|
||||
@@ -43,9 +42,6 @@ public class CdsHooksServlet extends HttpServlet {
|
||||
@Autowired
|
||||
ICdsServiceRegistry cdsServiceRegistry;
|
||||
|
||||
@Autowired
|
||||
RestfulServer restfulServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CDS_HOOKS_OBJECT_MAPPER_FACTORY)
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||
|
||||
import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
||||
import ca.uhn.fhir.jpa.starter.cr.CqlRuntimeProperties;
|
||||
|
||||
public class ProviderConfiguration {
|
||||
private final String clientIdHeaderName;
|
||||
@@ -11,8 +11,8 @@ public class ProviderConfiguration {
|
||||
this.clientIdHeaderName = clientIdHeaderName;
|
||||
}
|
||||
|
||||
public ProviderConfiguration(CdsHooksProperties cdsProperties, CrProperties crProperties) {
|
||||
this(crProperties.getCql().getRuntime().isDebugLoggingEnabled(), cdsProperties.getClientIdHeaderName());
|
||||
public ProviderConfiguration(CdsHooksProperties cdsProperties, CqlRuntimeProperties cqlRuntimeProperties) {
|
||||
this(cqlRuntimeProperties.isDebugLoggingEnabled(), cdsProperties.getClientIdHeaderName());
|
||||
}
|
||||
|
||||
public String getClientIdHeaderName() {
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.jpa.starter.cr.CrCommonConfig;
|
||||
import ca.uhn.fhir.jpa.starter.cr.CrConfigCondition;
|
||||
import ca.uhn.fhir.jpa.starter.cr.CrProperties;
|
||||
import ca.uhn.fhir.jpa.starter.cr.*;
|
||||
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 org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrServiceRegistry;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrSettings;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.ICdsCrServiceRegistry;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.discovery.CdsCrDiscoveryServiceRegistry;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.discovery.ICdsCrDiscoveryServiceRegistry;
|
||||
import org.opencds.cqf.fhir.cr.hapi.config.CrCdsHooksConfig;
|
||||
import org.opencds.cqf.fhir.cr.hapi.config.RepositoryConfig;
|
||||
import org.opencds.cqf.fhir.cr.hapi.config.test.TestCdsHooksConfig;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -24,30 +17,9 @@ import org.springframework.context.annotation.Import;
|
||||
|
||||
@Configuration
|
||||
@Conditional({CdsHooksConfigCondition.class, CrConfigCondition.class})
|
||||
@Import({RepositoryConfig.class, TestCdsHooksConfig.class, CrCdsHooksConfig.class, CrCommonConfig.class})
|
||||
@Import({RepositoryConfig.class, CrCdsHooksConfig.class, CrCommonConfig.class, CdsHooksConfig.class})
|
||||
public class StarterCdsHooksConfig {
|
||||
|
||||
@Bean
|
||||
public ICdsCrDiscoveryServiceRegistry cdsCrDiscoveryServiceRegistry() {
|
||||
CdsCrDiscoveryServiceRegistry registry = new CdsCrDiscoveryServiceRegistry();
|
||||
registry.unregister(FhirVersionEnum.R4);
|
||||
registry.register(FhirVersionEnum.R4, UpdatedCrDiscoveryService.class);
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ICdsCrServiceRegistry cdsCrServiceRegistry() {
|
||||
CdsCrServiceRegistry registry = new CdsCrServiceRegistry();
|
||||
registry.unregister(FhirVersionEnum.R4);
|
||||
registry.register(FhirVersionEnum.R4, UpdatedCdsCrService.class);
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CdsHooksProperties cdsHooksProperties() {
|
||||
return new CdsHooksProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CdsCrSettings cdsCrSettings(CdsHooksProperties cdsHooksProperties) {
|
||||
CdsCrSettings settings = CdsCrSettings.getDefault();
|
||||
@@ -67,8 +39,9 @@ public class StarterCdsHooksConfig {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProviderConfiguration providerConfiguration(CdsHooksProperties cdsProperties, CrProperties crProperties) {
|
||||
return new ProviderConfiguration(cdsProperties, crProperties);
|
||||
public ProviderConfiguration providerConfiguration(
|
||||
CdsHooksProperties cdsProperties, CqlProperties cqlProperties, CqlRuntimeProperties cqlRuntimeProperties) {
|
||||
return new ProviderConfiguration(cdsProperties, cqlRuntimeProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.repository.IRepository;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.cdshooks.CdsServiceRequestJson;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.CdsCrService;
|
||||
import org.opencds.cqf.fhir.utility.adapter.IAdapterFactory;
|
||||
|
||||
import static org.opencds.cqf.fhir.utility.Constants.APPLY_PARAMETER_DATA;
|
||||
|
||||
public class UpdatedCdsCrService extends CdsCrService {
|
||||
private final IAdapterFactory adapterFactory;
|
||||
|
||||
public UpdatedCdsCrService(RequestDetails theRequestDetails, IRepository theRepository) {
|
||||
super(theRequestDetails, theRepository);
|
||||
adapterFactory = IAdapterFactory.forFhirContext(theRepository.fhirContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseParameters encodeParams(CdsServiceRequestJson theJson) {
|
||||
var parameters = adapterFactory.createParameters(super.encodeParams(theJson));
|
||||
if (parameters.hasParameter(APPLY_PARAMETER_DATA)) {
|
||||
parameters.addParameter(
|
||||
"useServerData",
|
||||
booleanTypeForVersion(parameters.fhirContext().getVersion().getVersion(), false));
|
||||
}
|
||||
return (IBaseParameters) parameters.get();
|
||||
}
|
||||
|
||||
private IPrimitiveType<Boolean> booleanTypeForVersion(FhirVersionEnum fhirVersion, boolean value) {
|
||||
return switch (fhirVersion) {
|
||||
case DSTU2 -> new org.hl7.fhir.dstu2.model.BooleanType(value);
|
||||
case DSTU3 -> new org.hl7.fhir.dstu3.model.BooleanType(value);
|
||||
case R4 -> new org.hl7.fhir.r4.model.BooleanType(value);
|
||||
case R5 -> new org.hl7.fhir.r5.model.BooleanType(value);
|
||||
default -> throw new IllegalArgumentException("unknown or unsupported FHIR version");
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package ca.uhn.fhir.jpa.starter.cdshooks;
|
||||
|
||||
import ca.uhn.fhir.repository.IRepository;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.opencds.cqf.fhir.cr.hapi.cdshooks.discovery.CrDiscoveryService;
|
||||
|
||||
public class UpdatedCrDiscoveryService extends CrDiscoveryService {
|
||||
public UpdatedCrDiscoveryService(IIdType thePlanDefinitionId, IRepository theRepository) {
|
||||
super(thePlanDefinitionId, theRepository);
|
||||
maxUriLength = 6000;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
package ca.uhn.fhir.jpa.starter.cr;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr.caregaps")
|
||||
public class CareGapsProperties {
|
||||
private String reporter = "default";
|
||||
private String section_author = "default";
|
||||
|
||||
@@ -3,7 +3,11 @@ 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;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.compiler")
|
||||
public class CqlCompilerProperties {
|
||||
private Boolean validate_units = true;
|
||||
private Boolean verify_only = false;
|
||||
|
||||
46
src/main/java/ca/uhn/fhir/jpa/starter/cr/CqlData.java
Normal file
46
src/main/java/ca/uhn/fhir/jpa/starter/cr/CqlData.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package ca.uhn.fhir.jpa.starter.cr;
|
||||
|
||||
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.data")
|
||||
public class CqlData {
|
||||
private RetrieveSettings.SEARCH_FILTER_MODE searchParameterMode = RetrieveSettings.SEARCH_FILTER_MODE.AUTO;
|
||||
private RetrieveSettings.PROFILE_MODE profileMode = RetrieveSettings.PROFILE_MODE.OFF;
|
||||
private RetrieveSettings.TERMINOLOGY_FILTER_MODE terminologyParameterMode =
|
||||
RetrieveSettings.TERMINOLOGY_FILTER_MODE.AUTO;
|
||||
|
||||
public RetrieveSettings.SEARCH_FILTER_MODE getSearchParameterMode() {
|
||||
return searchParameterMode;
|
||||
}
|
||||
|
||||
public void setSearchParameterMode(RetrieveSettings.SEARCH_FILTER_MODE searchParameterMode) {
|
||||
this.searchParameterMode = searchParameterMode;
|
||||
}
|
||||
|
||||
public RetrieveSettings.PROFILE_MODE getProfileMode() {
|
||||
return profileMode;
|
||||
}
|
||||
|
||||
public void setProfileMode(RetrieveSettings.PROFILE_MODE profileMode) {
|
||||
this.profileMode = profileMode;
|
||||
}
|
||||
|
||||
public RetrieveSettings.TERMINOLOGY_FILTER_MODE getTerminologyParameterMode() {
|
||||
return terminologyParameterMode;
|
||||
}
|
||||
|
||||
public void setTerminologyParameterMode(RetrieveSettings.TERMINOLOGY_FILTER_MODE terminologyParameterMode) {
|
||||
this.terminologyParameterMode = terminologyParameterMode;
|
||||
}
|
||||
|
||||
public RetrieveSettings getRetrieveSettings() {
|
||||
var retrieveSettings = new RetrieveSettings();
|
||||
retrieveSettings.setSearchParameterMode(searchParameterMode);
|
||||
retrieveSettings.setProfileMode(profileMode);
|
||||
retrieveSettings.setTerminologyParameterMode(terminologyParameterMode);
|
||||
return retrieveSettings;
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,18 @@ package ca.uhn.fhir.jpa.starter.cr;
|
||||
|
||||
import org.opencds.cqf.fhir.cql.engine.retrieve.RetrieveSettings;
|
||||
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql")
|
||||
public class CqlProperties {
|
||||
|
||||
private Boolean use_embedded_libraries = true;
|
||||
private CqlCompilerProperties compiler = new CqlCompilerProperties();
|
||||
private CqlRuntimeProperties runtime = new CqlRuntimeProperties();
|
||||
private TerminologySettings terminology = new TerminologySettings();
|
||||
private RetrieveSettings data = new RetrieveSettings();
|
||||
private CqlData data = new CqlData();
|
||||
|
||||
public Boolean getUse_embedded_libraries() {
|
||||
return use_embedded_libraries;
|
||||
@@ -43,11 +47,15 @@ public class CqlProperties {
|
||||
this.terminology = terminology;
|
||||
}
|
||||
|
||||
public RetrieveSettings getData() {
|
||||
public CqlData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(RetrieveSettings data) {
|
||||
public void setData(CqlData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public RetrieveSettings getRetrieveSettings() {
|
||||
return data.getRetrieveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package ca.uhn.fhir.jpa.starter.cr;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.runtime")
|
||||
public class CqlRuntimeProperties {
|
||||
|
||||
private Boolean debug_logging_enabled = false;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package ca.uhn.fhir.jpa.starter.cr;
|
||||
|
||||
import org.opencds.cqf.fhir.cql.engine.terminology.TerminologySettings;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr.cql.terminology")
|
||||
@Configuration
|
||||
public class CqlTerminologyProperties {
|
||||
|
||||
private TerminologySettings.VALUESET_EXPANSION_MODE valuesetExpansionMode =
|
||||
TerminologySettings.VALUESET_EXPANSION_MODE.AUTO;
|
||||
private TerminologySettings.VALUESET_MEMBERSHIP_MODE valuesetMembershipMode =
|
||||
TerminologySettings.VALUESET_MEMBERSHIP_MODE.AUTO;
|
||||
private TerminologySettings.CODE_LOOKUP_MODE codeLookupMode = TerminologySettings.CODE_LOOKUP_MODE.AUTO;
|
||||
private TerminologySettings.VALUESET_PRE_EXPANSION_MODE valueSetPreExpansionMode =
|
||||
TerminologySettings.VALUESET_PRE_EXPANSION_MODE.USE_IF_PRESENT;
|
||||
|
||||
public void setValuesetExpansionMode(TerminologySettings.VALUESET_EXPANSION_MODE valuesetExpansionMode) {
|
||||
this.valuesetExpansionMode = valuesetExpansionMode;
|
||||
}
|
||||
|
||||
public void setValuesetMembershipMode(TerminologySettings.VALUESET_MEMBERSHIP_MODE valuesetMembershipMode) {
|
||||
this.valuesetMembershipMode = valuesetMembershipMode;
|
||||
}
|
||||
|
||||
public void setCodeLookupMode(TerminologySettings.CODE_LOOKUP_MODE codeLookupMode) {
|
||||
this.codeLookupMode = codeLookupMode;
|
||||
}
|
||||
|
||||
public void setValueSetPreExpansionMode(TerminologySettings.VALUESET_PRE_EXPANSION_MODE valueSetPreExpansionMode) {
|
||||
this.valueSetPreExpansionMode = valueSetPreExpansionMode;
|
||||
}
|
||||
|
||||
public TerminologySettings getTerminologySettings() {
|
||||
TerminologySettings settings = new TerminologySettings();
|
||||
settings.setValuesetExpansionMode(valuesetExpansionMode);
|
||||
settings.setValuesetMembershipMode(valuesetMembershipMode);
|
||||
settings.setCodeLookupMode(codeLookupMode);
|
||||
settings.setValuesetPreExpansionMode(valueSetPreExpansionMode);
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import org.opencds.cqf.fhir.cr.measure.CareGapsProperties;
|
||||
import org.opencds.cqf.fhir.cr.measure.MeasureEvaluationOptions;
|
||||
import org.opencds.cqf.fhir.utility.ValidationProfile;
|
||||
import org.opencds.cqf.fhir.utility.client.TerminologyServerClientSettings;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -43,19 +42,13 @@ import java.util.concurrent.Executors;
|
||||
public class CrCommonConfig {
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr")
|
||||
CrProperties crProperties() {
|
||||
return new CrProperties();
|
||||
RetrieveSettings retrieveSettings(CqlData cqlData) {
|
||||
return cqlData.getRetrieveSettings();
|
||||
}
|
||||
|
||||
@Bean
|
||||
RetrieveSettings retrieveSettings(CrProperties theCrProperties) {
|
||||
return theCrProperties.getCql().getData();
|
||||
}
|
||||
|
||||
@Bean
|
||||
TerminologySettings terminologySettings(CrProperties theCrProperties) {
|
||||
return theCrProperties.getCql().getTerminology();
|
||||
TerminologySettings terminologySettings(CqlTerminologyProperties theCqlTerminologyProperties) {
|
||||
return theCqlTerminologyProperties.getTerminologySettings();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -65,7 +58,8 @@ public class CrCommonConfig {
|
||||
|
||||
@Bean
|
||||
public EvaluationSettings evaluationSettings(
|
||||
CrProperties theCrProperties,
|
||||
CqlRuntimeProperties cqlRuntimeProperties,
|
||||
CqlCompilerProperties cqlCompilerProperties,
|
||||
RetrieveSettings theRetrieveSettings,
|
||||
TerminologySettings theTerminologySettings,
|
||||
Map<VersionedIdentifier, CompiledLibrary> theGlobalLibraryCache,
|
||||
@@ -76,7 +70,7 @@ public class CrCommonConfig {
|
||||
|
||||
var cqlEngineOptions = cqlOptions.getCqlEngineOptions();
|
||||
Set<CqlEngine.Options> options = EnumSet.noneOf(CqlEngine.Options.class);
|
||||
var cqlRuntimeProperties = theCrProperties.getCql().getRuntime();
|
||||
|
||||
if (cqlRuntimeProperties.isEnableExpressionCaching()) {
|
||||
options.add(CqlEngine.Options.EnableExpressionCaching);
|
||||
}
|
||||
@@ -91,8 +85,6 @@ public class CrCommonConfig {
|
||||
|
||||
var cqlCompilerOptions = new CqlCompilerOptions();
|
||||
|
||||
var cqlCompilerProperties = theCrProperties.getCql().getCompiler();
|
||||
|
||||
if (cqlCompilerProperties.isEnableDateRangeOptimization()) {
|
||||
cqlCompilerOptions.setOptions(CqlCompilerOptions.Options.EnableDateRangeOptimization);
|
||||
}
|
||||
@@ -159,8 +151,8 @@ public class CrCommonConfig {
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
|
||||
@Bean(name = "measure.CareGapsProperties")
|
||||
org.opencds.cqf.fhir.cr.measure.CareGapsProperties careGapsProperties(CrProperties theCrProperties) {
|
||||
var careGapsProperties = new CareGapsProperties();
|
||||
// This check for the resource type really should be happening down in CR where the setting is actually used but
|
||||
// that will have to wait for a future CR release
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package ca.uhn.fhir.jpa.starter.cr;
|
||||
|
||||
import org.opencds.cqf.fhir.utility.client.TerminologyServerClientSettings;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "hapi.fhir.cr")
|
||||
public class CrProperties {
|
||||
private Boolean enabled;
|
||||
|
||||
private CareGapsProperties careGaps = new CareGapsProperties();
|
||||
private CqlProperties cql = new CqlProperties();
|
||||
|
||||
private TerminologyServerClientSettings terminologyServerClientSettings = new TerminologyServerClientSettings();
|
||||
|
||||
public Boolean getEnabled() {
|
||||
|
||||
@@ -8,6 +8,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.hapi.fhir.cdshooks.api.ICdsServiceRegistry;
|
||||
import ca.uhn.hapi.fhir.cdshooks.module.CdsHooksObjectMapperFactory;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
|
||||
import io.modelcontextprotocol.server.McpServerFeatures;
|
||||
import io.modelcontextprotocol.server.transport.HttpServletStreamableServerTransportProvider;
|
||||
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerStreamableHttpProperties;
|
||||
@@ -66,7 +67,7 @@ public class McpServerConfig {
|
||||
return HttpServletStreamableServerTransportProvider.builder()
|
||||
.disallowDelete(false)
|
||||
.mcpEndpoint(properties.getMcpEndpoint())
|
||||
.objectMapper(new ObjectMapper())
|
||||
.jsonMapper(new JacksonMcpJsonMapper(new ObjectMapper()))
|
||||
// .contextExtractor((serverRequest, context) -> context)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
#Uncomment the "servlet" and "context-path" lines below to make the fhir endpoint available at /example/path/fhir instead of the default value of /fhir
|
||||
# -------------------------------------------------------------------------------------
|
||||
# Server & Spring Boot
|
||||
# -------------------------------------------------------------------------------------
|
||||
server:
|
||||
# servlet:
|
||||
# context-path: /example/path
|
||||
# Uncomment to serve FHIR under a non-default context path (e.g., /example/path/fhir)
|
||||
# servlet:
|
||||
# context-path: /example/path
|
||||
port: 8080
|
||||
tomcat:
|
||||
# allow | as a separator in the URL
|
||||
# allow | as a separator in URLs
|
||||
relaxed-query-chars: "|"
|
||||
#Adds the option to go to e.g. http://localhost:8080/actuator/health for seeing the running configuration
|
||||
#see https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints
|
||||
|
||||
management:
|
||||
health:
|
||||
elasticsearch:
|
||||
enabled: false
|
||||
#The following configuration will enable the actuator endpoints at /actuator/health, /actuator/info, /actuator/prometheus, /actuator/metrics. For security purposes, only /actuator/health is enabled by default.
|
||||
# Actuator endpoints: only /actuator/health exposed by default
|
||||
endpoints:
|
||||
enabled-by-default: false
|
||||
web:
|
||||
exposure:
|
||||
# expose only health (default) — change to [health,info,prometheus,metrics] if you want them reachable
|
||||
include: health
|
||||
include: "health" # or "info,health,prometheus,metrics" or "*" for all
|
||||
endpoint:
|
||||
info:
|
||||
enabled: true
|
||||
@@ -30,40 +28,42 @@ management:
|
||||
enabled: true
|
||||
group:
|
||||
liveness:
|
||||
include:
|
||||
- livenessState
|
||||
- readinessState
|
||||
include: [ "livenessState", "readinessState" ]
|
||||
prometheus:
|
||||
enabled: true
|
||||
prometheus:
|
||||
metrics:
|
||||
export:
|
||||
enabled: true
|
||||
spring:
|
||||
ai:
|
||||
# Run e.g. `npx @modelcontextprotocol/inspector` and connect to http://localhost:8080/mcp/message using Streamable HTTP
|
||||
|
||||
# Add the following to the MCP server settings file in e.g. cursor or claude (Desktop applications) for local debugging:
|
||||
# cursor:
|
||||
# {
|
||||
# "mcpServers": {
|
||||
# "hapi": {
|
||||
# "url": "http://localhost:8080/mcp/message"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# or claude:
|
||||
# {
|
||||
# "mcpServers": {
|
||||
# "hapi": {
|
||||
# "command": "npx",
|
||||
# "args": [
|
||||
# "mcp-remote@latest",
|
||||
# "http://localhost:8080/mcp/message"
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
spring:
|
||||
# -------------------------------------------------------------------------------
|
||||
# A. Spring AI — Model Context Protocol (MCP)
|
||||
# -------------------------------------------------------------------------------
|
||||
ai:
|
||||
# Run e.g. `npx @modelcontextprotocol/inspector` and connect to http://localhost:8080/mcp/messages using Streamable HTTP
|
||||
|
||||
# Add the following to the MCP server settings file in e.g. cursor or claude (Desktop applications) for local debugging:
|
||||
# cursor:
|
||||
# {
|
||||
# "mcpServers": {
|
||||
# "hapi": {
|
||||
# "url": "http://localhost:8080/mcp/messages"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# or claude:
|
||||
# {
|
||||
# "mcpServers": {
|
||||
# "hapi": {
|
||||
# "command": "npx",
|
||||
# "args": [
|
||||
# "mcp-remote@latest",
|
||||
# "http://localhost:8080/mcp/messages"
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
mcp:
|
||||
server:
|
||||
@@ -75,48 +75,43 @@ spring:
|
||||
mcp-endpoint: /mcp/messages
|
||||
|
||||
|
||||
#schema:
|
||||
# fhir-enabled: true
|
||||
# fhir:
|
||||
# base-url: http://localhost:8080/fhir
|
||||
|
||||
#query:
|
||||
# prompt:
|
||||
# template: |
|
||||
# You are a FHIR assistant. Translate the following question into a valid FHIR RESTful API query:
|
||||
# "{{query}}"
|
||||
# Use the provided FHIR schema:
|
||||
# {{schema}}
|
||||
#base-url: /api/v1
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# B. Core Spring
|
||||
# -------------------------------------------------------------------------------
|
||||
main:
|
||||
allow-bean-definition-overriding: false
|
||||
allow-circular-references: true
|
||||
|
||||
autoconfigure:
|
||||
# This exclude is only needed for setups not using Elasticsearch where the elasticsearch sniff is not needed.
|
||||
exclude: org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
|
||||
main:
|
||||
allow-bean-definition-overriding: false
|
||||
allow-circular-references: true
|
||||
|
||||
flyway:
|
||||
enabled: false
|
||||
baseline-on-migrate: true
|
||||
fail-on-missing-locations: false
|
||||
|
||||
datasource:
|
||||
#url: 'jdbc:h2:file:./target/database/h2'
|
||||
# url: "jdbc:h2:file:./target/database/h2"
|
||||
url: jdbc:h2:mem:test_mem
|
||||
username: sa
|
||||
password: null
|
||||
driver-class-name: org.h2.Driver
|
||||
|
||||
# database connection pool size
|
||||
# max-active: 15 # (ignored with HikariCP; use hikari.maximum-pool-size)
|
||||
hikari:
|
||||
maximum-pool-size: 10
|
||||
# elasticsearch:
|
||||
# uris: http://localhost:9200
|
||||
# username: elastic
|
||||
# password: changeme
|
||||
|
||||
jpa:
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: false
|
||||
show_sql: false
|
||||
# Hibernate dialect is auto-detected except for H2/Postgres.
|
||||
# If using H2: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
# If using Postgres: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
||||
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
|
||||
# --- Optional Hibernate DDL & tuning (commented out from source) ---
|
||||
hbm2ddl:
|
||||
auto: update
|
||||
jdbc:
|
||||
@@ -126,43 +121,73 @@ spring:
|
||||
use_second_level_cache: false
|
||||
use_structured_entries: false
|
||||
use_minimal_puts: false
|
||||
format_sql: false
|
||||
show_sql: false
|
||||
#If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
#If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
||||
#dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect
|
||||
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
|
||||
# --- Hibernate Search (Lucene/Elasticsearch) ---
|
||||
search:
|
||||
enabled: true
|
||||
schema_management:
|
||||
strategy: create
|
||||
### lucene parameters
|
||||
backend:
|
||||
type: lucene
|
||||
directory:
|
||||
type: local-filesystem
|
||||
root: target/lucenefiles
|
||||
analysis:
|
||||
configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
||||
|
||||
### elastic parameters ===> see also elasticsearch section below <===
|
||||
# backend:
|
||||
# type: elasticsearch
|
||||
# discovery: true
|
||||
# analysis:
|
||||
# configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
||||
# hosts: localhost:9200
|
||||
# protocol: http
|
||||
# username: elastic
|
||||
# password: changeme
|
||||
# refresh_after_write: true
|
||||
enabled: false
|
||||
# Lucene backend (default example)
|
||||
# backend:
|
||||
# type: lucene
|
||||
# analysis:
|
||||
# configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
||||
# directory:
|
||||
# type: local-filesystem
|
||||
# root: target/lucenefiles
|
||||
# lucene_version: lucene_current
|
||||
# Elasticsearch backend (alternative) — see also hapi.fhir.elasticsearch section in docs
|
||||
# backend:
|
||||
# type: elasticsearch
|
||||
# analysis:
|
||||
# configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
||||
|
||||
# -------------------------------------------------------------------------------------
|
||||
# HAPI FHIR — grouped by domain
|
||||
# -------------------------------------------------------------------------------------
|
||||
hapi:
|
||||
fhir:
|
||||
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
||||
### Flag is false by default, can be passed as command line argument to override.
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# A. Core Server & API
|
||||
# -------------------------------------------------------------------------------
|
||||
openapi_enabled: true # Swagger UI at /fhir/swagger-ui/index.html; API docs at /fhir/api-docs
|
||||
fhir_version: R4 # DSTU2 | DSTU3 | R4 | R5
|
||||
# use_apache_address_strategy: false
|
||||
# use_apache_address_strategy_https: false
|
||||
# custom_content_path: ./custom # folder name must be 'custom'
|
||||
# app_content_path: ./configs/app # served under /web/app
|
||||
# server_address: http://hapi.fhir.org/baseR4
|
||||
# defer_indexing_for_codesystems_of_size: 101
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# B. Implementation Guides (IG) & Package Install
|
||||
# -------------------------------------------------------------------------------
|
||||
ig_runtime_upload_enabled: false
|
||||
# validate_resource_status_for_package_upload: false # default true
|
||||
# install_transitive_ig_dependencies: true
|
||||
# implementationguides:
|
||||
# swiss:
|
||||
# name: swiss.mednet.fhir
|
||||
# version: 0.8.0
|
||||
# reloadExisting: false
|
||||
# installMode: STORE_AND_INSTALL
|
||||
# ips_1_0_0:
|
||||
# packageUrl: https://costateixeira.github.io/smart-ips-pilgrimage-fulltest/package.tgz
|
||||
# name: smart.who.int.ips-pilgrimage-test
|
||||
# version: 0.1.0
|
||||
# installMode: STORE_AND_INSTALL
|
||||
# additionalResourceFolders:
|
||||
# - example
|
||||
# - example2
|
||||
# supported_resource_types:
|
||||
# - Patient
|
||||
# - Observation
|
||||
# allowed_bundle_types: COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# C. Clinical Reasoning / CQL / Care Gaps / CDS Hooks
|
||||
# -------------------------------------------------------------------------------
|
||||
cr:
|
||||
enabled: false
|
||||
enabled: false # exposes Clinical Reasoning operation endpoints
|
||||
caregaps:
|
||||
reporter: "default"
|
||||
section_author: "default"
|
||||
@@ -174,8 +199,7 @@ hapi:
|
||||
cql:
|
||||
use_embedded_libraries: true
|
||||
compiler:
|
||||
### These are low-level compiler options.
|
||||
### They are not typically needed by most users.
|
||||
# low-level compiler options (typically not needed)
|
||||
# validate_units: true
|
||||
# verify_only: false
|
||||
# compatibility_level: "1.5"
|
||||
@@ -200,124 +224,84 @@ hapi:
|
||||
debug_logging_enabled: false
|
||||
# enable_validation: false
|
||||
# enable_expression_caching: true
|
||||
terminology:
|
||||
valueset_preexpansion_mode: REQUIRE # USE_IF_PRESENT, REQUIRE, IGNORE
|
||||
valueset_expansion_mode: PERFORM_NAIVE_EXPANSION # AUTO, USE_EXPANSION_OPERATION, PERFORM_NAIVE_EXPANSION
|
||||
valueset_membership_mode: USE_EXPANSION # AUTO, USE_VALIDATE_CODE_OPERATION, USE_EXPANSION
|
||||
code_lookup_mode: USE_VALIDATE_CODE_OPERATION # AUTO, USE_VALIDATE_CODE_OPERATION, USE_CODESYSTEM_URL
|
||||
data:
|
||||
search_parameter_mode: USE_SEARCH_PARAMETERS # AUTO, USE_SEARCH_PARAMETERS, FILTER_IN_MEMORY
|
||||
terminology_parameter_mode: FILTER_IN_MEMORY # AUTO, USE_VALUE_SET_URL, USE_INLINE_CODES, FILTER_IN_MEMORY
|
||||
profile_mode: DECLARED # ENFORCED, DECLARED, OPTIONAL, TRUST, OFF
|
||||
|
||||
terminology:
|
||||
valueset_preexpansion_mode: REQUIRE # USE_IF_PRESENT | REQUIRE | IGNORE
|
||||
valueset_expansion_mode: PERFORM_NAIVE_EXPANSION # AUTO | USE_EXPANSION_OPERATION | PERFORM_NAIVE_EXPANSION
|
||||
valueset_membership_mode: USE_EXPANSION # AUTO | USE_VALIDATE_CODE_OPERATION | USE_EXPANSION
|
||||
code_lookup_mode: USE_VALIDATE_CODE_OPERATION # AUTO | USE_VALIDATE_CODE_OPERATION | USE_CODESYSTEM_URL
|
||||
data:
|
||||
search_parameter_mode: USE_SEARCH_PARAMETERS # AUTO | USE_SEARCH_PARAMETERS | FILTER_IN_MEMORY
|
||||
terminology_parameter_mode: FILTER_IN_MEMORY # AUTO | USE_VALUE_SET_URL | USE_INLINE_CODES | FILTER_IN_MEMORY
|
||||
profile_mode: DECLARED # ENFORCED | DECLARED | OPTIONAL | TRUST | OFF
|
||||
cdshooks:
|
||||
enabled: false
|
||||
clientIdHeaderName: client_id
|
||||
|
||||
### This enables the swagger-ui at /fhir/swagger-ui/index.html as well as the /fhir/api-docs (see https://hapifhir.io/hapi-fhir/docs/server_plain/openapi.html)
|
||||
openapi_enabled: true
|
||||
### This is the FHIR version. Choose between, DSTU2, DSTU3, R4 or R5
|
||||
fhir_version: R4
|
||||
### Flag is false by default. This flag enables runtime installation of IG's.
|
||||
ig_runtime_upload_enabled: false
|
||||
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
||||
|
||||
### enable to use the ApacheProxyAddressStrategy which uses X-Forwarded-* headers
|
||||
### to determine the FHIR server address
|
||||
# use_apache_address_strategy: false
|
||||
### forces the use of the https:// protocol for the returned server address.
|
||||
### alternatively, it may be set using the X-Forwarded-Proto header.
|
||||
# use_apache_address_strategy_https: false
|
||||
### enables the server to overwrite defaults on HTML, css, etc. under the url pattern of eg. /content/custom **
|
||||
### Folder with custom content MUST be named custom. If omitted then default content applies
|
||||
#custom_content_path: ./custom
|
||||
### enables the server host custom content. If e.g. the value ./configs/app is supplied then the content
|
||||
### will be served under /web/app
|
||||
#app_content_path: ./configs/app
|
||||
### enable to set the Server URL
|
||||
# server_address: http://hapi.fhir.org/baseR4
|
||||
# defer_indexing_for_codesystems_of_size: 101
|
||||
### Flag is true by default. This flag filters resources during package installation, allowing only those resources with a valid status (e.g. active) to be installed.
|
||||
# validate_resource_status_for_package_upload: false
|
||||
# install_transitive_ig_dependencies: true
|
||||
#implementationguides:
|
||||
### example from registry (packages.fhir.org)
|
||||
# swiss:
|
||||
# name: swiss.mednet.fhir
|
||||
# version: 0.8.0
|
||||
# reloadExisting: false
|
||||
# installMode: STORE_AND_INSTALL
|
||||
# example not from registry
|
||||
# ips_1_0_0:
|
||||
# packageUrl: https://costateixeira.github.io/smart-ips-pilgrimage-fulltest/package.tgz
|
||||
# name: smart.who.int.ips-pilgrimage-test
|
||||
# version: 0.1.0
|
||||
# installMode: STORE_AND_INSTALL
|
||||
# additionalResourceFolders:
|
||||
# - example
|
||||
# - example2
|
||||
# supported_resource_types:
|
||||
# - Patient
|
||||
# - Observation
|
||||
##################################################
|
||||
# Allowed Bundle Types for persistence (defaults are: COLLECTION,DOCUMENT,MESSAGE)
|
||||
##################################################
|
||||
# allowed_bundle_types: COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET
|
||||
# allow_cascading_deletes: true
|
||||
# allow_contains_searches: true
|
||||
# allow_external_references: true
|
||||
# allow_multiple_delete: true
|
||||
# allow_override_default_search_params: true
|
||||
# auto_create_placeholder_reference_targets: false
|
||||
# mass_ingestion_mode_enabled: false
|
||||
### tells the server to automatically append the current version of the target resource to references at these paths
|
||||
# auto_version_reference_at_paths: Device.patient, Device.location, Device.parent, DeviceMetric.parent, DeviceMetric.source, Observation.device, Observation.subject
|
||||
# ips_enabled: false
|
||||
# default_encoding: JSON
|
||||
# default_pretty_print: true
|
||||
# default_page_size: 20
|
||||
# delete_enabled: true
|
||||
# delete_expunge_enabled: true
|
||||
# match_url_cache_enabled: false
|
||||
# enable_repository_validating_interceptor: true
|
||||
### Reduce the size used by search indexes by not tagging every row with the resource type and parameter name (this setting makes manual inspection of the database more difficult, but does not impact HAPI FHIR functionality in any way)
|
||||
# index_storage_optimized: false
|
||||
# enable_index_missing_fields: false
|
||||
# enable_index_of_type: true
|
||||
# enable_index_contained_resource: false
|
||||
# upliftedRefchains_enabled: true
|
||||
# resource_dbhistory_enabled: false
|
||||
### !!Extended Lucene/Elasticsearch Indexing is still a experimental feature, expect some features (e.g. _total=accurate) to not work as expected!!
|
||||
### more information here: https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html
|
||||
# -------------------------------------------------------------------------------
|
||||
# D. Search & Indexing
|
||||
# -------------------------------------------------------------------------------
|
||||
# NOTE: Extended Lucene/Elasticsearch indexing is experimental.
|
||||
# See https://hapifhir.io/hapi-fhir/docs/server_jpa/elastic.html
|
||||
advanced_lucene_indexing: false
|
||||
search_index_full_text_enabled: false
|
||||
# language_search_parameter_enabled: true
|
||||
# upliftedRefchains_enabled: true
|
||||
# index_storage_optimized: false
|
||||
# enable_index_missing_fields: false
|
||||
# enable_index_of_type: true
|
||||
# enable_index_contained_resource: false
|
||||
# store_resource_in_lucene_index_enabled: true
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# E. Bulk Operations
|
||||
# -------------------------------------------------------------------------------
|
||||
bulk_export_enabled: false
|
||||
bulk_import_enabled: false
|
||||
# language_search_parameter_enabled: true
|
||||
# enforce_referential_integrity_on_delete: false
|
||||
# This is an experimental feature, and does not fully support _total and other FHIR features.
|
||||
# enforce_referential_integrity_on_delete: false
|
||||
# enforce_referential_integrity_on_write: false
|
||||
# etag_support_enabled: true
|
||||
# expunge_enabled: true
|
||||
# client_id_strategy: ALPHANUMERIC
|
||||
# server_id_strategy: SEQUENTIAL_NUMERIC
|
||||
# fhirpath_interceptor_enabled: false
|
||||
# filter_search_enabled: true
|
||||
# graphql_enabled: true
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# F. Write / Delete / Integrity
|
||||
# -------------------------------------------------------------------------------
|
||||
# allow_cascading_deletes: true
|
||||
# allow_contains_searches: true
|
||||
# allow_external_references: true
|
||||
# allow_multiple_delete: true
|
||||
# allow_override_default_search_params: true
|
||||
# auto_create_placeholder_reference_targets: false
|
||||
# mass_ingestion_mode_enabled: false
|
||||
# auto_version_reference_at_paths: Device.patient, Device.location, Device.parent, DeviceMetric.parent, DeviceMetric.source, Observation.device, Observation.subject
|
||||
# client_id_strategy: ALPHANUMERIC
|
||||
# server_id_strategy: SEQUENTIAL_NUMERIC
|
||||
# enforce_referential_integrity_on_delete: false
|
||||
# enforce_referential_integrity_on_write: false
|
||||
# etag_support_enabled: true
|
||||
# expunge_enabled: true
|
||||
# fhirpath_interceptor_enabled: false
|
||||
# filter_search_enabled: true
|
||||
# graphql_enabled: true
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# G. Narrative & Validation
|
||||
# -------------------------------------------------------------------------------
|
||||
narrative_enabled: false
|
||||
# validation:
|
||||
# requests_enabled: true
|
||||
# responses_enabled: true
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# H. MDM (Master Data Management)
|
||||
# -------------------------------------------------------------------------------
|
||||
mdm_enabled: false
|
||||
mdm_rules_json_location: "mdm-rules.json"
|
||||
## see: https://hapifhir.io/hapi-fhir/docs/interceptors/built_in_server_interceptors.html#jpa-server-retry-on-version-conflicts
|
||||
# userRequestRetryVersionConflictsInterceptorEnabled : false
|
||||
# local_base_urls:
|
||||
# - https://hapi.fhir.org/baseR4
|
||||
# pre_expand_value_sets: true
|
||||
# enable_task_pre_expand_value_sets: true
|
||||
# pre_expand_value_sets_default_count: 1000
|
||||
# pre_expand_value_sets_max_count: 1000
|
||||
# maximum_expansion_size: 1000
|
||||
# userRequestRetryVersionConflictsInterceptorEnabled: false
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# I. Terminology / ValueSet Expansion
|
||||
# -------------------------------------------------------------------------------
|
||||
# pre_expand_value_sets: true
|
||||
# enable_task_pre_expand_value_sets: true
|
||||
# pre_expand_value_sets_default_count: 1000
|
||||
# pre_expand_value_sets_max_count: 1000
|
||||
# maximum_expansion_size: 1000
|
||||
logical_urls:
|
||||
- http://terminology.hl7.org/*
|
||||
- https://terminology.hl7.org/*
|
||||
@@ -328,38 +312,32 @@ hapi:
|
||||
- http://loinc.org/*
|
||||
- https://loinc.org/*
|
||||
|
||||
### Uncomment the following section, and any sub-properties you need in order to enable
|
||||
### partitioning support on this server.
|
||||
#partitioning:
|
||||
# allow_references_across_partitions: false
|
||||
# partitioning_include_in_search_hashes: false
|
||||
# default_partition_id: 0
|
||||
### Enable the following setting to enable Database Partitioning Mode
|
||||
### See: https://hapifhir.io/hapi-fhir/docs/server_jpa_partitioning/db_partition_mode.html
|
||||
# database_partition_mode_enabled: true
|
||||
### Partition Style: Partitioning requires a partition interceptor which helps the server
|
||||
### select which partition(s) should be accessed for a given request. You can supply your
|
||||
### own interceptor (see https://hapifhir.io/hapi-fhir/docs/server_jpa_partitioning/partitioning.html#partition-interceptors )
|
||||
### but the following setting can also be used to use a built-in form.
|
||||
### Patient ID Partitioning Mode uses the patient/subject ID to determine the partition
|
||||
# patient_id_partitioning_mode: true
|
||||
### Request tenant mode can be used for a multi-tenancy setup where the request path is
|
||||
### expected to have an additional path element, e.g. GET http://example.com/fhir/TENANT-ID/Patient/A
|
||||
# request_tenant_partitioning_mode: false
|
||||
# -------------------------------------------------------------------------------
|
||||
# J. Partitioning & Multitenancy
|
||||
# -------------------------------------------------------------------------------
|
||||
# partitioning:
|
||||
# allow_references_across_partitions: false
|
||||
# partitioning_include_in_search_hashes: false
|
||||
# default_partition_id: 0
|
||||
# database_partition_mode_enabled: true
|
||||
# patient_id_partitioning_mode: true
|
||||
# request_tenant_partitioning_mode: false
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# K. CORS
|
||||
# -------------------------------------------------------------------------------
|
||||
cors:
|
||||
allow_Credentials: true
|
||||
# These are allowed_origin patterns, see: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/cors/CorsConfiguration.html#setAllowedOriginPatterns-java.util.List-
|
||||
allowed_origin:
|
||||
- '*'
|
||||
- "*"
|
||||
|
||||
# Search coordinator thread pool sizes
|
||||
# -------------------------------------------------------------------------------
|
||||
# L. Search Orchestration
|
||||
# -------------------------------------------------------------------------------
|
||||
search-coord-core-pool-size: 20
|
||||
search-coord-max-pool-size: 100
|
||||
search-coord-queue-capacity: 200
|
||||
|
||||
# Search Prefetch Thresholds.
|
||||
|
||||
# This setting sets the number of search results to prefetch. For example, if this list
|
||||
# is set to [100, 1000, -1] then the server will initially load 100 results and not
|
||||
# attempt to load more. If the user requests subsequent page(s) of results and goes
|
||||
@@ -367,87 +345,78 @@ hapi:
|
||||
# The system will progressively work through these thresholds.
|
||||
# A threshold of -1 means to load all results. Note that if the final threshold is a
|
||||
# number other than -1, the system will never prefetch more than the given number.
|
||||
# CSV list; -1 as final value means "all"
|
||||
search_prefetch_thresholds: 13,503,2003,-1
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# M. Extensibility (custom beans / interceptors / providers)
|
||||
# -------------------------------------------------------------------------------
|
||||
# comma-separated package names, will be @ComponentScan'ed by Spring to allow for creating custom Spring beans
|
||||
#custom-bean-packages:
|
||||
|
||||
# custom-provider-classes:
|
||||
# custom-interceptor-classes:
|
||||
# custom-provider-classes:
|
||||
|
||||
# comma-separated list of fully qualified interceptor classes.
|
||||
# classes listed here will be fetched from the Spring context when combined with 'custom-bean-packages',
|
||||
# or will be instantiated via reflection using a no-arg constructor; then registered with the server
|
||||
#custom-interceptor-classes:
|
||||
|
||||
# comma-separated list of fully qualified provider classes.
|
||||
# classes listed here will be fetched from the Spring context when combined with 'custom-bean-packages',
|
||||
# or will be instantiated via reflection using a no-arg constructor; then registered with the server
|
||||
#custom-provider-classes:
|
||||
# specify what should be stored in meta.source based on StoreMetaSourceInformationEnum defaults to NONE
|
||||
# store_meta_source_information: NONE
|
||||
# Threadpool size for BATCH'ed GETs in a bundle.
|
||||
# bundle_batch_pool_size: 10
|
||||
# bundle_batch_pool_max_size: 50
|
||||
# bundle_batch_pool_size: 10
|
||||
# bundle_batch_pool_max_size: 50
|
||||
|
||||
# logger:
|
||||
# error_format: 'ERROR - ${requestVerb} ${requestUrl}'
|
||||
# format: >-
|
||||
# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}]
|
||||
# Operation[${operationType} ${operationName} ${idOrResourceName}]
|
||||
# UA[${requestHeader.user-agent}] Params[${requestParameters}]
|
||||
# ResponseEncoding[${responseEncodingNoDefault}]
|
||||
# log_exceptions: true
|
||||
# name: fhirtest.access
|
||||
# max_binary_size: 104857600
|
||||
# max_page_size: 200
|
||||
# retain_cached_searches_mins: 60
|
||||
# reuse_cached_search_results_millis: 60000
|
||||
# The remote_terminology_service block is commented out by default because it requires external terminology service endpoints.
|
||||
# Uncomment and configure the block below if you need to enable remote terminology validation or mapping.
|
||||
#remote_terminology_service:
|
||||
# all:
|
||||
# system: '*'
|
||||
# url: 'https://tx.fhir.org/r4/'
|
||||
# snomed:
|
||||
# system: 'http://snomed.info/sct'
|
||||
# url: 'https://tx.fhir.org/r4/'
|
||||
# loinc:
|
||||
# system: 'http://loinc.org'
|
||||
# url: 'https://hapi.fhir.org/baseR4/'
|
||||
tester:
|
||||
home:
|
||||
name: Local Tester
|
||||
server_address: 'http://localhost:8080/fhir'
|
||||
refuse_to_fetch_third_party_urls: false
|
||||
fhir_version: R4
|
||||
global:
|
||||
name: Global Tester
|
||||
server_address: "http://hapi.fhir.org/baseR4"
|
||||
refuse_to_fetch_third_party_urls: false
|
||||
fhir_version: R4
|
||||
# validation:
|
||||
# requests_enabled: true
|
||||
# responses_enabled: true
|
||||
# binary_storage_enabled: true
|
||||
# -------------------------------------------------------------------------------
|
||||
# N. Logging
|
||||
# -------------------------------------------------------------------------------
|
||||
# logger:
|
||||
# error_format: "ERROR - ${requestVerb} ${requestUrl}"
|
||||
# format: >-
|
||||
# Path[${servletPath}] Source[${requestHeader.x-forwarded-for}]
|
||||
# Operation[${operationType} ${operationName} ${idOrResourceName}]
|
||||
# UA[${requestHeader.user-agent}] Params[${requestParameters}]
|
||||
# ResponseEncoding[${responseEncodingNoDefault}]
|
||||
# log_exceptions: true
|
||||
# name: fhirtest.access
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# O. Storage / Pagination / Caching
|
||||
# -------------------------------------------------------------------------------
|
||||
# max_binary_size: 104857600
|
||||
# max_page_size: 200
|
||||
# retain_cached_searches_mins: 60
|
||||
# reuse_cached_search_results_millis: 60000
|
||||
inline_resource_storage_below_size: 4000
|
||||
# bulk_export_enabled: true
|
||||
# subscription:
|
||||
# resthook_enabled: true
|
||||
# websocket_enabled: false
|
||||
# polling_interval_ms: 5000
|
||||
# immediately_queued: false
|
||||
# email:
|
||||
# from: some@test.com
|
||||
# host: google.com
|
||||
# port:
|
||||
# username:
|
||||
# password:
|
||||
# auth:
|
||||
# startTlsEnable:
|
||||
# startTlsRequired:
|
||||
# quitWait:
|
||||
# lastn_enabled: true
|
||||
# store_resource_in_lucene_index_enabled: true
|
||||
### This is configuration for normalized quantity search level default is 0
|
||||
### 0: NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED - default
|
||||
### 1: NORMALIZED_QUANTITY_STORAGE_SUPPORTED
|
||||
### 2: NORMALIZED_QUANTITY_SEARCH_SUPPORTED
|
||||
# normalized_quantity_search_level: 2
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# P. Remote Terminology Service (disabled by default)
|
||||
# -------------------------------------------------------------------------------
|
||||
# remote_terminology_service:
|
||||
# all:
|
||||
# system: "*"
|
||||
# url: "https://tx.fhir.org/r4/"
|
||||
# snomed:
|
||||
# system: "http://snomed.info/sct"
|
||||
# url: "https://tx.fhir.org/r4/"
|
||||
# loinc:
|
||||
# system: "http://loinc.org"
|
||||
# url: "https://hapi.fhir.org/baseR4/"
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Q. Subscriptions (disabled by default)
|
||||
# -------------------------------------------------------------------------------
|
||||
# subscription:
|
||||
# resthook_enabled: true
|
||||
# websocket_enabled: false
|
||||
# polling_interval_ms: 5000
|
||||
# immediately_queued: false
|
||||
# email:
|
||||
# from: some@test.com
|
||||
# host: google.com
|
||||
# port:
|
||||
# username:
|
||||
# password:
|
||||
# auth:
|
||||
# startTlsEnable:
|
||||
# startTlsRequired:
|
||||
# quitWait:
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# R. LastN (analytics)
|
||||
# -------------------------------------------------------------------------------
|
||||
# lastn_enabled: true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#Uncomment the "servlet" and "context-path" lines below to make the fhir endpoint available at /example/path/fhir instead of the default value of /fhir
|
||||
server:
|
||||
# servlet:
|
||||
# context-path: /example/path
|
||||
# servlet:
|
||||
# context-path: /example/path
|
||||
port: 8080
|
||||
#Adds the option to go to e.g. http://localhost:8080/actuator/health for seeing the running configuration
|
||||
#see https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints
|
||||
@@ -53,31 +53,38 @@ spring:
|
||||
maximum-pool-size: 10
|
||||
jpa:
|
||||
properties:
|
||||
hibernate.format_sql: false
|
||||
hibernate.show_sql: false
|
||||
hibernate:
|
||||
format_sql: false
|
||||
show_sql: false
|
||||
|
||||
#Hibernate dialect is automatically detected except Postgres and H2.
|
||||
#If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
#If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect
|
||||
hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
# hibernate.hbm2ddl.auto: update
|
||||
# hibernate.jdbc.batch_size: 20
|
||||
# hibernate.cache.use_query_cache: false
|
||||
# hibernate.cache.use_second_level_cache: false
|
||||
# hibernate.cache.use_structured_entries: false
|
||||
# hibernate.cache.use_minimal_puts: false
|
||||
dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect
|
||||
# hibernate.hbm2ddl.auto: update
|
||||
# hibernate.jdbc.batch_size: 20
|
||||
# hibernate.cache.use_query_cache: false
|
||||
# hibernate.cache.use_second_level_cache: false
|
||||
# hibernate.cache.use_structured_entries: false
|
||||
# hibernate.cache.use_minimal_puts: false
|
||||
|
||||
### These settings will enable fulltext search with lucene or elastic
|
||||
hibernate.search.enabled: true
|
||||
### These settings will enable fulltext search with lucene or elastic
|
||||
|
||||
search:
|
||||
enabled: true
|
||||
### lucene parameters
|
||||
# hibernate.search.backend.type: lucene
|
||||
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
||||
# hibernate.search.backend.directory.type: local-filesystem
|
||||
# hibernate.search.backend.directory.root: target/lucenefiles
|
||||
# hibernate.search.backend.lucene_version: lucene_current
|
||||
# hibernate.search.backend.type: lucene
|
||||
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiLuceneAnalysisConfigurer
|
||||
# hibernate.search.backend.directory.type: local-filesystem
|
||||
# hibernate.search.backend.directory.root: target/lucenefiles
|
||||
# hibernate.search.backend.lucene_version: lucene_current
|
||||
### elastic parameters ===> see also elasticsearch section below <===
|
||||
# hibernate.search.backend.type: elasticsearch
|
||||
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
|
||||
autoconfigure:
|
||||
# This exclude is only needed for setups not using Elasticsearch where the elasticsearch sniff is not needed.
|
||||
exclude: org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
|
||||
|
||||
hapi:
|
||||
fhir:
|
||||
### This flag when enabled to true, will avail evaluate measure operations from CR Module.
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opencds.cqf.fhir.cr.hapi.config.CrCdsHooksConfig;
|
||||
import org.opencds.cqf.fhir.cr.hapi.config.RepositoryConfig;
|
||||
@@ -35,25 +36,19 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = {
|
||||
Application.class,
|
||||
NicknameServiceConfig.class,
|
||||
RepositoryConfig.class,
|
||||
TestCdsHooksConfig.class,
|
||||
CrCdsHooksConfig.class,
|
||||
StarterCdsHooksConfig.class
|
||||
}, properties = {
|
||||
"spring.profiles.include=storageSettingsTest",
|
||||
"spring.datasource.url=jdbc:h2:mem:dbr4",
|
||||
"spring.jpa.properties.hibernate.search.backend.directory.type=local-heap",
|
||||
"hapi.fhir.enable_repository_validating_interceptor=true",
|
||||
"hapi.fhir.fhir_version=r4",
|
||||
"hapi.fhir.cr.enabled=true",
|
||||
"hapi.fhir.cr.caregaps.section_author=Organization/alphora-author",
|
||||
"hapi.fhir.cr.caregaps.reporter=Organization/alphora",
|
||||
"hapi.fhir.cdshooks.enabled=true",
|
||||
"spring.main.allow-bean-definition-overriding=true"})
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, NicknameServiceConfig.class, RepositoryConfig.class, TestCdsHooksConfig.class, CrCdsHooksConfig.class, StarterCdsHooksConfig.class},
|
||||
properties = {
|
||||
"spring.profiles.include=storageSettingsTest",
|
||||
"spring.datasource.url=jdbc:h2:mem:dbr4",
|
||||
"spring.jpa.properties.hibernate.search.backend.directory.type=local-heap",
|
||||
"hapi.fhir.enable_repository_validating_interceptor=true",
|
||||
"hapi.fhir.fhir_version=r4",
|
||||
"hapi.fhir.cr.enabled=true",
|
||||
"hapi.fhir.cr.caregaps.section_author=Organization/alphora-author",
|
||||
"hapi.fhir.cr.caregaps.reporter=Organization/alphora",
|
||||
"hapi.fhir.cdshooks.enabled=true",
|
||||
"spring.main.allow-bean-definition-overriding=true",
|
||||
"server.max-http-request-header-size=16KB"})
|
||||
class CdsHooksServletIT implements IServerSupport {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CdsHooksServletIT.class);
|
||||
private final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||
@@ -156,83 +151,87 @@ class CdsHooksServletIT implements IServerSupport {
|
||||
fail(ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testRec10() throws IOException {
|
||||
loadBundle("r4/opioidcds-10-order-sign-bundle.json", ourCtx, ourClient);
|
||||
await().atMost(20000, TimeUnit.MILLISECONDS).until(this::hasCdsServices);
|
||||
var fhirServer = " \"fhirServer\": " + "\"" + ourServerBase + "\"" + ",\n";
|
||||
var cdsRequest = "{\n" +
|
||||
" \"hookInstance\": \"055b009c-4a7d-4db4-a35e-0e5198918ed1\",\n" +
|
||||
" \"hook\": \"order-sign\",\n" +
|
||||
fhirServer +
|
||||
" \"context\": {\n" +
|
||||
" \"patientId\": \"example-rec-10-order-sign-illicit-POS-Cocaine-drugs\",\n" +
|
||||
" \"userId\": \"COREPRACTITIONER1\",\n" +
|
||||
" \"draftOrders\": {\n" +
|
||||
" \"resourceType\": \"Bundle\",\n" +
|
||||
" \"entry\": [\n" +
|
||||
" {\n" +
|
||||
" \"resource\": {\n" +
|
||||
" \"resourceType\": \"MedicationRequest\",\n" +
|
||||
" \"id\": \"request-123\",\n" +
|
||||
" \"status\": \"draft\",\n" +
|
||||
" \"subject\": {\n" +
|
||||
" \"reference\": \"Patient/example-rec-10-order-sign-illicit-POS-Cocaine-drugs\"\n" +
|
||||
" },\n" +
|
||||
" \"authoredOn\": \"2024-03-27\",\n" +
|
||||
" \"dosageInstruction\": [\n" +
|
||||
" {\n" +
|
||||
" \"timing\": {\n" +
|
||||
" \"repeat\": {\n" +
|
||||
" \"frequency\": 1,\n" +
|
||||
" \"period\": 1,\n" +
|
||||
" \"periodUnit\": \"d\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"doseAndRate\": [\n" +
|
||||
" {\n" +
|
||||
" \"doseQuantity\": {\n" +
|
||||
" \"value\": 1,\n" +
|
||||
" \"system\": \"http://unitsofmeasure.org\",\n" +
|
||||
" \"code\": \"{pill}\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"dispenseRequest\": {\n" +
|
||||
" \"expectedSupplyDuration\": {\n" +
|
||||
" \"value\": 90,\n" +
|
||||
" \"unit\": \"days\",\n" +
|
||||
" \"system\": \"http://unitsofmeasure.org\",\n" +
|
||||
" \"code\": \"d\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"intent\": \"order\",\n" +
|
||||
" \"category\": {\n" +
|
||||
" \"coding\": [\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"http://terminology.hl7.org/CodeSystem/medicationrequest-category\",\n" +
|
||||
" \"code\": \"community\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"medicationCodeableConcept\": {\n" +
|
||||
" \"coding\": [\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"http://www.nlm.nih.gov/research/umls/rxnorm\",\n" +
|
||||
" \"code\": \"1049502\",\n" +
|
||||
" \"display\": \"12 HR oxycodone hydrochloride 10 MG Extended Release Oral Tablet\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
var cdsRequest = """
|
||||
{
|
||||
"hookInstance": "055b009c-4a7d-4db4-a35e-0e5198918ed1",
|
||||
"hook": "order-sign",
|
||||
""" + fhirServer + """
|
||||
"context": {
|
||||
"patientId": "example-rec-10-order-sign-illicit-POS-Cocaine-drugs",
|
||||
"userId": "COREPRACTITIONER1",
|
||||
"draftOrders": {
|
||||
"resourceType": "Bundle",
|
||||
"entry": [
|
||||
{
|
||||
"resource": {
|
||||
"resourceType": "MedicationRequest",
|
||||
"id": "request-123",
|
||||
"status": "draft",
|
||||
"subject": {
|
||||
"reference": "Patient/example-rec-10-order-sign-illicit-POS-Cocaine-drugs"
|
||||
},
|
||||
"authoredOn": "2024-03-27",
|
||||
"dosageInstruction": [
|
||||
{
|
||||
"timing": {
|
||||
"repeat": {
|
||||
"frequency": 1,
|
||||
"period": 1,
|
||||
"periodUnit": "d"
|
||||
}
|
||||
},
|
||||
"doseAndRate": [
|
||||
{
|
||||
"doseQuantity": {
|
||||
"value": 1,
|
||||
"system": "http://unitsofmeasure.org",
|
||||
"code": "{pill}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dispenseRequest": {
|
||||
"expectedSupplyDuration": {
|
||||
"value": 90,
|
||||
"unit": "days",
|
||||
"system": "http://unitsofmeasure.org",
|
||||
"code": "d"
|
||||
}
|
||||
},
|
||||
"intent": "order",
|
||||
"category": [
|
||||
{
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category",
|
||||
"code": "community"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"medicationCodeableConcept": {
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||
"code": "1049502",
|
||||
"display": "12 HR oxycodone hydrochloride 10 MG Extended Release Oral Tablet"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||
HttpPost request = new HttpPost(ourCdsBase + "/opioidcds-10-order-sign");
|
||||
request.setEntity(new StringEntity(cdsRequest));
|
||||
@@ -245,7 +244,7 @@ class CdsHooksServletIT implements IServerSupport {
|
||||
assertNotNull(response);
|
||||
JsonArray cards = response.getAsJsonArray("cards");
|
||||
assertEquals(0, cards.size());
|
||||
// assertEquals("\"Hello World!\"", cards.get(0).getAsJsonObject().get("summary").toString());
|
||||
//assertEquals("\"Hello World!\"", cards.get(0).getAsJsonObject().get("summary").toString());
|
||||
} catch (IOException ioe) {
|
||||
fail(ioe.getMessage());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user