Standalone subscription (#1125)

This commit is contained in:
Ken Stevens 2018-11-30 17:19:16 -05:00 committed by GitHub
parent b2179b1696
commit 6baee4dc3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
287 changed files with 3394 additions and 1923 deletions

View File

@ -11,7 +11,7 @@ jdk:
- oraclejdk9
env:
global:
- MAVEN_OPTS="-Xmx1024m"
- MAVEN_OPTS="-Xmx10244M -Xss128M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=1024M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
cache:
directories:

View File

@ -26,6 +26,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Scanner;
// FIXME KHS
@Ignore
public class CdsExampleTests {
private static IGenericClient ourClient;
private static FhirContext ourCtx = FhirContext.forDstu3();

View File

@ -54,7 +54,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
/**
* Configure FHIR properties around the the JPA server via this bean
*/
@Bean()
@Bean
public DaoConfig daoConfig() {
return FhirServerConfigCommon.getDaoConfig();
}
@ -71,7 +71,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
}
@Override
@Bean()
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
return FhirServerConfigCommon.getEntityManagerFactory(env, dataSource(), fhirContextDstu3());
}
@ -99,7 +99,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
return interceptor;
}
@Bean()
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return FhirServerConfigCommon.getTransactionManager(entityManagerFactory);
}

View File

@ -57,7 +57,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
* Configure FHIR properties around the the JPA server via this bean
*/
@SuppressWarnings("deprecation")
@Bean()
@Bean
public DaoConfig daoConfig() {
return FhirServerConfigCommon.getDaoConfig();
}
@ -74,7 +74,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
}
@Override
@Bean()
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
return FhirServerConfigCommon.getEntityManagerFactory(env, dataSource(), fhirContextDstu2());
}
@ -103,7 +103,7 @@ public class FhirServerConfigDstu2 extends BaseJavaConfigDstu2 {
return interceptor;
}
@Bean()
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return FhirServerConfigCommon.getTransactionManager(entityManagerFactory);
}

View File

@ -37,7 +37,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
/**
* Configure FHIR properties around the the JPA server via this bean
*/
@Bean()
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
retVal.setSubscriptionEnabled(true);
@ -64,13 +64,11 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
}
@Override
@Bean()
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = new LocalContainerEntityManagerFactoryBean();
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
retVal.setPersistenceUnitName("HAPI_PU");
retVal.setDataSource(dataSource());
retVal.setPackagesToScan("ca.uhn.fhir.jpa.entity");
retVal.setPersistenceProvider(new HibernatePersistenceProvider());
retVal.setJpaProperties(jpaProperties());
return retVal;
}
@ -122,7 +120,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
return retVal;
}
@Bean()
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager retVal = new JpaTransactionManager();
retVal.setEntityManagerFactory(entityManagerFactory);

View File

@ -61,7 +61,6 @@ ca.uhn.fhir.validation.ValidationResult.noIssuesDetected=No issues detected duri
ca.uhn.fhir.jpa.config.HapiFhirHibernateJpaDialect.resourceVersionConstraintFailure=The operation has failed with a version constraint failure. This generally means that two clients/threads were trying to update the same resource at the same time, and this request was chosen as the failing request.
ca.uhn.fhir.jpa.config.HapiFhirHibernateJpaDialect.resourceIndexedCompositeStringUniqueConstraintFailure=The operation has failed with a unique index constraint failure. This probably means that the operation was trying to create/update a resource that would have resulted in a duplicate value for a unique index.
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.externalReferenceNotAllowed=Resource contains external reference to URL "{0}" but this server is not configured to allow external references
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.incomingNoopInTransaction=Transaction contains resource with operation NOOP. This is only valid as a response operation, not in a request
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.invalidMatchUrlInvalidResourceType=Invalid match URL "{0}" - Unknown resource type: "{1}"
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.invalidMatchUrlNoMatches=Invalid match URL "{0}" - No resources match this search
@ -92,7 +91,8 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.successfulUpdate=Successfully update
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.successfulDeletes=Successfully deleted {0} resource(s) in {1}ms
ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao.invalidSearchParameter=Unknown search parameter "{0}". Value search parameters for this search are: {1}
ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor.failedToExtractPaths=Failed to extract values from resource using FHIRPath "{0}": {1}
ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor.externalReferenceNotAllowed=Resource contains external reference to URL "{0}" but this server is not configured to allow external references
ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor.failedToExtractPaths=Failed to extract values from resource using FHIRPath "{0}": {1}
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidQuantityPrefix=Unable to handle quantity prefix "{0}" for value: {1}
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidNumberPrefix=Unable to handle number prefix "{0}" for value: {1}

View File

@ -37,7 +37,7 @@ public class FhirDbConfig {
return retVal;
}
@Bean()
@Bean
public Properties jpaProperties() {
Properties extraProperties = new Properties();
extraProperties.put("hibernate.dialect", DerbyTenSevenHapiFhirDialect.class.getName());

View File

@ -36,7 +36,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu2 {
/**
* Configure FHIR properties around the the JPA server via this bean
*/
@Bean()
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
retVal.setSubscriptionEnabled(true);
@ -47,13 +47,11 @@ public class FhirServerConfig extends BaseJavaConfigDstu2 {
}
@Override
@Bean()
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
retVal.setPersistenceUnitName("HAPI_PU");
retVal.setDataSource(myDataSource);
retVal.setPackagesToScan("ca.uhn.fhir.jpa.entity");
retVal.setPersistenceProvider(new HibernatePersistenceProvider());
retVal.setJpaProperties(myJpaProperties);
return retVal;
}
@ -87,7 +85,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu2 {
return retVal;
}
@Bean()
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager retVal = new JpaTransactionManager();
retVal.setEntityManagerFactory(entityManagerFactory);

View File

@ -2,14 +2,18 @@ package ca.uhn.fhir.jpa.demo;
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@ -42,7 +46,7 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 {
/**
* Configure FHIR properties around the the JPA server via this bean
*/
@Bean()
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
retVal.setSubscriptionEnabled(true);
@ -52,8 +56,13 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 {
return retVal;
}
@Bean
public ModelConfig modelConfig() {
return daoConfig().getModelConfig();
}
@Override
@Bean()
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
retVal.setPersistenceUnitName("HAPI_PU");
@ -90,11 +99,10 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 {
return retVal;
}
@Bean()
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager retVal = new JpaTransactionManager();
retVal.setEntityManagerFactory(entityManagerFactory);
return retVal;
}
}

View File

@ -42,7 +42,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 {
/**
* Configure FHIR properties around the the JPA server via this bean
*/
@Bean()
@Bean
public DaoConfig daoConfig() {
DaoConfig retVal = new DaoConfig();
retVal.setSubscriptionEnabled(true);
@ -53,7 +53,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 {
}
@Override
@Bean()
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
retVal.setPersistenceUnitName("HAPI_PU");
@ -90,7 +90,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 {
return retVal;
}
@Bean()
@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager retVal = new JpaTransactionManager();
retVal.setEntityManagerFactory(entityManagerFactory);

View File

@ -76,8 +76,23 @@
<artifactId>hapi-fhir-client-okhttp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-subscription</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-searchparam</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
</dependency>
@ -303,6 +318,9 @@
<include>hapi-fhir-structures-hl7org-dstu2/target/jacoco.exec</include>
<include>hapi-fhir-structures-dstu3/target/jacoco.exec</include>
<include>hapi-fhir-structures-r4/target/jacoco.exec</include>
<include>hapi-fhir-jpaserver-model/target/jacoco.exec</include>
<include>hapi-fhir-jpaserver-searchparam/target/jacoco.exec</include>
<include>hapi-fhir-jpaserver-subscription/target/jacoco.exec</include>
<include>hapi-fhir-jpaserver-base/target/jacoco.exec</include>
<include>hapi-fhir-client-okhttp/target/jacoco.exec</include>
<include>hapi-fhir-android/target/jacoco.exec</include>
@ -341,6 +359,9 @@
<sourceDirectory>../hapi-fhir-structures-hl7org-dstu2/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-dstu3/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-structures-r4/src/test/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-model/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-searchparam/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-subscription/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-jpaserver-base/src/main/java</sourceDirectory>
<sourceDirectory>../hapi-fhir-client-okhttp/src/main/java</sourceDirectory>
</sourceDirectories>
@ -368,6 +389,9 @@
<source>../hapi-fhir-base/src/main/java</source>
<source>../hapi-fhir-client/src/main/java</source>
<source>../hapi-fhir-server/src/main/java</source>
<source>../hapi-fhir-jpaserver-model/src/main/java</source>
<source>../hapi-fhir-jpaserver-searchparam/src/main/java</source>
<source>../hapi-fhir-jpaserver-subscription/src/main/java</source>
<source>../hapi-fhir-jpaserver-base/src/main/java</source>
</sources>
</configuration>
@ -395,6 +419,15 @@
<testResource>
<directory>../hapi-fhir-base/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-jpaserver-model/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-jpaserver-searchparam/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-jpaserver-subscription/src/test/resources</directory>
</testResource>
<testResource>
<directory>../hapi-fhir-jpaserver-base/src/test/resources</directory>
</testResource>

View File

@ -70,6 +70,21 @@
<artifactId>hapi-fhir-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-subscription</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-searchparam</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-validation</artifactId>
@ -550,74 +565,29 @@
</pluginManagement>
<plugins>
<plugin>
<groupId>de.juplo</groupId>
<artifactId>hibernate-maven-plugin</artifactId>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate52-ddl-maven-plugin</artifactId>
<configuration>
<dialects>
<param>derby_10_7</param>
<param>postgresql92</param>
<param>mysql57</param>
<param>mariadb</param>
<param>oracle12c</param>
<param>sqlserver2012</param>
</dialects>
<outputDirectory>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database</outputDirectory>
<packages>
<param>ca.uhn.fhir.jpa.entity</param>
<param>ca.uhn.fhir.jpa.model.entity</param>
</packages>
</configuration>
<executions>
<execution>
<id>derby107</id>
<phase>process-classes</phase>
<goals>
<goal>create</goal>
<goal>gen-ddl</goal>
</goals>
<configuration>
<dialect>org.hibernate.dialect.DerbyTenSevenDialect</dialect>
<outputFile>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database/persistence_create_derby107.sql</outputFile>
</configuration>
</execution>
<execution>
<id>postgres94</id>
<phase>process-classes</phase>
<goals>
<goal>create</goal>
</goals>
<configuration>
<dialect>org.hibernate.dialect.PostgreSQL94Dialect</dialect>
<outputFile>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database/persistence_create_postgres94.sql</outputFile>
</configuration>
</execution>
<execution>
<id>mysql57</id>
<phase>process-classes</phase>
<goals>
<goal>create</goal>
</goals>
<configuration>
<dialect>org.hibernate.dialect.MySQL57Dialect</dialect>
<outputFile>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database/persistence_create_mysql57.sql</outputFile>
</configuration>
</execution>
<execution>
<id>mariadb103</id>
<phase>process-classes</phase>
<goals>
<goal>create</goal>
</goals>
<configuration>
<dialect>org.hibernate.dialect.MariaDB103Dialect</dialect>
<outputFile>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database/persistence_create_mariadb103.sql</outputFile>
</configuration>
</execution>
<execution>
<id>oracle12c</id>
<phase>process-classes</phase>
<goals>
<goal>create</goal>
</goals>
<configuration>
<dialect>org.hibernate.dialect.Oracle12cDialect</dialect>
<outputFile>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database/persistence_create_oracle12c.sql</outputFile>
</configuration>
</execution>
<execution>
<id>sqlserver2012</id>
<phase>process-classes</phase>
<goals>
<goal>create</goal>
</goals>
<configuration>
<dialect>org.hibernate.dialect.SQLServer2012Dialect</dialect>
<outputFile>${project.build.directory}/classes/ca/uhn/hapi/fhir/jpa/docs/database/persistence_create_sqlserver2012.sql</outputFile>
</configuration>
</execution>
</executions>
<dependencies>

View File

@ -2,12 +2,15 @@ package ca.uhn.fhir.jpa.config;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.i18n.HapiLocalizer;
import ca.uhn.fhir.jpa.dao.DatabaseSearchParamProvider;
import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
import ca.uhn.fhir.jpa.subscription.config.BaseSubscriptionConfig;
import ca.uhn.fhir.jpa.subscription.email.SubscriptionEmailInterceptor;
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
import ca.uhn.fhir.jpa.subscription.websocket.SubscriptionWebsocketInterceptor;
@ -88,7 +91,7 @@ public abstract class BaseConfig implements SchedulingConfigurer {
public abstract FhirContext fhirContext();
@Bean()
@Bean
public ScheduledExecutorFactoryBean scheduledExecutorService() {
ScheduledExecutorFactoryBean b = new ScheduledExecutorFactoryBean();
b.setPoolSize(5);
@ -102,7 +105,7 @@ public abstract class BaseConfig implements SchedulingConfigurer {
return new SubscriptionTriggeringProvider();
}
@Bean()
@Bean
public TaskScheduler taskScheduler() {
ConcurrentTaskScheduler retVal = new ConcurrentTaskScheduler();
retVal.setConcurrentExecutor(scheduledExecutorService().getObject());
@ -128,6 +131,11 @@ public abstract class BaseConfig implements SchedulingConfigurer {
return new StaleSearchDeletingSvcImpl();
}
@Bean
protected ISearchParamProvider searchParamProvider() {
return new DatabaseSearchParamProvider();
}
/**
* Note: If you're going to use this, you need to provide a bean
* of type {@link ca.uhn.fhir.jpa.subscription.email.IEmailSender}
@ -151,9 +159,10 @@ public abstract class BaseConfig implements SchedulingConfigurer {
return new SubscriptionWebsocketInterceptor();
}
public static void configureEntityManagerFactory(LocalContainerEntityManagerFactoryBean theFactory, FhirContext theCtx) {
theFactory.setJpaDialect(hibernateJpaDialect(theCtx.getLocalizer()));
theFactory.setPackagesToScan("ca.uhn.fhir.jpa.entity");
theFactory.setPackagesToScan("ca.uhn.fhir.jpa.model.entity", "ca.uhn.fhir.jpa.entity");
theFactory.setPersistenceProvider(new HibernatePersistenceProvider());
}

View File

@ -1,7 +1,12 @@
package ca.uhn.fhir.jpa.config;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu2;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryDstu2;
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu2;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
@ -111,7 +116,7 @@ public class BaseDstu2Config extends BaseConfig {
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryDstu2();
return new SearchParamRegistryDstu2(searchParamProvider());
}
@Bean(name = "mySystemDaoDstu2", autowire = Autowire.BY_NAME)

View File

@ -21,8 +21,8 @@ package ca.uhn.fhir.jpa.config;
*/
import ca.uhn.fhir.i18n.HapiLocalizer;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import org.hibernate.HibernateException;

View File

@ -3,11 +3,15 @@ package ca.uhn.fhir.jpa.config.dstu3;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ParserOptions;
import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.dstu3.TransactionProcessorVersionAdapterDstu3;
import ca.uhn.fhir.jpa.dao.dstu3.SearchParamExtractorDstu3;
import ca.uhn.fhir.jpa.dao.dstu3.SearchParamRegistryDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryDstu3;
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu3;
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcDstu3;
@ -119,7 +123,7 @@ public class BaseDstu3Config extends BaseConfig {
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryDstu3();
return new SearchParamRegistryDstu3(searchParamProvider());
}
@Bean(name = "mySystemDaoDstu3", autowire = Autowire.BY_NAME)

View File

@ -3,12 +3,16 @@ package ca.uhn.fhir.jpa.config.r4;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ParserOptions;
import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.r4.SearchParamExtractorR4;
import ca.uhn.fhir.jpa.dao.r4.SearchParamRegistryR4;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4;
import ca.uhn.fhir.jpa.graphql.JpaStorageServices;
import ca.uhn.fhir.jpa.provider.r4.TerminologyUploaderProviderR4;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryR4;
import ca.uhn.fhir.jpa.term.HapiTerminologySvcR4;
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcR4;
@ -134,7 +138,7 @@ public class BaseR4Config extends BaseConfig {
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryR4();
return new SearchParamRegistryR4(searchParamProvider());
}
@Bean(name = "mySystemDaoR4", autowire = Autowire.BY_NAME)

View File

@ -2,12 +2,17 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.dao.index.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.dao.index.SearchParamExtractorService;
import ca.uhn.fhir.jpa.dao.index.*;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.LogicalReferenceHelper;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.DeleteConflict;
@ -111,7 +116,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
public static final String OO_SEVERITY_ERROR = "error";
public static final String OO_SEVERITY_INFO = "information";
public static final String OO_SEVERITY_WARN = "warning";
public static final String UCUM_NS = "http://unitsofmeasure.org";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirDao.class);
private static final Map<FhirVersionEnum, FhirContext> ourRetrievalContexts = new HashMap<FhirVersionEnum, FhirContext>();
private static final String PROCESSING_SUB_REQUEST = "BaseHapiFhirDao.processingSubRequest";
@ -182,9 +186,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
@Autowired
private DaoRegistry myDaoRegistry;
@Autowired
private MatchUrlService myMatchUrlService;
@Autowired
private SearchParamExtractorService mySearchParamExtractorService;
@Autowired
private SearchParamWithInlineReferencesExtractor mySearchParamWithInlineReferencesExtractor;
@Autowired
private DatabaseSearchParamSynchronizer myDatabaseSearchParamSynchronizer;
private ApplicationContext myApplicationContext;
@ -743,7 +749,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
}
public boolean isLogicalReference(IIdType theId) {
return LogicalReferenceHelper.isLogicalReference(myConfig, theId);
return LogicalReferenceHelper.isLogicalReference(myConfig.getModelConfig(), theId);
}
@Override
@ -1291,7 +1297,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
if (thePerformIndexing) {
newParams = new ResourceIndexedSearchParams();
mySearchParamExtractorService.populateFromResource(newParams, this, theUpdateTime, theEntity, theResource, existingParams);
mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, this, theUpdateTime, theEntity, theResource, existingParams);
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true);
@ -1395,7 +1401,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
* Indexing
*/
if (thePerformIndexing) {
mySearchParamExtractorService.removeCommon(newParams, theEntity, existingParams);
myDatabaseSearchParamSynchronizer.synchronizeSearchParamsToDatabase(newParams, theEntity, existingParams);
mySearchParamWithInlineReferencesExtractor.storeCompositeStringUniques(newParams, theEntity, existingParams);
} // if thePerformIndexing
if (theResource != null) {
@ -1678,32 +1685,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
return bytes;
}
public static String normalizeString(String theString) {
CharArrayWriter outBuffer = new CharArrayWriter(theString.length());
/*
* The following block of code is used to strip out diacritical marks from latin script
* and also convert to upper case. E.g. "j?mes" becomes "JAMES".
*
* See http://www.unicode.org/charts/PDF/U0300.pdf for the logic
* behind stripping 0300-036F
*
* See #454 for an issue where we were completely stripping non latin characters
* See #832 for an issue where we normalize korean characters, which are decomposed
*/
String string = Normalizer.normalize(theString, Normalizer.Form.NFD);
for (int i = 0, n = string.length(); i < n; ++i) {
char c = string.charAt(i);
if (c >= '\u0300' && c <= '\u036F') {
continue;
} else {
outBuffer.append(c);
}
}
return new String(outBuffer.toCharArray()).toUpperCase();
}
private static String parseNarrativeTextIntoWords(IBaseResource theResource) {
StringBuilder b = new StringBuilder();

View File

@ -25,10 +25,13 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.dao.r4.MatchResourceUrlService;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
@ -76,15 +79,11 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
protected IFulltextSearchSvc mySearchDao;
@Autowired
protected DaoConfig myDaoConfig;
@Autowired
private IResourceLinkDao myResourceLinkDao;
private String myResourceName;
private Class<T> myResourceType;
private String mySecondaryPrimaryKeyParamName;
@Autowired
private ISearchParamRegistry mySearchParamRegistry;
@Autowired
private MatchUrlService myMatchUrlService;
private MatchResourceUrlService myMatchResourceUrlService;
@Override
public void addTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, String theLabel) {
@ -271,7 +270,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
public DeleteMethodOutcome deleteByUrl(String theUrl, List<DeleteConflict> deleteConflicts, RequestDetails theRequest) {
StopWatch w = new StopWatch();
Set<Long> resource = myMatchUrlService.processMatchUrl(theUrl, myResourceType);
Set<Long> resource = myMatchResourceUrlService.processMatchUrl(theUrl, myResourceType);
if (resource.size() > 1) {
if (myDaoConfig.isAllowMultipleDelete() == false) {
throw new PreconditionFailedException(getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resource.size()));
@ -371,7 +370,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
entity.setResourceType(toResourceName(theResource));
if (isNotBlank(theIfNoneExist)) {
Set<Long> match = myMatchUrlService.processMatchUrl(theIfNoneExist, myResourceType);
Set<Long> match = myMatchResourceUrlService.processMatchUrl(theIfNoneExist, myResourceType);
if (match.size() > 1) {
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "CREATE", theIfNoneExist, match.size());
throw new PreconditionFailedException(msg);
@ -848,7 +847,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Override
public Set<Long> processMatchUrl(String theMatchUrl) {
return myMatchUrlService.processMatchUrl(theMatchUrl, getResourceType());
return myMatchResourceUrlService.processMatchUrl(theMatchUrl, getResourceType());
}
@Override
@ -1231,7 +1230,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
IIdType resourceId;
if (isNotBlank(theMatchUrl)) {
StopWatch sw = new StopWatch();
Set<Long> match = myMatchUrlService.processMatchUrl(theMatchUrl, myResourceType);
Set<Long> match = myMatchResourceUrlService.processMatchUrl(theMatchUrl, myResourceType);
if (match.size() > 1) {
String msg = getContext().getLocalizer().getMessage(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "UPDATE", theMatchUrl, match.size());
throw new PreconditionFailedException(msg);

View File

@ -1,7 +1,7 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptDao;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
@ -50,13 +50,6 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
@Autowired
@Qualifier("myResourceCountsCache")
public ResourceCountCache myResourceCountsCache;
private ReentrantLock myReindexLock = new ReentrantLock(false);
@Autowired
private ITermConceptDao myTermConceptDao;
@Autowired
private ISearchParamRegistry mySearchParamRegistry;
@Autowired
private PlatformTransactionManager myTxManager;
@Override
@Transactional(propagation = Propagation.NEVER)

View File

@ -1,7 +1,9 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.search.warm.WarmCacheEntry;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import com.google.common.collect.Sets;
@ -36,21 +38,6 @@ import java.util.*;
public class DaoConfig {
/**
* Default {@link #getTreatReferencesAsLogical() logical URL bases}. Includes the following
* values:
* <ul>
* <li><code>"http://hl7.org/fhir/valueset-*"</code></li>
* <li><code>"http://hl7.org/fhir/codesystem-*"</code></li>
* <li><code>"http://hl7.org/fhir/StructureDefinition/*"</code></li>
* </ul>
*/
public static final Set<String> DEFAULT_LOGICAL_BASE_URLS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
"http://hl7.org/fhir/ValueSet/*",
"http://hl7.org/fhir/CodeSystem/*",
"http://hl7.org/fhir/valueset-*",
"http://hl7.org/fhir/codesystem-*",
"http://hl7.org/fhir/StructureDefinition/*")));
/**
* Default value for {@link #setReuseCachedSearchResultsForMillis(Long)}: 60000ms (one minute)
*/
@ -86,24 +73,22 @@ public class DaoConfig {
)));
private static final Logger ourLog = LoggerFactory.getLogger(DaoConfig.class);
private IndexEnabledEnum myIndexMissingFieldsEnabled = IndexEnabledEnum.DISABLED;
/**
* Child Configurations
*/
private ModelConfig myModelConfig = new ModelConfig();
/**
* update setter javadoc if default changes
*/
private Long myTranslationCachesExpireAfterWriteInMinutes = DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES;
/**
* update setter javadoc if default changes
*/
private boolean myAllowExternalReferences = false;
/**
* update setter javadoc if default changes
*/
private boolean myAllowContainsSearches = false;
/**
* update setter javadoc if default changes
*/
private boolean myAllowInlineMatchUrlReferences = true;
private boolean myAllowMultipleDelete;
private boolean myDefaultSearchParamsCanBeOverridden = false;
/**
* update setter javadoc if default changes
*/
@ -141,8 +126,6 @@ public class DaoConfig {
private Long myReuseCachedSearchResultsForMillis = DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
private boolean mySchedulingDisabled;
private boolean mySuppressUpdatesWithNoChange = true;
private Set<String> myTreatBaseUrlsAsLocal = new HashSet<>();
private Set<String> myTreatReferencesAsLogical = new HashSet<>(DEFAULT_LOGICAL_BASE_URLS);
private boolean myAutoCreatePlaceholderReferenceTargets;
private Integer myCacheControlNoStoreMaxResultsUpperLimit = 1000;
private Integer myCountSearchResultsUpTo = null;
@ -224,12 +207,7 @@ public class DaoConfig {
* @see #setTreatReferencesAsLogical(Set)
*/
public void addTreatReferencesAsLogical(String theTreatReferencesAsLogical) {
validateTreatBaseUrlsAsLocal(theTreatReferencesAsLogical);
if (myTreatReferencesAsLogical == null) {
myTreatReferencesAsLogical = new HashSet<>();
}
myTreatReferencesAsLogical.add(theTreatReferencesAsLogical);
myModelConfig.addTreatReferencesAsLogical(theTreatReferencesAsLogical);
}
/**
@ -754,57 +732,6 @@ public class DaoConfig {
myTranslationCachesExpireAfterWriteInMinutes = translationCachesExpireAfterWriteInMinutes;
}
/**
* This setting may be used to advise the server that any references found in
* resources that have any of the base URLs given here will be replaced with
* simple local references.
* <p>
* For example, if the set contains the value <code>http://example.com/base/</code>
* and a resource is submitted to the server that contains a reference to
* <code>http://example.com/base/Patient/1</code>, the server will automatically
* convert this reference to <code>Patient/1</code>
* </p>
* <p>
* Note that this property has different behaviour from {@link DaoConfig#getTreatReferencesAsLogical()}
* </p>
*
* @see #getTreatReferencesAsLogical()
*/
public Set<String> getTreatBaseUrlsAsLocal() {
return myTreatBaseUrlsAsLocal;
}
/**
* This setting may be used to advise the server that any references found in
* resources that have any of the base URLs given here will be replaced with
* simple local references.
* <p>
* For example, if the set contains the value <code>http://example.com/base/</code>
* and a resource is submitted to the server that contains a reference to
* <code>http://example.com/base/Patient/1</code>, the server will automatically
* convert this reference to <code>Patient/1</code>
* </p>
*
* @param theTreatBaseUrlsAsLocal The set of base URLs. May be <code>null</code>, which
* means no references will be treated as external
*/
public void setTreatBaseUrlsAsLocal(Set<String> theTreatBaseUrlsAsLocal) {
if (theTreatBaseUrlsAsLocal != null) {
for (String next : theTreatBaseUrlsAsLocal) {
validateTreatBaseUrlsAsLocal(next);
}
}
HashSet<String> treatBaseUrlsAsLocal = new HashSet<String>();
for (String next : ObjectUtils.defaultIfNull(theTreatBaseUrlsAsLocal, new HashSet<String>())) {
while (next.endsWith("/")) {
next = next.substring(0, next.length() - 1);
}
treatBaseUrlsAsLocal.add(next);
}
myTreatBaseUrlsAsLocal = treatBaseUrlsAsLocal;
}
/**
* This setting may be used to advise the server that any references found in
* resources that have any of the base URLs given here will be treated as logical
@ -824,10 +751,10 @@ public class DaoConfig {
* <li><code>http://example.com/some-base*</code> <b>(will match anything beginning with the part before the *)</b></li>
* </ul>
*
* @see #DEFAULT_LOGICAL_BASE_URLS Default values for this property
* @see ModelConfig#DEFAULT_LOGICAL_BASE_URLS Default values for this property
*/
public Set<String> getTreatReferencesAsLogical() {
return myTreatReferencesAsLogical;
return myModelConfig.getTreatReferencesAsLogical();
}
/**
@ -849,49 +776,13 @@ public class DaoConfig {
* <li><code>http://example.com/some-base*</code> <b>(will match anything beginning with the part before the *)</b></li>
* </ul>
*
* @see #DEFAULT_LOGICAL_BASE_URLS Default values for this property
* @see ModelConfig#DEFAULT_LOGICAL_BASE_URLS Default values for this property
*/
public DaoConfig setTreatReferencesAsLogical(Set<String> theTreatReferencesAsLogical) {
myTreatReferencesAsLogical = theTreatReferencesAsLogical;
myModelConfig.setTreatReferencesAsLogical(theTreatReferencesAsLogical);
return this;
}
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
* <p>
* Default is <code>false</code> (Note that prior to HAPI FHIR
* 3.5.0 the default was <code>true</code>)
* </p>
* <p>
* Note: If you change this value after data already has
* already been stored in the database, you must for a reindexing
* of all data in the database or resources may not be
* searchable.
* </p>
*/
public boolean isAllowContainsSearches() {
return myAllowContainsSearches;
}
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
* <p>
* Default is <code>false</code> (Note that prior to HAPI FHIR
* 3.5.0 the default was <code>true</code>)
* </p>
* <p>
* Note: If you change this value after data already has
* already been stored in the database, you must for a reindexing
* of all data in the database or resources may not be
* searchable.
* </p>
*/
public void setAllowContainsSearches(boolean theAllowContainsSearches) {
this.myAllowContainsSearches = theAllowContainsSearches;
}
/**
* If set to <code>true</code> (default is <code>false</code>) the server will allow
* resources to have references to external servers. For example if this server is
@ -918,7 +809,7 @@ public class DaoConfig {
* @see #setAllowExternalReferences(boolean)
*/
public boolean isAllowExternalReferences() {
return myAllowExternalReferences;
return myModelConfig.isAllowExternalReferences();
}
/**
@ -947,7 +838,7 @@ public class DaoConfig {
* @see #setAllowExternalReferences(boolean)
*/
public void setAllowExternalReferences(boolean theAllowExternalReferences) {
myAllowExternalReferences = theAllowExternalReferences;
myModelConfig.setAllowExternalReferences(theAllowExternalReferences);
}
/**
@ -1024,38 +915,6 @@ public class DaoConfig {
myAutoCreatePlaceholderReferenceTargets = theAutoCreatePlaceholderReferenceTargets;
}
/**
* If set to {@code true} the default search params (i.e. the search parameters that are
* defined by the FHIR specification itself) may be overridden by uploading search
* parameters to the server with the same code as the built-in search parameter.
* <p>
* This can be useful if you want to be able to disable or alter
* the behaviour of the default search parameters.
* </p>
* <p>
* The default value for this setting is {@code false}
* </p>
*/
public boolean isDefaultSearchParamsCanBeOverridden() {
return myDefaultSearchParamsCanBeOverridden;
}
/**
* If set to {@code true} the default search params (i.e. the search parameters that are
* defined by the FHIR specification itself) may be overridden by uploading search
* parameters to the server with the same code as the built-in search parameter.
* <p>
* This can be useful if you want to be able to disable or alter
* the behaviour of the default search parameters.
* </p>
* <p>
* The default value for this setting is {@code false}
* </p>
*/
public void setDefaultSearchParamsCanBeOverridden(boolean theDefaultSearchParamsCanBeOverridden) {
myDefaultSearchParamsCanBeOverridden = theDefaultSearchParamsCanBeOverridden;
}
/**
* If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
* deleted even if other resources currently contain references to them.
@ -1273,7 +1132,7 @@ public class DaoConfig {
/**
* If set to <code>true</code> (default is <code>true</code>), indexes will be
* created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}.
* created for search parameters marked as {@link SearchParamConstants#EXT_SP_UNIQUE}.
* This is a HAPI FHIR specific extension which can be used to specify that no more than one
* resource can exist which matches a given criteria, using a database constraint to
* enforce this.
@ -1284,7 +1143,7 @@ public class DaoConfig {
/**
* If set to <code>true</code> (default is <code>true</code>), indexes will be
* created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}.
* created for search parameters marked as {@link SearchParamConstants#EXT_SP_UNIQUE}.
* This is a HAPI FHIR specific extension which can be used to specify that no more than one
* resource can exist which matches a given criteria, using a database constraint to
* enforce this.
@ -1493,6 +1352,117 @@ public class DaoConfig {
myEnableInMemorySubscriptionMatching = theEnableInMemorySubscriptionMatching;
}
public ModelConfig getModelConfig() {
return myModelConfig;
}
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
* <p>
* Default is <code>false</code> (Note that prior to HAPI FHIR
* 3.5.0 the default was <code>true</code>)
* </p>
* <p>
* Note: If you change this value after data already has
* already been stored in the database, you must for a reindexing
* of all data in the database or resources may not be
* searchable.
* </p>
*/
public boolean isAllowContainsSearches() {
return this.myModelConfig.isAllowContainsSearches();
}
/**
* If enabled, the server will support the use of :contains searches,
* which are helpful but can have adverse effects on performance.
* <p>
* Default is <code>false</code> (Note that prior to HAPI FHIR
* 3.5.0 the default was <code>true</code>)
* </p>
* <p>
* Note: If you change this value after data already has
* already been stored in the database, you must for a reindexing
* of all data in the database or resources may not be
* searchable.
* </p>
*/
public void setAllowContainsSearches(boolean theAllowContainsSearches) {
this.myModelConfig.setAllowContainsSearches(theAllowContainsSearches);
}
/**
* This setting may be used to advise the server that any references found in
* resources that have any of the base URLs given here will be replaced with
* simple local references.
* <p>
* For example, if the set contains the value <code>http://example.com/base/</code>
* and a resource is submitted to the server that contains a reference to
* <code>http://example.com/base/Patient/1</code>, the server will automatically
* convert this reference to <code>Patient/1</code>
* </p>
* <p>
* Note that this property has different behaviour from {@link DaoConfig#getTreatReferencesAsLogical()}
* </p>
*
* @see #getTreatReferencesAsLogical()
*/
public Set<String> getTreatBaseUrlsAsLocal() {
return myModelConfig.getTreatBaseUrlsAsLocal();
}
/**
* This setting may be used to advise the server that any references found in
* resources that have any of the base URLs given here will be replaced with
* simple local references.
* <p>
* For example, if the set contains the value <code>http://example.com/base/</code>
* and a resource is submitted to the server that contains a reference to
* <code>http://example.com/base/Patient/1</code>, the server will automatically
* convert this reference to <code>Patient/1</code>
* </p>
*
* @param theTreatBaseUrlsAsLocal The set of base URLs. May be <code>null</code>, which
* means no references will be treated as external
*/
public void setTreatBaseUrlsAsLocal(Set<String> theTreatBaseUrlsAsLocal) {
myModelConfig.setTreatBaseUrlsAsLocal(theTreatBaseUrlsAsLocal);
}
/**
* If set to {@code true} the default search params (i.e. the search parameters that are
* defined by the FHIR specification itself) may be overridden by uploading search
* parameters to the server with the same code as the built-in search parameter.
* <p>
* This can be useful if you want to be able to disable or alter
* the behaviour of the default search parameters.
* </p>
* <p>
* The default value for this setting is {@code false}
* </p>
*/
public boolean isDefaultSearchParamsCanBeOverridden() {
return myModelConfig.isDefaultSearchParamsCanBeOverridden();
}
/**
* If set to {@code true} the default search params (i.e. the search parameters that are
* defined by the FHIR specification itself) may be overridden by uploading search
* parameters to the server with the same code as the built-in search parameter.
* <p>
* This can be useful if you want to be able to disable or alter
* the behaviour of the default search parameters.
* </p>
* <p>
* The default value for this setting is {@code false}
* </p>
*/
public void setDefaultSearchParamsCanBeOverridden(boolean theDefaultSearchParamsCanBeOverridden) {
myModelConfig.setDefaultSearchParamsCanBeOverridden(theDefaultSearchParamsCanBeOverridden);
}
public enum IndexEnabledEnum {
ENABLED,
DISABLED
@ -1539,17 +1509,4 @@ public class DaoConfig {
*/
ANY
}
private static void validateTreatBaseUrlsAsLocal(String theUrl) {
Validate.notBlank(theUrl, "Base URL must not be null or empty");
int starIdx = theUrl.indexOf('*');
if (starIdx != -1) {
if (starIdx != theUrl.length() - 1) {
throw new IllegalArgumentException("Base URL wildcard character (*) can only appear at the end of the string: " + theUrl);
}
}
}
}

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao;
* #L%
*/
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.MethodOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -123,4 +124,8 @@ public class DaoRegistry implements ApplicationContextAware {
public void setResourceDaos(Collection<IFhirResourceDao> theResourceDaos) {
initializeMaps(theResourceDaos);
}
public IFhirResourceDao getSubscriptionDao() {
return getResourceDao(ResourceTypeEnum.SUBSCRIPTION.getCode());
}
}

View File

@ -0,0 +1,33 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.searchparam.registry.BaseSearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
public class DatabaseSearchParamProvider implements ISearchParamProvider {
@Autowired
private PlatformTransactionManager myTxManager;
@Autowired
private DaoRegistry myDaoRegistry;
@Override
public IBundleProvider search(SearchParameterMap theParams) {
return myDaoRegistry.getResourceDao(ResourceTypeEnum.SEARCHPARAMETER.getCode()).search(theParams);
}
@Override
public <SP extends IBaseResource> void refreshCache(BaseSearchParamRegistry<SP> theSearchParamRegistry, long theRefreshInterval) {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.execute(t->{
theSearchParamRegistry.doRefresh(theRefreshInterval);
return null;
});
}
}

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import java.util.List;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.MethodOutcome;
/**

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao;
* #L%
*/
import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
class EncodedResource {

View File

@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;

View File

@ -24,10 +24,11 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.rest.api.SortSpec;

View File

@ -24,10 +24,11 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.rest.api.*;

View File

@ -32,7 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.SearchParameter;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;

View File

@ -27,6 +27,7 @@ import java.util.*;
import javax.annotation.PostConstruct;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import org.apache.commons.codec.binary.StringUtils;
import org.hl7.fhir.instance.hapi.validation.CachingValidationSupport;
import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport;
@ -37,7 +38,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;

View File

@ -21,9 +21,10 @@ package ca.uhn.fhir.jpa.dao;
*/
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;

View File

@ -21,8 +21,9 @@ package ca.uhn.fhir.jpa.dao;
*/
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.StringParam;

View File

@ -1,10 +1,11 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.entity.IBaseResourceEntity;
import ca.uhn.fhir.jpa.entity.ResourceTag;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.jpa.model.entity.IBaseResourceEntity;
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import org.hl7.fhir.instance.model.api.IBaseResource;
import java.util.Collection;

View File

@ -21,9 +21,10 @@ package ca.uhn.fhir.jpa.dao;
*/
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.jpa.util.ExpungeOutcome;

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.dao;
import java.util.List;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
public interface IFulltextSearchSvc {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao;
*/
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.param.DateRangeParam;
import org.hl7.fhir.instance.model.api.IBaseResource;

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.TokenParam;

View File

@ -26,9 +26,16 @@ import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.dao.index.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.r4.MatchResourceUrlService;
import ca.uhn.fhir.jpa.entity.ResourceSearchView;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.util.StringNormalizer;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.jpa.util.BaseIterator;
@ -126,6 +133,8 @@ public class SearchBuilder implements ISearchBuilder {
@Autowired
private IHapiTerminologySvc myTerminologySvc;
@Autowired
private MatchResourceUrlService myMatchResourceUrlService;
@Autowired
private MatchUrlService myMatchUrlService;
@Autowired
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
@ -243,7 +252,7 @@ public class SearchBuilder implements ISearchBuilder {
}
Class<? extends IBaseResource> resourceType = targetResourceDefinition.getImplementingClass();
Set<Long> match = myMatchUrlService.processMatchUrl(matchUrl, resourceType);
Set<Long> match = myMatchResourceUrlService.processMatchUrl(matchUrl, resourceType);
if (match.isEmpty()) {
// Pick a PID that can never match
match = Collections.singleton(-1L);
@ -1201,7 +1210,7 @@ public class SearchBuilder implements ISearchBuilder {
}
if (myDontUseHashesForSearch) {
String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm);
String likeExpression = StringNormalizer.normalizeString(rawSearchTerm);
if (myDaoConfig.isAllowContainsSearches()) {
if (theParameter instanceof StringParam) {
if (((StringParam) theParameter).isContains()) {
@ -1237,7 +1246,7 @@ public class SearchBuilder implements ISearchBuilder {
// Normalized Match
String normalizedString = BaseHapiFhirDao.normalizeString(rawSearchTerm);
String normalizedString = StringNormalizer.normalizeString(rawSearchTerm);
String likeExpression;
if (theParameter instanceof StringParam &&
((StringParam) theParameter).isContains() &&
@ -1247,7 +1256,7 @@ public class SearchBuilder implements ISearchBuilder {
likeExpression = createLeftMatchLikeExpression(normalizedString);
}
Long hash = ResourceIndexedSearchParamString.calculateHashNormalized(myDaoConfig, theResourceName, theParamName, normalizedString);
Long hash = ResourceIndexedSearchParamString.calculateHashNormalized(myDaoConfig.getModelConfig(), theResourceName, theParamName, normalizedString);
Predicate hashCode = theBuilder.equal(theFrom.get("myHashNormalizedPrefix").as(Long.class), hash);
Predicate singleCode = theBuilder.like(theFrom.get("myValueNormalized").as(String.class), likeExpression);
return theBuilder.and(hashCode, singleCode);

View File

@ -22,8 +22,9 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.parser.DataFormatException;

View File

@ -27,7 +27,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ca.uhn.fhir.jpa.entity.ForcedId;
import ca.uhn.fhir.jpa.model.entity.ForcedId;
public interface IForcedIdDao extends JpaRepository<ForcedId, Long> {

View File

@ -12,7 +12,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.Temporal;
import org.springframework.data.repository.query.Param;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
/*
* #%L

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.dao.data;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTag;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
import org.springframework.data.jpa.repository.JpaRepository;
/*

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao.data;
* #L%
*/
import ca.uhn.fhir.jpa.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
public interface IResourceIndexedSearchParamCoordsDao extends JpaRepository<ResourceIndexedSearchParamCoords, Long> {
// nothing yet

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
public interface IResourceIndexedSearchParamDateDao extends JpaRepository<ResourceIndexedSearchParamDate, Long> {
// nothing yet

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
public interface IResourceIndexedSearchParamNumberDao extends JpaRepository<ResourceIndexedSearchParamNumber, Long> {
// nothing yet

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
public interface IResourceIndexedSearchParamQuantityDao extends JpaRepository<ResourceIndexedSearchParamQuantity, Long> {
// nothing yet

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao.data;
* #L%
*/
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

View File

@ -26,7 +26,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
public interface IResourceIndexedSearchParamUriDao extends JpaRepository<ResourceIndexedSearchParamUri, Long> {

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
public interface IResourceLinkDao extends JpaRepository<ResourceLink, Long> {

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.dao.data;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;

View File

@ -26,7 +26,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ca.uhn.fhir.jpa.entity.ResourceTag;
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
public interface IResourceTagDao extends JpaRepository<ResourceTag, Long> {
@Query("" +

View File

@ -27,8 +27,8 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SearchParamPresent;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.SearchParamPresent;
public interface ISearchParamPresentDao extends JpaRepository<SearchParamPresent, Long> {

View File

@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao.data;
* #L%
*/
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import org.springframework.data.jpa.repository.JpaRepository;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
public interface ITagDefinitionDao extends JpaRepository<TagDefinition, Long> {
// nothing

View File

@ -21,10 +21,10 @@ package ca.uhn.fhir.jpa.dao.dstu3;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept;

View File

@ -21,8 +21,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoComposition;
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -32,7 +31,6 @@ import ca.uhn.fhir.rest.param.StringParam;
import org.hl7.fhir.dstu3.model.Composition;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.term.TranslationMatch;
import ca.uhn.fhir.jpa.term.TranslationRequest;
import ca.uhn.fhir.jpa.term.TranslationResult;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;

View File

@ -37,7 +37,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;

View File

@ -29,8 +29,8 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoEncounter;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;

View File

@ -24,14 +24,14 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.SortSpec;

View File

@ -3,9 +3,9 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.hl7.fhir.dstu3.model.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -33,12 +33,6 @@ import java.util.List;
public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
@Autowired
private ISearchParamRegistry mySearchParamRegistry;
@Autowired
private IFhirSystemDao<Bundle, Meta> mySystemDao;
protected void markAffectedResources(SearchParameter theResource) {
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
String expression = theResource != null ? theResource.getExpression() : null;

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;

View File

@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.UriParam;

View File

@ -0,0 +1,89 @@
package ca.uhn.fhir.jpa.dao.index;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.IResourceLinkResolver;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
@Service
public class DatabaseResourceLinkResolver implements IResourceLinkResolver {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DatabaseResourceLinkResolver.class);
@Autowired
private DaoConfig myDaoConfig;
@Autowired
private FhirContext myContext;
@Autowired
private IdHelperService myIdHelperService;
@Autowired
private DaoRegistry myDaoRegistry;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
@Override
public ResourceTable findTargetResource(RuntimeSearchParam theNextSpDef, String theNextPathsUnsplit, IIdType theNextId, String theTypeString, Class<? extends IBaseResource> theType, String theId) {
ResourceTable target;
Long valueOf;
try {
valueOf = myIdHelperService.translateForcedIdToPid(theTypeString, theId);
} catch (ResourceNotFoundException e) {
if (myDaoConfig.isEnforceReferentialIntegrityOnWrite() == false) {
return null;
}
RuntimeResourceDefinition missingResourceDef = myContext.getResourceDefinition(theType);
String resName = missingResourceDef.getName();
if (myDaoConfig.isAutoCreatePlaceholderReferenceTargets()) {
IBaseResource newResource = missingResourceDef.newInstance();
newResource.setId(resName + "/" + theId);
IFhirResourceDao<IBaseResource> placeholderResourceDao = (IFhirResourceDao<IBaseResource>) myDaoRegistry.getResourceDao(newResource.getClass());
ourLog.debug("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue());
valueOf = placeholderResourceDao.update(newResource).getEntity().getId();
} else {
throw new InvalidRequestException("Resource " + resName + "/" + theId + " not found, specified in path: " + theNextPathsUnsplit);
}
}
target = myEntityManager.find(ResourceTable.class, valueOf);
RuntimeResourceDefinition targetResourceDef = myContext.getResourceDefinition(theType);
if (target == null) {
String resName = targetResourceDef.getName();
throw new InvalidRequestException("Resource " + resName + "/" + theId + " not found, specified in path: " + theNextPathsUnsplit);
}
if (!theTypeString.equals(target.getResourceType())) {
throw new UnprocessableEntityException(
"Resource contains reference to " + theNextId.getValue() + " but resource with ID " + theNextId.getIdPart() + " is actually of type " + target.getResourceType());
}
if (target.getDeleted() != null) {
String resName = targetResourceDef.getName();
throw new InvalidRequestException("Resource " + resName + "/" + theId + " is deleted, specified in path: " + theNextPathsUnsplit);
}
if (theNextSpDef.getTargets() != null && !theNextSpDef.getTargets().contains(theTypeString)) {
return null;
}
return target;
}
@Override
public void validateTypeOrThrowException(Class<? extends IBaseResource> theType) {
myDaoRegistry.getDaoOrThrowException(theType);
}
}

View File

@ -0,0 +1,115 @@
package ca.uhn.fhir.jpa.dao.index;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.ArrayList;
import java.util.Collection;
@Service
public class DatabaseSearchParamSynchronizer {
@Autowired
private DaoConfig myDaoConfig;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
public void synchronizeSearchParamsToDatabase(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
theParams.calculateHashes(theParams.stringParams);
for (ResourceIndexedSearchParamString next : synchronizeSearchParamsToDatabase(existingParams.stringParams, theParams.stringParams)) {
next.setModelConfig(myDaoConfig.getModelConfig());
myEntityManager.remove(next);
theEntity.getParamsString().remove(next);
}
for (ResourceIndexedSearchParamString next : synchronizeSearchParamsToDatabase(theParams.stringParams, existingParams.stringParams)) {
myEntityManager.persist(next);
}
theParams.calculateHashes(theParams.tokenParams);
for (ResourceIndexedSearchParamToken next : synchronizeSearchParamsToDatabase(existingParams.tokenParams, theParams.tokenParams)) {
myEntityManager.remove(next);
theEntity.getParamsToken().remove(next);
}
for (ResourceIndexedSearchParamToken next : synchronizeSearchParamsToDatabase(theParams.tokenParams, existingParams.tokenParams)) {
myEntityManager.persist(next);
}
theParams.calculateHashes(theParams.numberParams);
for (ResourceIndexedSearchParamNumber next : synchronizeSearchParamsToDatabase(existingParams.numberParams, theParams.numberParams)) {
myEntityManager.remove(next);
theEntity.getParamsNumber().remove(next);
}
for (ResourceIndexedSearchParamNumber next : synchronizeSearchParamsToDatabase(theParams.numberParams, existingParams.numberParams)) {
myEntityManager.persist(next);
}
theParams.calculateHashes(theParams.quantityParams);
for (ResourceIndexedSearchParamQuantity next : synchronizeSearchParamsToDatabase(existingParams.quantityParams, theParams.quantityParams)) {
myEntityManager.remove(next);
theEntity.getParamsQuantity().remove(next);
}
for (ResourceIndexedSearchParamQuantity next : synchronizeSearchParamsToDatabase(theParams.quantityParams, existingParams.quantityParams)) {
myEntityManager.persist(next);
}
// Store date SP's
theParams.calculateHashes(theParams.dateParams);
for (ResourceIndexedSearchParamDate next : synchronizeSearchParamsToDatabase(existingParams.dateParams, theParams.dateParams)) {
myEntityManager.remove(next);
theEntity.getParamsDate().remove(next);
}
for (ResourceIndexedSearchParamDate next : synchronizeSearchParamsToDatabase(theParams.dateParams, existingParams.dateParams)) {
myEntityManager.persist(next);
}
// Store URI SP's
theParams.calculateHashes(theParams.uriParams);
for (ResourceIndexedSearchParamUri next : synchronizeSearchParamsToDatabase(existingParams.uriParams, theParams.uriParams)) {
myEntityManager.remove(next);
theEntity.getParamsUri().remove(next);
}
for (ResourceIndexedSearchParamUri next : synchronizeSearchParamsToDatabase(theParams.uriParams, existingParams.uriParams)) {
myEntityManager.persist(next);
}
// Store Coords SP's
theParams.calculateHashes(theParams.coordsParams);
for (ResourceIndexedSearchParamCoords next : synchronizeSearchParamsToDatabase(existingParams.coordsParams, theParams.coordsParams)) {
myEntityManager.remove(next);
theEntity.getParamsCoords().remove(next);
}
for (ResourceIndexedSearchParamCoords next : synchronizeSearchParamsToDatabase(theParams.coordsParams, existingParams.coordsParams)) {
myEntityManager.persist(next);
}
// Store resource links
for (ResourceLink next : synchronizeSearchParamsToDatabase(existingParams.links, theParams.links)) {
myEntityManager.remove(next);
theEntity.getResourceLinks().remove(next);
}
for (ResourceLink next : synchronizeSearchParamsToDatabase(theParams.links, existingParams.links)) {
myEntityManager.persist(next);
}
// make sure links are indexed
theEntity.setResourceLinks(theParams.links);
}
public <T> Collection<T> synchronizeSearchParamsToDatabase(Collection<T> theInput, Collection<T> theToRemove) {
assert theInput != theToRemove;
if (theInput.isEmpty()) {
return theInput;
}
ArrayList<T> retVal = new ArrayList<>(theInput);
retVal.removeAll(theToRemove);
return retVal;
}
}

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.index;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.entity.ForcedId;
import ca.uhn.fhir.jpa.model.entity.ForcedId;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.apache.commons.lang3.Validate;

View File

@ -1,604 +0,0 @@
package ca.uhn.fhir.jpa.dao.index;
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.search.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.MatchUrlService;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@Service
@Lazy
public class SearchParamExtractorService {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorService.class);
@Autowired
private DaoConfig myDaoConfig;
@Autowired
private FhirContext myContext;
@Autowired
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
@Autowired
private ISearchParamRegistry mySearchParamRegistry;
@Autowired
private IdHelperService myIdHelperService;
@Autowired
private DaoRegistry myDaoRegistry;
@Autowired
private MatchUrlService myMatchUrlService;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
public void populateFromResource(ResourceIndexedSearchParams theParams, IDao theCallingDao, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams existingParams) {
extractFromResource(theParams, theEntity, theResource);
Set<Map.Entry<String, RuntimeSearchParam>> activeSearchParams = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).entrySet();
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {
theParams.findMissingSearchParams(myDaoConfig, theEntity, activeSearchParams);
}
theParams.setUpdatedTime(theUpdateTime);
extractInlineReferences(theResource);
extractResourceLinks(theParams, theEntity, theResource, theUpdateTime, true);
/*
* If the existing resource already has links and those match links we still want, use them instead of removing them and re adding them
*/
for (Iterator<ResourceLink> existingLinkIter = existingParams.getResourceLinks().iterator(); existingLinkIter.hasNext(); ) {
ResourceLink nextExisting = existingLinkIter.next();
if (theParams.links.remove(nextExisting)) {
existingLinkIter.remove();
theParams.links.add(nextExisting);
}
}
/*
* Handle composites
*/
extractCompositeStringUniques(theEntity, theParams);
}
public void extractFromResource(ResourceIndexedSearchParams theParams, ResourceTable theEntity, IBaseResource theResource) {
theParams.stringParams.addAll(extractSearchParamStrings(theEntity, theResource));
theParams.numberParams.addAll(extractSearchParamNumber(theEntity, theResource));
theParams.quantityParams.addAll(extractSearchParamQuantity(theEntity, theResource));
theParams.dateParams.addAll(extractSearchParamDates(theEntity, theResource));
theParams.uriParams.addAll(extractSearchParamUri(theEntity, theResource));
theParams.coordsParams.addAll(extractSearchParamCoords(theEntity, theResource));
ourLog.trace("Storing date indexes: {}", theParams.dateParams);
for (BaseResourceIndexedSearchParam next : extractSearchParamTokens(theEntity, theResource)) {
if (next instanceof ResourceIndexedSearchParamToken) {
theParams.tokenParams.add((ResourceIndexedSearchParamToken) next);
} else {
theParams.stringParams.add((ResourceIndexedSearchParamString) next);
}
}
}
/**
* Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the
* matching resource.
*/
public void extractInlineReferences(IBaseResource theResource) {
if (!myDaoConfig.isAllowInlineMatchUrlReferences()) {
return;
}
FhirTerser terser = myContext.newTerser();
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
for (IBaseReference nextRef : allRefs) {
IIdType nextId = nextRef.getReferenceElement();
String nextIdText = nextId.getValue();
if (nextIdText == null) {
continue;
}
int qmIndex = nextIdText.indexOf('?');
if (qmIndex != -1) {
for (int i = qmIndex - 1; i >= 0; i--) {
if (nextIdText.charAt(i) == '/') {
if (i < nextIdText.length() - 1 && nextIdText.charAt(i + 1) == '?') {
// Just in case the URL is in the form Patient/?foo=bar
continue;
}
nextIdText = nextIdText.substring(i + 1);
break;
}
}
String resourceTypeString = nextIdText.substring(0, nextIdText.indexOf('?')).replace("/", "");
RuntimeResourceDefinition matchResourceDef = myContext.getResourceDefinition(resourceTypeString);
if (matchResourceDef == null) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlInvalidResourceType", nextId.getValue(), resourceTypeString);
throw new InvalidRequestException(msg);
}
Class<? extends IBaseResource> matchResourceType = matchResourceDef.getImplementingClass();
Set<Long> matches = myMatchUrlService.processMatchUrl(nextIdText, matchResourceType);
if (matches.isEmpty()) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", nextId.getValue());
throw new ResourceNotFoundException(msg);
}
if (matches.size() > 1) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlMultipleMatches", nextId.getValue());
throw new PreconditionFailedException(msg);
}
Long next = matches.iterator().next();
String newId = myIdHelperService.translatePidIdToForcedId(resourceTypeString, next);
ourLog.debug("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId);
nextRef.setReference(newId);
}
}
}
protected Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamCoords(theEntity, theResource);
}
protected Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamDates(theEntity, theResource);
}
protected Set<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamNumber(theEntity, theResource);
}
protected Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamQuantity(theEntity, theResource);
}
protected Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamStrings(theEntity, theResource);
}
protected Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamTokens(theEntity, theResource);
}
protected Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamUri(theEntity, theResource);
}
private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) {
String resourceType = theEntity.getResourceType();
List<JpaRuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
for (JpaRuntimeSearchParam next : uniqueSearchParams) {
List<List<String>> partsChoices = new ArrayList<>();
for (RuntimeSearchParam nextCompositeOf : next.getCompositeOf()) {
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
Collection<ResourceLink> linksForCompositePart = null;
Collection<String> linksForCompositePartWantPaths = null;
switch (nextCompositeOf.getParamType()) {
case NUMBER:
paramsListForCompositePart = theParams.numberParams;
break;
case DATE:
paramsListForCompositePart = theParams.dateParams;
break;
case STRING:
paramsListForCompositePart = theParams.stringParams;
break;
case TOKEN:
paramsListForCompositePart = theParams.tokenParams;
break;
case REFERENCE:
linksForCompositePart = theParams.links;
linksForCompositePartWantPaths = new HashSet<>();
linksForCompositePartWantPaths.addAll(nextCompositeOf.getPathsSplit());
break;
case QUANTITY:
paramsListForCompositePart = theParams.quantityParams;
break;
case URI:
paramsListForCompositePart = theParams.uriParams;
break;
case COMPOSITE:
case HAS:
break;
}
ArrayList<String> nextChoicesList = new ArrayList<>();
partsChoices.add(nextChoicesList);
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
if (paramsListForCompositePart != null) {
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
if (isNotBlank(value)) {
value = UrlUtil.escapeUrlParam(value);
nextChoicesList.add(key + "=" + value);
}
}
}
}
if (linksForCompositePart != null) {
for (ResourceLink nextLink : linksForCompositePart) {
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
String value = nextLink.getTargetResource().getIdDt().toUnqualifiedVersionless().getValue();
if (isNotBlank(value)) {
value = UrlUtil.escapeUrlParam(value);
nextChoicesList.add(key + "=" + value);
}
}
}
}
}
Set<String> queryStringsToPopulate = theParams.extractCompositeStringUniquesValueChains(resourceType, partsChoices);
for (String nextQueryString : queryStringsToPopulate) {
if (isNotBlank(nextQueryString)) {
theParams.compositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString));
}
}
}
}
@SuppressWarnings("unchecked")
public void extractResourceLinks(ResourceIndexedSearchParams theParams, ResourceTable theEntity, IBaseResource theResource, Date theUpdateTime, boolean lookUpReferencesInDatabase) {
String resourceType = theEntity.getResourceType();
/*
* For now we don't try to load any of the links in a bundle if it's the actual bundle we're storing..
*/
if (theResource instanceof IBaseBundle) {
return;
}
Map<String, RuntimeSearchParam> searchParams = mySearchParamRegistry.getActiveSearchParams(toResourceName(theResource.getClass()));
for (RuntimeSearchParam nextSpDef : searchParams.values()) {
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.REFERENCE) {
continue;
}
String nextPathsUnsplit = nextSpDef.getPath();
if (isBlank(nextPathsUnsplit)) {
continue;
}
boolean multiType = false;
if (nextPathsUnsplit.endsWith("[x]")) {
multiType = true;
}
List<PathAndRef> refs = mySearchParamExtractor.extractResourceLinks(theResource, nextSpDef);
for (PathAndRef nextPathAndRef : refs) {
Object nextObject = nextPathAndRef.getRef();
/*
* A search parameter on an extension field that contains
* references should index those references
*/
if (nextObject instanceof IBaseExtension<?, ?>) {
nextObject = ((IBaseExtension<?, ?>) nextObject).getValue();
}
if (nextObject instanceof CanonicalType) {
nextObject = new Reference(((CanonicalType) nextObject).getValueAsString());
}
IIdType nextId;
if (nextObject instanceof IBaseReference) {
IBaseReference nextValue = (IBaseReference) nextObject;
if (nextValue.isEmpty()) {
continue;
}
nextId = nextValue.getReferenceElement();
/*
* This can only really happen if the DAO is being called
* programatically with a Bundle (not through the FHIR REST API)
* but Smile does this
*/
if (nextId.isEmpty() && nextValue.getResource() != null) {
nextId = nextValue.getResource().getIdElement();
}
if (nextId.isEmpty() || nextId.getValue().startsWith("#")) {
// This is a blank or contained resource reference
continue;
}
} else if (nextObject instanceof IBaseResource) {
nextId = ((IBaseResource) nextObject).getIdElement();
if (nextId == null || nextId.hasIdPart() == false) {
continue;
}
} else if (myContext.getElementDefinition((Class<? extends IBase>) nextObject.getClass()).getName().equals("uri")) {
continue;
} else if (resourceType.equals("Consent") && nextPathAndRef.getPath().equals("Consent.source")) {
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
continue;
} else {
if (!multiType) {
if (nextSpDef.getName().equals("sourceuri")) {
continue; // TODO: disable this eventually - ConceptMap:sourceuri is of type reference but points to a URI
}
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
} else {
continue;
}
}
theParams.populatedResourceLinkParameters.add(nextSpDef.getName());
if (LogicalReferenceHelper.isLogicalReference(myDaoConfig, nextId)) {
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime);
if (theParams.links.add(resourceLink)) {
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
}
continue;
}
String baseUrl = nextId.getBaseUrl();
String typeString = nextId.getResourceType();
if (isBlank(typeString)) {
throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Does not contain resource type - " + nextId.getValue());
}
RuntimeResourceDefinition resourceDefinition;
try {
resourceDefinition = myContext.getResourceDefinition(typeString);
} catch (DataFormatException e) {
throw new InvalidRequestException(
"Invalid resource reference found at path[" + nextPathsUnsplit + "] - Resource type is unknown or not supported on this server - " + nextId.getValue());
}
if (isNotBlank(baseUrl)) {
if (!myDaoConfig.getTreatBaseUrlsAsLocal().contains(baseUrl) && !myDaoConfig.isAllowExternalReferences()) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "externalReferenceNotAllowed", nextId.getValue());
throw new InvalidRequestException(msg);
} else {
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, nextId, theUpdateTime);
if (theParams.links.add(resourceLink)) {
ourLog.debug("Indexing remote resource reference URL: {}", nextId);
}
continue;
}
}
Class<? extends IBaseResource> type = resourceDefinition.getImplementingClass();
String id = nextId.getIdPart();
if (StringUtils.isBlank(id)) {
throw new InvalidRequestException("Invalid resource reference found at path[" + nextPathsUnsplit + "] - Does not contain resource ID - " + nextId.getValue());
}
myDaoRegistry.getDaoOrThrowException(type);
ResourceTable target;
if (lookUpReferencesInDatabase) {
Long valueOf;
try {
valueOf = myIdHelperService.translateForcedIdToPid(typeString, id);
} catch (ResourceNotFoundException e) {
if (myDaoConfig.isEnforceReferentialIntegrityOnWrite() == false) {
continue;
}
RuntimeResourceDefinition missingResourceDef = myContext.getResourceDefinition(type);
String resName = missingResourceDef.getName();
if (myDaoConfig.isAutoCreatePlaceholderReferenceTargets()) {
IBaseResource newResource = missingResourceDef.newInstance();
newResource.setId(resName + "/" + id);
IFhirResourceDao<IBaseResource> placeholderResourceDao = (IFhirResourceDao<IBaseResource>) myDaoRegistry.getResourceDao(newResource.getClass());
ourLog.debug("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue());
valueOf = placeholderResourceDao.update(newResource).getEntity().getId();
} else {
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit);
}
}
target = myEntityManager.find(ResourceTable.class, valueOf);
RuntimeResourceDefinition targetResourceDef = myContext.getResourceDefinition(type);
if (target == null) {
String resName = targetResourceDef.getName();
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit);
}
if (!typeString.equals(target.getResourceType())) {
throw new UnprocessableEntityException(
"Resource contains reference to " + nextId.getValue() + " but resource with ID " + nextId.getIdPart() + " is actually of type " + target.getResourceType());
}
if (target.getDeleted() != null) {
String resName = targetResourceDef.getName();
throw new InvalidRequestException("Resource " + resName + "/" + id + " is deleted, specified in path: " + nextPathsUnsplit);
}
if (nextSpDef.getTargets() != null && !nextSpDef.getTargets().contains(typeString)) {
continue;
}
} else {
target = new ResourceTable();
target.setResourceType(typeString);
if (nextId.isIdPartValidLong()) {
target.setId(nextId.getIdPartAsLong());
} else {
ForcedId forcedId = new ForcedId();
forcedId.setForcedId(id);
target.setForcedId(forcedId);
}
}
ResourceLink resourceLink = new ResourceLink(nextPathAndRef.getPath(), theEntity, target, theUpdateTime);
theParams.links.add(resourceLink);
}
}
theEntity.setHasLinks(theParams.links.size() > 0);
}
public String toResourceName(Class<? extends IBaseResource> theResourceType) {
return myContext.getResourceDefinition(theResourceType).getName();
}
public void removeCommon(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
theParams.calculateHashes(theParams.stringParams);
for (ResourceIndexedSearchParamString next : removeCommon(existingParams.stringParams, theParams.stringParams)) {
next.setDaoConfig(myDaoConfig);
myEntityManager.remove(next);
theEntity.getParamsString().remove(next);
}
for (ResourceIndexedSearchParamString next : removeCommon(theParams.stringParams, existingParams.stringParams)) {
myEntityManager.persist(next);
}
theParams.calculateHashes(theParams.tokenParams);
for (ResourceIndexedSearchParamToken next : removeCommon(existingParams.tokenParams, theParams.tokenParams)) {
myEntityManager.remove(next);
theEntity.getParamsToken().remove(next);
}
for (ResourceIndexedSearchParamToken next : removeCommon(theParams.tokenParams, existingParams.tokenParams)) {
myEntityManager.persist(next);
}
theParams.calculateHashes(theParams.numberParams);
for (ResourceIndexedSearchParamNumber next : removeCommon(existingParams.numberParams, theParams.numberParams)) {
myEntityManager.remove(next);
theEntity.getParamsNumber().remove(next);
}
for (ResourceIndexedSearchParamNumber next : removeCommon(theParams.numberParams, existingParams.numberParams)) {
myEntityManager.persist(next);
}
theParams.calculateHashes(theParams.quantityParams);
for (ResourceIndexedSearchParamQuantity next : removeCommon(existingParams.quantityParams, theParams.quantityParams)) {
myEntityManager.remove(next);
theEntity.getParamsQuantity().remove(next);
}
for (ResourceIndexedSearchParamQuantity next : removeCommon(theParams.quantityParams, existingParams.quantityParams)) {
myEntityManager.persist(next);
}
// Store date SP's
theParams.calculateHashes(theParams.dateParams);
for (ResourceIndexedSearchParamDate next : removeCommon(existingParams.dateParams, theParams.dateParams)) {
myEntityManager.remove(next);
theEntity.getParamsDate().remove(next);
}
for (ResourceIndexedSearchParamDate next : removeCommon(theParams.dateParams, existingParams.dateParams)) {
myEntityManager.persist(next);
}
// Store URI SP's
theParams.calculateHashes(theParams.uriParams);
for (ResourceIndexedSearchParamUri next : removeCommon(existingParams.uriParams, theParams.uriParams)) {
myEntityManager.remove(next);
theEntity.getParamsUri().remove(next);
}
for (ResourceIndexedSearchParamUri next : removeCommon(theParams.uriParams, existingParams.uriParams)) {
myEntityManager.persist(next);
}
// Store Coords SP's
theParams.calculateHashes(theParams.coordsParams);
for (ResourceIndexedSearchParamCoords next : removeCommon(existingParams.coordsParams, theParams.coordsParams)) {
myEntityManager.remove(next);
theEntity.getParamsCoords().remove(next);
}
for (ResourceIndexedSearchParamCoords next : removeCommon(theParams.coordsParams, existingParams.coordsParams)) {
myEntityManager.persist(next);
}
// Store resource links
for (ResourceLink next : removeCommon(existingParams.links, theParams.links)) {
myEntityManager.remove(next);
theEntity.getResourceLinks().remove(next);
}
for (ResourceLink next : removeCommon(theParams.links, existingParams.links)) {
myEntityManager.persist(next);
}
// make sure links are indexed
theEntity.setResourceLinks(theParams.links);
// Store composite string uniques
if (myDaoConfig.isUniqueIndexesEnabled()) {
for (ResourceIndexedCompositeStringUnique next : removeCommon(existingParams.compositeStringUniques, theParams.compositeStringUniques)) {
ourLog.debug("Removing unique index: {}", next);
myEntityManager.remove(next);
theEntity.getParamsCompositeStringUnique().remove(next);
}
for (ResourceIndexedCompositeStringUnique next : removeCommon(theParams.compositeStringUniques, existingParams.compositeStringUniques)) {
if (myDaoConfig.isUniqueIndexesCheckedBeforeSave()) {
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
if (existing != null) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "uniqueIndexConflictFailure", theEntity.getResourceType(), next.getIndexString(), existing.getResource().getIdDt().toUnqualifiedVersionless().getValue());
throw new PreconditionFailedException(msg);
}
}
ourLog.debug("Persisting unique index: {}", next);
myEntityManager.persist(next);
}
}
}
private <T> Collection<T> removeCommon(Collection<T> theInput, Collection<T> theToRemove) {
assert theInput != theToRemove;
if (theInput.isEmpty()) {
return theInput;
}
ArrayList<T> retVal = new ArrayList<>(theInput);
retVal.removeAll(theToRemove);
return retVal;
}
}

View File

@ -0,0 +1,259 @@
package ca.uhn.fhir.jpa.dao.index;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
import ca.uhn.fhir.jpa.dao.r4.MatchResourceUrlService;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceLinkExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@Service
@Lazy
public class SearchParamWithInlineReferencesExtractor {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamWithInlineReferencesExtractor.class);
@Autowired
private MatchResourceUrlService myMatchResourceUrlService;
@Autowired
private DaoConfig myDaoConfig;
@Autowired
private FhirContext myContext;
@Autowired
private IdHelperService myIdHelperService;
@Autowired
private ISearchParamRegistry mySearchParamRegistry;
@Autowired
SearchParamExtractorService mySearchParamExtractorService;
@Autowired
ResourceLinkExtractor myResourceLinkExtractor;
@Autowired
DatabaseResourceLinkResolver myDatabaseResourceLinkResolver;
@Autowired
DatabaseSearchParamSynchronizer myDatabaseSearchParamSynchronizer;
@Autowired
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager;
public void populateFromResource(ResourceIndexedSearchParams theParams, IDao theCallingDao, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams existingParams) {
mySearchParamExtractorService.extractFromResource(theParams, theEntity, theResource);
Set<Map.Entry<String, RuntimeSearchParam>> activeSearchParams = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).entrySet();
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {
theParams.findMissingSearchParams(myDaoConfig.getModelConfig(), theEntity, activeSearchParams);
}
theParams.setUpdatedTime(theUpdateTime);
extractInlineReferences(theResource);
myResourceLinkExtractor.extractResourceLinks(theParams, theEntity, theResource, theUpdateTime, myDatabaseResourceLinkResolver);
/*
* If the existing resource already has links and those match links we still want, use them instead of removing them and re adding them
*/
for (Iterator<ResourceLink> existingLinkIter = existingParams.getResourceLinks().iterator(); existingLinkIter.hasNext(); ) {
ResourceLink nextExisting = existingLinkIter.next();
if (theParams.links.remove(nextExisting)) {
existingLinkIter.remove();
theParams.links.add(nextExisting);
}
}
/*
* Handle composites
*/
extractCompositeStringUniques(theEntity, theParams);
}
private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) {
final String resourceType = theEntity.getResourceType();
List<JpaRuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
for (JpaRuntimeSearchParam next : uniqueSearchParams) {
List<List<String>> partsChoices = new ArrayList<>();
for (RuntimeSearchParam nextCompositeOf : next.getCompositeOf()) {
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
Collection<ResourceLink> linksForCompositePart = null;
Collection<String> linksForCompositePartWantPaths = null;
switch (nextCompositeOf.getParamType()) {
case NUMBER:
paramsListForCompositePart = theParams.numberParams;
break;
case DATE:
paramsListForCompositePart = theParams.dateParams;
break;
case STRING:
paramsListForCompositePart = theParams.stringParams;
break;
case TOKEN:
paramsListForCompositePart = theParams.tokenParams;
break;
case REFERENCE:
linksForCompositePart = theParams.links;
linksForCompositePartWantPaths = new HashSet<>();
linksForCompositePartWantPaths.addAll(nextCompositeOf.getPathsSplit());
break;
case QUANTITY:
paramsListForCompositePart = theParams.quantityParams;
break;
case URI:
paramsListForCompositePart = theParams.uriParams;
break;
case COMPOSITE:
case HAS:
break;
}
ArrayList<String> nextChoicesList = new ArrayList<>();
partsChoices.add(nextChoicesList);
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
if (paramsListForCompositePart != null) {
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
if (isNotBlank(value)) {
value = UrlUtil.escapeUrlParam(value);
nextChoicesList.add(key + "=" + value);
}
}
}
}
if (linksForCompositePart != null) {
for (ResourceLink nextLink : linksForCompositePart) {
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
String value = nextLink.getTargetResource().getIdDt().toUnqualifiedVersionless().getValue();
if (isNotBlank(value)) {
value = UrlUtil.escapeUrlParam(value);
nextChoicesList.add(key + "=" + value);
}
}
}
}
}
Set<String> queryStringsToPopulate = theParams.extractCompositeStringUniquesValueChains(resourceType, partsChoices);
for (String nextQueryString : queryStringsToPopulate) {
if (isNotBlank(nextQueryString)) {
theParams.compositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString));
}
}
}
}
/**
* Handle references within the resource that are match URLs, for example references like "Patient?identifier=foo". These match URLs are resolved and replaced with the ID of the
* matching resource.
*/
public void extractInlineReferences(IBaseResource theResource) {
if (!myDaoConfig.isAllowInlineMatchUrlReferences()) {
return;
}
FhirTerser terser = myContext.newTerser();
List<IBaseReference> allRefs = terser.getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
for (IBaseReference nextRef : allRefs) {
IIdType nextId = nextRef.getReferenceElement();
String nextIdText = nextId.getValue();
if (nextIdText == null) {
continue;
}
int qmIndex = nextIdText.indexOf('?');
if (qmIndex != -1) {
for (int i = qmIndex - 1; i >= 0; i--) {
if (nextIdText.charAt(i) == '/') {
if (i < nextIdText.length() - 1 && nextIdText.charAt(i + 1) == '?') {
// Just in case the URL is in the form Patient/?foo=bar
continue;
}
nextIdText = nextIdText.substring(i + 1);
break;
}
}
String resourceTypeString = nextIdText.substring(0, nextIdText.indexOf('?')).replace("/", "");
RuntimeResourceDefinition matchResourceDef = myContext.getResourceDefinition(resourceTypeString);
if (matchResourceDef == null) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlInvalidResourceType", nextId.getValue(), resourceTypeString);
throw new InvalidRequestException(msg);
}
Class<? extends IBaseResource> matchResourceType = matchResourceDef.getImplementingClass();
Set<Long> matches = myMatchResourceUrlService.processMatchUrl(nextIdText, matchResourceType);
if (matches.isEmpty()) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", nextId.getValue());
throw new ResourceNotFoundException(msg);
}
if (matches.size() > 1) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlMultipleMatches", nextId.getValue());
throw new PreconditionFailedException(msg);
}
Long next = matches.iterator().next();
String newId = myIdHelperService.translatePidIdToForcedId(resourceTypeString, next);
ourLog.debug("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId);
nextRef.setReference(newId);
}
}
}
public void storeCompositeStringUniques(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
// Store composite string uniques
if (myDaoConfig.isUniqueIndexesEnabled()) {
for (ResourceIndexedCompositeStringUnique next : myDatabaseSearchParamSynchronizer.synchronizeSearchParamsToDatabase(existingParams.compositeStringUniques, theParams.compositeStringUniques)) {
ourLog.debug("Removing unique index: {}", next);
myEntityManager.remove(next);
theEntity.getParamsCompositeStringUnique().remove(next);
}
for (ResourceIndexedCompositeStringUnique next : myDatabaseSearchParamSynchronizer.synchronizeSearchParamsToDatabase(theParams.compositeStringUniques, existingParams.compositeStringUniques)) {
if (myDaoConfig.isUniqueIndexesCheckedBeforeSave()) {
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
if (existing != null) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "uniqueIndexConflictFailure", theEntity.getResourceType(), next.getIndexString(), existing.getResource().getIdDt().toUnqualifiedVersionless().getValue());
throw new PreconditionFailedException(msg);
}
}
ourLog.debug("Persisting unique index: {}", next);
myEntityManager.persist(next);
}
}
}
}

View File

@ -21,10 +21,10 @@ package ca.uhn.fhir.jpa.dao.r4;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept;

View File

@ -21,8 +21,7 @@ package ca.uhn.fhir.jpa.dao.r4;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoComposition;
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -32,7 +31,6 @@ import ca.uhn.fhir.rest.param.StringParam;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.Composition;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;

View File

@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.dao.r4;
*/
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;

View File

@ -29,8 +29,8 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoEncounter;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;

View File

@ -24,14 +24,14 @@ import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.SortSpec;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;

View File

@ -2,11 +2,11 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ElementUtil;

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum;

View File

@ -22,7 +22,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;

View File

@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.UriParam;

View File

@ -0,0 +1,45 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class MatchResourceUrlService {
@Autowired
private DaoRegistry myDaoRegistry;
@Autowired
private FhirContext myContext;
@Autowired
private MatchUrlService myMatchUrlService;
public <R extends IBaseResource> Set<Long> processMatchUrl(String theMatchUrl, Class<R> theResourceType) {
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceType);
SearchParameterMap paramMap = myMatchUrlService.translateMatchUrl(theMatchUrl, resourceDef);
paramMap.setLoadSynchronous(true);
if (paramMap.isEmpty() && paramMap.getLastUpdated() == null) {
throw new InvalidRequestException("Invalid match URL[" + theMatchUrl + "] - URL has no search parameters");
}
IFhirResourceDao<R> dao = myDaoRegistry.getResourceDao(theResourceType);
if (dao == null) {
throw new InternalErrorException("No DAO for resource type: " + theResourceType.getName());
}
return dao.searchForIds(paramMap);
}
}

View File

@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.entity;
*/
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.model.entity.IBaseResourceEntity;
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.api.Constants;

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.entity;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.param.DateRangeParam;
import org.apache.commons.lang3.SerializationUtils;

View File

@ -20,6 +20,8 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import java.io.Serializable;
import javax.persistence.Column;

View File

@ -20,6 +20,8 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import javax.persistence.*;
import java.util.Date;

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.util.CoverageIgnore;
import javax.persistence.*;

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.entity;
* #L%
*/
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

View File

@ -24,8 +24,8 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.subscription.ISubscriptionTriggeringSvc;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
@ -65,7 +66,7 @@ public class SubscriptionTriggeringProvider implements IResourceProvider {
@Override
public Class<? extends IBaseResource> getResourceType() {
return myFhirContext.getResourceDefinition("Subscription").getImplementingClass();
return myFhirContext.getResourceDefinition(ResourceTypeEnum.SUBSCRIPTION.getCode()).getImplementingClass();
}
}

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.ExtensionConstants;

View File

@ -23,7 +23,7 @@ import java.util.*;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.CapabilityStatement.*;
import org.hl7.fhir.r4.model.Enumerations.SearchParamType;

View File

@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.search;
*/
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.server.IBundleProvider;

View File

@ -24,8 +24,8 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.model.primitive.InstantDt;

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.dao.data.ISearchDao;
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.Constants;

View File

@ -29,9 +29,9 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.data.IResourceReindexJobDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.ForcedId;
import ca.uhn.fhir.jpa.model.entity.ForcedId;
import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.util.StopWatch;

Some files were not shown because too many files have changed in this diff Show More