From 4eaa9fbfb2744a9688e09b119abf53f665fce46c Mon Sep 17 00:00:00 2001 From: jvi Date: Mon, 8 Feb 2021 16:36:55 +0100 Subject: [PATCH 1/4] Springified the wiring of interceptors --- .../jpa/starter/BaseJpaRestfulServer.java | 15 +++------ .../jpa/starter/FhirServerConfigCommon.java | 7 ---- ...epositoryValidationInterceptorFactory.java | 32 ++++++++++++------- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index 745d838..01d4c39 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -10,7 +10,6 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.bulk.provider.BulkDataExportProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; -import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; @@ -97,6 +96,10 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired ApplicationContext myApplicationContext; + + @Autowired(required = false) + RepositoryValidationInterceptorFactory repositoryValidationInterceptorFactory; + public BaseJpaRestfulServer() { } @@ -364,15 +367,5 @@ public class BaseJpaRestfulServer extends RestfulServer { } daoConfig.getModelConfig().setNormalizedQuantitySearchLevel(appProperties.getNormalized_quantity_search_level()); - - // Repository Validating Interceptor - if (Boolean.TRUE.equals(appProperties.getEnable_repository_validating_interceptor())) { - RepositoryValidationInterceptorFactory repositoryValidationInterceptorFactory = myApplicationContext.getBean(RepositoryValidationInterceptorFactory.class); - RepositoryValidatingInterceptor interceptor = repositoryValidationInterceptorFactory.build(); - interceptorService.registerInterceptor(interceptor); - } - } - - } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java index 965e028..80bbe24 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/FhirServerConfigCommon.java @@ -132,13 +132,6 @@ public class FhirServerConfigCommon { } - @Bean - @Lazy - public RepositoryValidationInterceptorFactory repositoryValidationInterceptorFactory() { - return new RepositoryValidationInterceptorFactory(); - } - - @Primary @Bean public HibernatePropertiesProvider jpaStarterDialectProvider(LocalContainerEntityManagerFactoryBean myEntityManagerFactory) { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java index 0ea6652..c9ecff7 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java @@ -1,38 +1,48 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.interceptor.api.IInterceptorService; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; +import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; import java.util.List; /** * This class can be customized to enable the {@link ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor} * on this server. - * + *

* The enable_repository_validating_interceptor property must be enabled in application.yaml * in order to use this class. */ +@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@Configuration +@Conditional({OnEitherVersion.class}) public class RepositoryValidationInterceptorFactory { - @Autowired - private ApplicationContext myApplicationContext; - @Autowired - private FhirContext myFhirContext; + private final FhirContext fhirContext; + private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; + + public RepositoryValidationInterceptorFactory(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry, IInterceptorService interceptorService) { + this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder; + this.fhirContext = daoRegistry.getSystemDao().getContext(); + interceptorService.registerInterceptor(build()); + } public RepositoryValidatingInterceptor build() { - RepositoryValidatingRuleBuilder ruleBuilder = myApplicationContext.getBean(RepositoryValidatingRuleBuilder.class); // Customize the ruleBuilder here to have the rules you want! We will give a simple example // of enabling validation for all Patient resources - ruleBuilder.forResourcesOfType("Patient").requireValidationToDeclaredProfiles(); + repositoryValidatingRuleBuilder.forResourcesOfType("Patient").requireValidationToDeclaredProfiles(); // Do not customize below this line - List rules = ruleBuilder.build(); - return new RepositoryValidatingInterceptor(myFhirContext, rules); + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); } } From 4bfafc9be51abfd4d2fa70aff2d4953ca8daf8a7 Mon Sep 17 00:00:00 2001 From: jvi Date: Tue, 9 Feb 2021 00:18:17 +0100 Subject: [PATCH 2/4] Removed unnecessary wiring --- .../java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 4 ---- .../jpa/starter/RepositoryValidationInterceptorFactory.java | 3 --- 2 files changed, 7 deletions(-) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index 01d4c39..da3e989 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -96,10 +96,6 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired ApplicationContext myApplicationContext; - - @Autowired(required = false) - RepositoryValidationInterceptorFactory repositoryValidationInterceptorFactory; - public BaseJpaRestfulServer() { } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java index c9ecff7..577c412 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java @@ -6,9 +6,7 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; -import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import java.util.List; @@ -22,7 +20,6 @@ import java.util.List; */ @ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") @Configuration -@Conditional({OnEitherVersion.class}) public class RepositoryValidationInterceptorFactory { private final FhirContext fhirContext; From 5aec4b7e18948b797d77f449793be53d083bc51f Mon Sep 17 00:00:00 2001 From: jvi Date: Wed, 10 Feb 2021 16:57:14 +0100 Subject: [PATCH 3/4] Now with example of wiring up installed IG's --- .../jpa/starter/BaseJpaRestfulServer.java | 20 +++-- ...epositoryValidationInterceptorFactory.java | 45 ----------- ...toryValidationInterceptorFactoryDstu3.java | 74 +++++++++++++++++++ ...ositoryValidationInterceptorFactoryR4.java | 74 +++++++++++++++++++ ...ositoryValidationInterceptorFactoryR5.java | 74 +++++++++++++++++++ 5 files changed, 237 insertions(+), 50 deletions(-) delete mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index da3e989..aba299b 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -11,6 +11,7 @@ import ca.uhn.fhir.jpa.binstore.BinaryStorageInterceptor; import ca.uhn.fhir.jpa.bulk.provider.BulkDataExportProvider; import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor; import ca.uhn.fhir.jpa.packages.IPackageInstallerSvc; +import ca.uhn.fhir.jpa.packages.PackageInstallOutcomeJson; import ca.uhn.fhir.jpa.packages.PackageInstallationSpec; import ca.uhn.fhir.jpa.partition.PartitionManagementProvider; import ca.uhn.fhir.jpa.provider.*; @@ -96,6 +97,9 @@ public class BaseJpaRestfulServer extends RestfulServer { @Autowired ApplicationContext myApplicationContext; + @Autowired(required = false) + RepositoryValidationInterceptorFactoryR4 factory; + public BaseJpaRestfulServer() { } @@ -350,14 +354,20 @@ public class BaseJpaRestfulServer extends RestfulServer { if (appProperties.getImplementationGuides() != null) { Map guides = appProperties.getImplementationGuides(); for (Map.Entry guide : guides.entrySet()) { - packageInstallerSvc.install(new PackageInstallationSpec() - .setPackageUrl(guide.getValue().getUrl()) - .setName(guide.getValue().getName()) - .setVersion(guide.getValue().getVersion()) - .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)); + PackageInstallOutcomeJson outcome = packageInstallerSvc.install(new PackageInstallationSpec() + .setPackageUrl(guide.getValue().getUrl()) + .setName(guide.getValue().getName()) + .setVersion(guide.getValue().getVersion()) + .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)); + } } + if(factory != null) + interceptorService.registerInterceptor(factory.buildUsingStoredStructureDefinitions()); + + + if (appProperties.getLastn_enabled()) { daoConfig.setLastNEnabled(true); } diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java deleted file mode 100644 index 577c412..0000000 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.interceptor.api.IInterceptorService; -import ca.uhn.fhir.jpa.api.dao.DaoRegistry; -import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; -import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; -import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Configuration; - -import java.util.List; - -/** - * This class can be customized to enable the {@link ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor} - * on this server. - *

- * The enable_repository_validating_interceptor property must be enabled in application.yaml - * in order to use this class. - */ -@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") -@Configuration -public class RepositoryValidationInterceptorFactory { - - private final FhirContext fhirContext; - private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; - - public RepositoryValidationInterceptorFactory(RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder, DaoRegistry daoRegistry, IInterceptorService interceptorService) { - this.repositoryValidatingRuleBuilder = repositoryValidatingRuleBuilder; - this.fhirContext = daoRegistry.getSystemDao().getContext(); - interceptorService.registerInterceptor(build()); - } - - public RepositoryValidatingInterceptor build() { - - // 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").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/RepositoryValidationInterceptorFactoryDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java new file mode 100644 index 0000000..79ed691 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java @@ -0,0 +1,74 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.TokenParam; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * This class can be customized to enable the {@link RepositoryValidatingInterceptor} + * on this server. + *

+ * The enable_repository_validating_interceptor property must be enabled in application.yaml + * in order to use this class. + */ +@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@Configuration +@Conditional(OnDSTU3Condition.class) +public class RepositoryValidationInterceptorFactoryDstu3 { + + private final FhirContext fhirContext; + private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; + private final IFhirResourceDao structureDefinitionResourceProvider; + + 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> structureDefintions = results.getResources(0, results.size()) + .stream() + .map(StructureDefinition.class::cast) + .collect(Collectors.groupingBy(StructureDefinition::getType)); + + structureDefintions.entrySet().forEach(structureDefinitionListEntry -> + { + String[] urls = structureDefinitionListEntry.getValue().stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(structureDefinitionListEntry.getKey()).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + }); + + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); + } + + public RepositoryValidatingInterceptor build() { + + // 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(); + + // 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/RepositoryValidationInterceptorFactoryR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java new file mode 100644 index 0000000..2a053dc --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java @@ -0,0 +1,74 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.TokenParam; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * This class can be customized to enable the {@link ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor} + * on this server. + *

+ * The enable_repository_validating_interceptor property must be enabled in application.yaml + * in order to use this class. + */ +@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@Configuration +@Conditional(OnR4Condition.class) +public class RepositoryValidationInterceptorFactoryR4 { + + private final FhirContext fhirContext; + private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; + private final IFhirResourceDao structureDefinitionResourceProvider; + + public RepositoryValidationInterceptorFactoryR4(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)); + + structureDefintions.entrySet().forEach(structureDefinitionListEntry -> + { + String[] urls = structureDefinitionListEntry.getValue().stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(structureDefinitionListEntry.getKey()).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + }); + + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); + } + + public RepositoryValidatingInterceptor build() { + + // 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(); + + // 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/RepositoryValidationInterceptorFactoryR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java new file mode 100644 index 0000000..0ddcc96 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java @@ -0,0 +1,74 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.DaoRegistry; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder; +import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.jpa.starter.annotations.OnR5Condition; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.TokenParam; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * This class can be customized to enable the {@link RepositoryValidatingInterceptor} + * on this server. + *

+ * The enable_repository_validating_interceptor property must be enabled in application.yaml + * in order to use this class. + */ +@ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") +@Configuration +@Conditional(OnR5Condition.class) +public class RepositoryValidationInterceptorFactoryR5 { + + private final FhirContext fhirContext; + private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; + private final IFhirResourceDao structureDefinitionResourceProvider; + + 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)); + + structureDefintions.entrySet().forEach(structureDefinitionListEntry -> + { + String[] urls = structureDefinitionListEntry.getValue().stream().map(StructureDefinition::getUrl).toArray(String[]::new); + repositoryValidatingRuleBuilder.forResourcesOfType(structureDefinitionListEntry.getKey()).requireAtLeastOneProfileOf(urls).and().requireValidationToDeclaredProfiles(); + }); + + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); + } + + public RepositoryValidatingInterceptor build() { + + // 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(); + + // Do not customize below this line + List rules = repositoryValidatingRuleBuilder.build(); + return new RepositoryValidatingInterceptor(fhirContext, rules); + } + +} From 77f4fcba343bdf98159f39b7d4b20607157c7e17 Mon Sep 17 00:00:00 2001 From: jvi Date: Thu, 11 Feb 2021 11:17:48 +0100 Subject: [PATCH 4/4] Adjusted according to review --- .../ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java | 10 +++++----- .../IRepositoryValidationInterceptorFactory.java | 9 +++++++++ .../RepositoryValidationInterceptorFactoryDstu3.java | 2 +- .../RepositoryValidationInterceptorFactoryR4.java | 4 +++- .../RepositoryValidationInterceptorFactoryR5.java | 2 +- 5 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java index aba299b..8a12b87 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/BaseJpaRestfulServer.java @@ -98,7 +98,7 @@ public class BaseJpaRestfulServer extends RestfulServer { ApplicationContext myApplicationContext; @Autowired(required = false) - RepositoryValidationInterceptorFactoryR4 factory; + IRepositoryValidationInterceptorFactory factory; public BaseJpaRestfulServer() { @@ -354,7 +354,7 @@ public class BaseJpaRestfulServer extends RestfulServer { if (appProperties.getImplementationGuides() != null) { Map guides = appProperties.getImplementationGuides(); for (Map.Entry guide : guides.entrySet()) { - PackageInstallOutcomeJson outcome = packageInstallerSvc.install(new PackageInstallationSpec() + packageInstallerSvc.install(new PackageInstallationSpec() .setPackageUrl(guide.getValue().getUrl()) .setName(guide.getValue().getName()) .setVersion(guide.getValue().getVersion()) @@ -363,9 +363,9 @@ public class BaseJpaRestfulServer extends RestfulServer { } } - if(factory != null) - interceptorService.registerInterceptor(factory.buildUsingStoredStructureDefinitions()); - + if(factory != null) { + interceptorService.registerInterceptor(factory.buildUsingStoredStructureDefinitions()); + } if (appProperties.getLastn_enabled()) { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java b/src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java new file mode 100644 index 0000000..13262a1 --- /dev/null +++ b/src/main/java/ca/uhn/fhir/jpa/starter/IRepositoryValidationInterceptorFactory.java @@ -0,0 +1,9 @@ +package ca.uhn.fhir.jpa.starter; + +import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor; + +public interface IRepositoryValidationInterceptorFactory { + RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions(); + + RepositoryValidatingInterceptor build(); +} diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java index 79ed691..a68ae3e 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryDstu3.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; @ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") @Configuration @Conditional(OnDSTU3Condition.class) -public class RepositoryValidationInterceptorFactoryDstu3 { +public class RepositoryValidationInterceptorFactoryDstu3 implements IRepositoryValidationInterceptorFactory { private final FhirContext fhirContext; private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java index 2a053dc..a563d3c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR4.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; @ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") @Configuration @Conditional(OnR4Condition.class) -public class RepositoryValidationInterceptorFactoryR4 { +public class RepositoryValidationInterceptorFactoryR4 implements IRepositoryValidationInterceptorFactory { private final FhirContext fhirContext; private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder; @@ -42,6 +42,7 @@ public class RepositoryValidationInterceptorFactoryR4 { } + @Override public RepositoryValidatingInterceptor buildUsingStoredStructureDefinitions() { IBundleProvider results = structureDefinitionResourceProvider.search(new SearchParameterMap().add(StructureDefinition.SP_KIND, new TokenParam("resource"))); @@ -60,6 +61,7 @@ public class RepositoryValidationInterceptorFactoryR4 { return new RepositoryValidatingInterceptor(fhirContext, rules); } + @Override public RepositoryValidatingInterceptor build() { // Customize the ruleBuilder here to have the rules you want! We will give a simple example diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java index 0ddcc96..7702ef0 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/RepositoryValidationInterceptorFactoryR5.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; @ConditionalOnProperty(prefix = "hapi.fhir", name = "enable_repository_validating_interceptor", havingValue = "true") @Configuration @Conditional(OnR5Condition.class) -public class RepositoryValidationInterceptorFactoryR5 { +public class RepositoryValidationInterceptorFactoryR5 implements IRepositoryValidationInterceptorFactory { private final FhirContext fhirContext; private final RepositoryValidatingRuleBuilder repositoryValidatingRuleBuilder;