Merge remote-tracking branch 'origin/master' into ja_20231203_hapi_7_0

This commit is contained in:
dotasek.dev
2024-02-27 14:37:31 -05:00
27 changed files with 362 additions and 182 deletions

View File

@@ -79,9 +79,8 @@ public class AppProperties {
private Boolean install_transitive_ig_dependencies = true;
private Map<String, PackageInstallationSpec> implementationGuides = null;
private String staticLocation = null;
private String staticLocationPrefix = "/static";
private String custom_content_path = null;
private String app_content_path = null;
private Boolean lastn_enabled = false;
private boolean store_resource_in_lucene_index_enabled = false;
@@ -94,16 +93,9 @@ public class AppProperties {
private Integer bundle_batch_pool_max_size = 100;
private final Set<String> local_base_urls = new HashSet<>();
private final Set<String> logical_urls = new HashSet<>();
private final List<String> custom_interceptor_classes = new ArrayList<>();
public String getStaticLocationPrefix() {
return staticLocationPrefix;
}
public void setStaticLocationPrefix(String staticLocationPrefix) {
this.staticLocationPrefix = staticLocationPrefix;
}
public List<String> getCustomInterceptorClasses() {
@@ -111,14 +103,6 @@ public class AppProperties {
}
public String getStaticLocation() {
return staticLocation;
}
public void setStaticLocation(String staticLocation) {
this.staticLocation = staticLocation;
}
public Boolean getOpenapi_enabled() {
return openapi_enabled;
@@ -575,7 +559,7 @@ public Cors getCors() {
public void setInstall_transitive_ig_dependencies(boolean install_transitive_ig_dependencies) {
this.install_transitive_ig_dependencies = install_transitive_ig_dependencies;
}
public Integer getBundle_batch_pool_size() {
return this.bundle_batch_pool_size;
}
@@ -600,6 +584,7 @@ public Cors getCors() {
return logical_urls;
}
public Boolean getIg_runtime_upload_enabled() {
return ig_runtime_upload_enabled;
}
@@ -608,6 +593,22 @@ public Cors getCors() {
this.ig_runtime_upload_enabled = ig_runtime_upload_enabled;
}
public String getCustom_content_path() {
return custom_content_path;
}
public void setCustom_content_path(String custom_content_path) {
this.custom_content_path = custom_content_path;
}
public String getApp_content_path() {
return app_content_path;
}
public void setApp_content_path(String app_content_path) {
this.app_content_path = app_content_path;
}
public static class Cors {
private Boolean allow_Credentials = true;
private List<String> allowed_origin = List.of("*");

View File

@@ -1,50 +0,0 @@
package ca.uhn.fhir.jpa.starter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.net.URI;
@Configuration
@ConditionalOnProperty(prefix = "hapi.fhir", name = "staticLocation")
public class ExtraStaticFilesConfigurer implements WebMvcConfigurer {
private String staticLocation;
private String rootContextPath;
public ExtraStaticFilesConfigurer(AppProperties appProperties) {
rootContextPath = appProperties.getStaticLocationPrefix();
if (rootContextPath.endsWith("/"))
rootContextPath = rootContextPath.substring(0, rootContextPath.lastIndexOf('/'));
staticLocation = appProperties.getStaticLocation();
if (staticLocation.endsWith("/")) staticLocation = staticLocation.substring(0, staticLocation.lastIndexOf('/'));
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry theRegistry) {
theRegistry.addResourceHandler(rootContextPath + "/**").addResourceLocations(staticLocation);
}
@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 + "/" + lastSegment + "/")
.setViewName("redirect:" + rootContextPath + "/" + lastSegment + "/index.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}

View File

@@ -4,6 +4,7 @@ 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;
@@ -18,7 +19,7 @@ import org.springframework.context.annotation.Import;
*/
@Configuration
@Import(FhirTesterMvcConfig.class)
// @Conditional(FhirTesterConfigCondition.class)
@Conditional(FhirTesterConfigCondition.class)
public class FhirTesterConfig {
/**

View File

@@ -44,6 +44,7 @@ import ca.uhn.fhir.jpa.starter.annotations.OnImplementationGuidesPresent;
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
@@ -272,8 +273,7 @@ public class StarterJpaConfig {
IPackageInstallerSvc packageInstallerSvc,
ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
ApplicationContext appContext,
Optional<IpsOperationProvider> theIpsOperationProvider,
Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
Optional<IpsOperationProvider> theIpsOperationProvider, Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());
List<String> supportedResourceTypes = appProperties.getSupported_resource_types();

View File

@@ -47,7 +47,7 @@ public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryV
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
IBundleProvider results = structureDefinitionResourceProvider.search(
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
Map<String, List<StructureDefinition>> structureDefinitions = results.getResources(0, results.size()).stream()
.map(StructureDefinition.class::cast)
.collect(Collectors.groupingBy(StructureDefinition::getType));

View File

@@ -48,7 +48,7 @@ public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryVali
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
IBundleProvider results = structureDefinitionResourceProvider.search(
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
.map(StructureDefinition.class::cast)
.collect(Collectors.groupingBy(StructureDefinition::getType));

View File

@@ -48,7 +48,7 @@ public class RepositoryValidationInterceptorFactoryR4B implements IRepositoryVal
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
IBundleProvider results = structureDefinitionResourceProvider.search(
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
.map(StructureDefinition.class::cast)
.collect(Collectors.groupingBy(StructureDefinition::getType));

View File

@@ -47,7 +47,7 @@ public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryVali
public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() {
IBundleProvider results = structureDefinitionResourceProvider.search(
new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource")));
new SearchParameterMap().setLoadSynchronous(true).add(StructureDefinition.SP_KIND, new TokenParam("resource")));
Map<String, List<StructureDefinition>> structureDefintions = results.getResources(0, results.size()).stream()
.map(StructureDefinition.class::cast)
.collect(Collectors.groupingBy(StructureDefinition::getType));

View File

@@ -9,16 +9,10 @@ import java.io.IOException;
public interface IImplementationGuideOperationProvider {
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
return new PackageInstallationSpec()
.setName(npmPackage.name())
.setPackageContents(npmPackageAsByteArray)
.setVersion(npmPackage.version())
.setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)
.setFetchDependencies(false);
return new PackageInstallationSpec().setName(npmPackage.name()).setPackageContents(npmPackageAsByteArray).setVersion(npmPackage.version()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL).setFetchDependencies(false);
}
// The following declaration is the one that counts but cannot be used across different versions as stating
// Base64BinaryType would bind to a separate version
// @Operation(name = "$install", typeName = "ImplementationGuide")
// The following declaration is the one that counts but cannot be used across different versions as stating Base64BinaryType would bind to a separate version
// Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);
// Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) ;
}

View File

@@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.starter.ig;
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
@@ -22,15 +23,21 @@ public class ImplementationGuideR4OperationProvider implements IImplementationGu
}
@Operation(name = "$install", typeName = "ImplementationGuide")
public Parameters install(
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
try {
packageInstallerSvc.install(
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return new Parameters();
}
@Operation(name = "$uninstall", typeName = "ImplementationGuide")
public Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {
packageInstallerSvc.uninstall(new PackageInstallationSpec().setName(name).setVersion(version));
return new Parameters();
}
}

View File

@@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.starter.ig;
import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc;
import ca.uhn.fhir.jpa.packages.PackageInstallationSpec;
import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
@@ -13,7 +14,7 @@ import java.io.IOException;
@Conditional({OnR5Condition.class, IgConfigCondition.class})
@Service
public class ImplementationGuideR5OperationProvider {
public class ImplementationGuideR5OperationProvider implements IImplementationGuideOperationProvider {
IPackageInstallerSvc packageInstallerSvc;
@@ -22,15 +23,21 @@ public class ImplementationGuideR5OperationProvider {
}
@Operation(name = "$install", typeName = "ImplementationGuide")
public Parameters install(
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
try {
packageInstallerSvc.install(
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return new Parameters();
}
@Operation(name = "$uninstall", typeName = "ImplementationGuide")
public org.hl7.fhir.r4.model.Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {
packageInstallerSvc.uninstall(new PackageInstallationSpec().setName(name).setVersion(version));
return new org.hl7.fhir.r4.model.Parameters();
}
}

View File

@@ -0,0 +1,40 @@
package ca.uhn.fhir.jpa.starter.web;
import ca.uhn.fhir.jpa.starter.AppProperties;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileUrlResource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.net.MalformedURLException;
@Configuration
@ConditionalOnProperty(prefix = "hapi.fhir", name = "custom_content_path")
public class CustomContentFilesConfigurer implements WebMvcConfigurer {
public static final String CUSTOM_CONTENT = "/content";
private String customContentPath;
public CustomContentFilesConfigurer(AppProperties appProperties) {
customContentPath = appProperties.getCustom_content_path();
if (customContentPath.endsWith("/"))
customContentPath = customContentPath.substring(0, customContentPath.lastIndexOf('/'));
}
@Override
public void addResourceHandlers(@NotNull ResourceHandlerRegistry theRegistry) {
if (!theRegistry.hasMappingForPattern(CUSTOM_CONTENT + "/**")) {
try {
theRegistry.addResourceHandler(CUSTOM_CONTENT + "/**").addResourceLocations(new FileUrlResource(customContentPath));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
}

View File

@@ -0,0 +1,56 @@
package ca.uhn.fhir.jpa.starter.web;
import ca.uhn.fhir.jpa.starter.AppProperties;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.FileUrlResource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.net.MalformedURLException;
import java.net.URI;
@Configuration
@ConditionalOnProperty(prefix = "hapi.fhir", name = "app_content_path")
public class WebAppFilesConfigurer implements WebMvcConfigurer {
public static final String WEB_CONTENT = "web";
private String appContentPath;
public WebAppFilesConfigurer(AppProperties appProperties) {
appContentPath = appProperties.getApp_content_path();
if (appContentPath.endsWith("/"))
appContentPath = appContentPath.substring(0, appContentPath.lastIndexOf('/'));
}
@Override
public void addResourceHandlers(@NotNull ResourceHandlerRegistry theRegistry) {
if (!theRegistry.hasMappingForPattern(WEB_CONTENT + "/**")) {
{
try {
theRegistry.addResourceHandler(WEB_CONTENT + "/**").addResourceLocations(new FileUrlResource(appContentPath));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
}
@Override
public void addViewControllers(@NotNull ViewControllerRegistry registry) {
String path = URI.create(appContentPath).getPath();
String lastSegment = path.substring(path.lastIndexOf('/') + 1);
registry.addViewController(WEB_CONTENT + "/" + lastSegment).setViewName("redirect:" + lastSegment + "/index.html");
registry.addViewController(WEB_CONTENT + "/" + lastSegment + "/").setViewName("redirect:index.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}