Merge remote-tracking branch 'remotes/origin/master' into ks-flyway

This commit is contained in:
Ken Stevens 2019-11-20 14:32:19 -05:00
commit 6a55e1a8cb
127 changed files with 3300 additions and 2859 deletions

View File

@ -0,0 +1,43 @@
package example;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import java.io.FileReader;
public class ValidateSimple {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateSimple.class);
public static void main(String[] args) throws Exception {
FhirContext ctx = FhirContext.forR4();
// Create a validator module
FhirInstanceValidator instanceValidator = new FhirInstanceValidator();
// We'll create a validation chain with only the DefaultProfileValidationupport registered
ValidationSupportChain validationSupportChain = new ValidationSupportChain();
validationSupportChain.addValidationSupport(new DefaultProfileValidationSupport());
instanceValidator.setValidationSupport(validationSupportChain);
// Create a validator and register the InstanceValidator module
FhirValidator val = ctx.newValidator();
val.registerValidatorModule(instanceValidator);
// Read in the file and validate it
String nextFile = args[0];
try (FileReader fileReader = new FileReader(nextFile)) {
String input = IOUtils.toString(fileReader);
ValidationResult result = val.validateWithResult(input);
IBaseOperationOutcome oo = result.toOperationOutcome();
ourLog.info("Result:\n{}", ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(oo));
}
}
}

View File

@ -1,19 +1,27 @@
package ca.uhn.fhir.context; package ca.uhn.fhir.context;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import static org.apache.commons.lang3.StringUtils.trim;
import java.util.*;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim;
/* /*
* #%L * #%L
@ -44,61 +52,22 @@ public class RuntimeSearchParam {
private final RestSearchParameterTypeEnum myParamType; private final RestSearchParameterTypeEnum myParamType;
private final String myPath; private final String myPath;
private final Set<String> myTargets; private final Set<String> myTargets;
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("base", myBase)
.append("name", myName)
.append("path", myPath)
.append("id", myId)
.append("uri", myUri)
.toString();
}
private final Set<String> myProvidesMembershipInCompartments; private final Set<String> myProvidesMembershipInCompartments;
private final RuntimeSearchParamStatusEnum myStatus; private final RuntimeSearchParamStatusEnum myStatus;
private final String myUri; private final String myUri;
private final Map<String, List<IBaseExtension<?, ?>>> myExtensions = new HashMap<>();
public IIdType getId() { /**
return myId; * Constructor
} */
public String getUri() {
return myUri;
}
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf, public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) { Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
this(theId, theUri, theName, theDescription, thePath, theParamType, theCompositeOf, theProvidesMembershipInCompartments, theTargets, theStatus, null); this(theId, theUri, theName, theDescription, thePath, theParamType, theCompositeOf, theProvidesMembershipInCompartments, theTargets, theStatus, null);
} }
@Override /**
public boolean equals(Object theO) { * Constructor
if (this == theO) return true; */
if (theO == null || getClass() != theO.getClass()) return false;
RuntimeSearchParam that = (RuntimeSearchParam) theO;
return new EqualsBuilder()
.append(getId(), that.getId())
.append(getName(), that.getName())
.append(getPath(), that.getPath())
.append(getUri(), that.getUri())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getId())
.append(getName())
.append(getPath())
.append(getUri())
.toHashCode();
}
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf, public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) { Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) {
super(); super();
@ -136,6 +105,77 @@ public class RuntimeSearchParam {
} }
} }
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
this(null, null, theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments, theTargets, theStatus);
}
/**
* Retrieve user data - This can be used to store any application-specific data
*
* @return
*/
public List<IBaseExtension<?, ?>> getExtensions(String theKey) {
List<IBaseExtension<?, ?>> retVal = myExtensions.get(theKey);
if (retVal != null) {
retVal = Collections.unmodifiableList(retVal);
}
return retVal;
}
/**
* Sets user data - This can be used to store any application-specific data
*/
public RuntimeSearchParam addExtension(String theKey, IBaseExtension theValue) {
List<IBaseExtension<?, ?>> valuesList = myExtensions.computeIfAbsent(theKey, k -> new ArrayList<>());
valuesList.add(theValue);
return this;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("base", myBase)
.append("name", myName)
.append("path", myPath)
.append("id", myId)
.append("uri", myUri)
.toString();
}
public IIdType getId() {
return myId;
}
public String getUri() {
return myUri;
}
@Override
public boolean equals(Object theO) {
if (this == theO) return true;
if (theO == null || getClass() != theO.getClass()) return false;
RuntimeSearchParam that = (RuntimeSearchParam) theO;
return new EqualsBuilder()
.append(getId(), that.getId())
.append(getName(), that.getName())
.append(getPath(), that.getPath())
.append(getUri(), that.getUri())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getId())
.append(getName())
.append(getPath())
.append(getUri())
.toHashCode();
}
public Set<String> getBase() { public Set<String> getBase() {
return myBase; return myBase;
} }
@ -153,10 +193,6 @@ public class RuntimeSearchParam {
return myStatus; return myStatus;
} }
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
this(null, null, theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments, theTargets, theStatus);
}
public List<RuntimeSearchParam> getCompositeOf() { public List<RuntimeSearchParam> getCompositeOf() {
return myCompositeOf; return myCompositeOf;
} }
@ -206,5 +242,5 @@ public class RuntimeSearchParam {
RETIRED, RETIRED,
UNKNOWN UNKNOWN
} }
} }

View File

@ -118,11 +118,10 @@ public class ReflectionUtil {
/** /**
* Instantiate a class by no-arg constructor, throw {@link ConfigurationException} if we fail to do so * Instantiate a class by no-arg constructor, throw {@link ConfigurationException} if we fail to do so
*/ */
@CoverageIgnore
public static <T> T newInstance(Class<T> theType) { public static <T> T newInstance(Class<T> theType) {
Validate.notNull(theType, "theType must not be null"); Validate.notNull(theType, "theType must not be null");
try { try {
return theType.newInstance(); return theType.getConstructor().newInstance();
} catch (Exception e) { } catch (Exception e) {
throw new ConfigurationException("Failed to instantiate " + theType.getName(), e); throw new ConfigurationException("Failed to instantiate " + theType.getName(), e);
} }

View File

@ -25,6 +25,7 @@ import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IResultIterator; import ca.uhn.fhir.jpa.dao.IResultIterator;
import ca.uhn.fhir.jpa.dao.ISearchBuilder; import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.IBulkExportCollectionDao; import ca.uhn.fhir.jpa.dao.data.IBulkExportCollectionDao;
import ca.uhn.fhir.jpa.dao.data.IBulkExportCollectionFileDao; import ca.uhn.fhir.jpa.dao.data.IBulkExportCollectionFileDao;
import ca.uhn.fhir.jpa.dao.data.IBulkExportJobDao; import ca.uhn.fhir.jpa.dao.data.IBulkExportJobDao;
@ -251,7 +252,7 @@ public class BulkDataExportSvcImpl implements IBulkDataExportSvc {
OutputStreamWriter writer = new OutputStreamWriter(outputStream, Constants.CHARSET_UTF8); OutputStreamWriter writer = new OutputStreamWriter(outputStream, Constants.CHARSET_UTF8);
IParser parser = myContext.newJsonParser().setPrettyPrint(false); IParser parser = myContext.newJsonParser().setPrettyPrint(false);
List<Long> pidsSpool = new ArrayList<>(); List<ResourcePersistentId> pidsSpool = new ArrayList<>();
List<IBaseResource> resourcesSpool = new ArrayList<>(); List<IBaseResource> resourcesSpool = new ArrayList<>();
while (query.hasNext()) { while (query.hasNext()) {
pidsSpool.add(query.next()); pidsSpool.add(query.next());

View File

@ -10,6 +10,7 @@ import ca.uhn.fhir.jpa.bulk.BulkDataExportProvider;
import ca.uhn.fhir.jpa.bulk.BulkDataExportSvcImpl; import ca.uhn.fhir.jpa.bulk.BulkDataExportSvcImpl;
import ca.uhn.fhir.jpa.bulk.IBulkDataExportSvc; import ca.uhn.fhir.jpa.bulk.IBulkDataExportSvc;
import ca.uhn.fhir.jpa.dao.DaoRegistry; import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.delete.DeleteConflictService;
import ca.uhn.fhir.jpa.graphql.JpaStorageServices; import ca.uhn.fhir.jpa.graphql.JpaStorageServices;
import ca.uhn.fhir.jpa.interceptor.JpaConsentContextServices; import ca.uhn.fhir.jpa.interceptor.JpaConsentContextServices;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
@ -26,6 +27,8 @@ import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl; import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingInterceptor; import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingInterceptor;
import ca.uhn.fhir.jpa.subscription.dbmatcher.CompositeInMemoryDaoSubscriptionMatcher; import ca.uhn.fhir.jpa.subscription.dbmatcher.CompositeInMemoryDaoSubscriptionMatcher;
import ca.uhn.fhir.jpa.subscription.dbmatcher.DaoSubscriptionMatcher; import ca.uhn.fhir.jpa.subscription.dbmatcher.DaoSubscriptionMatcher;
@ -129,6 +132,12 @@ public abstract class BaseConfig {
return b; return b;
} }
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryImpl();
}
@Bean(name = "mySubscriptionTriggeringProvider") @Bean(name = "mySubscriptionTriggeringProvider")
@Lazy @Lazy
public SubscriptionTriggeringProvider subscriptionTriggeringProvider() { public SubscriptionTriggeringProvider subscriptionTriggeringProvider() {

View File

@ -5,16 +5,11 @@ import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu2; 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.TermReadSvcDstu2; import ca.uhn.fhir.jpa.term.TermReadSvcDstu2;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcDstu2;
import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.validation.IInstanceValidatorModule; import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidatorModule;
import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.instance.hapi.validation.CachingValidationSupport; import org.hl7.fhir.instance.hapi.validation.CachingValidationSupport;
import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport; import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport;
@ -117,11 +112,6 @@ public class BaseDstu2Config extends BaseConfig {
return new SearchParamExtractorDstu2(); return new SearchParamExtractorDstu2();
} }
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryDstu2();
}
@Bean(name = "mySystemDaoDstu2", autowire = Autowire.BY_NAME) @Bean(name = "mySystemDaoDstu2", autowire = Autowire.BY_NAME)
public IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDaoDstu2() { public IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDaoDstu2() {
ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2(); ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2();

View File

@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.config.dstu3;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ParserOptions; import ca.uhn.fhir.context.ParserOptions;
import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus; import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
@ -11,24 +10,20 @@ import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.dstu3.TransactionProcessorVersionAdapterDstu3; import ca.uhn.fhir.jpa.dao.dstu3.TransactionProcessorVersionAdapterDstu3;
import ca.uhn.fhir.jpa.provider.GraphQLProvider; import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3; 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.TermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl; import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcDstu3; import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcDstu3;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc; import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc; import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
import ca.uhn.fhir.validation.IInstanceValidatorModule; import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidatorModule;
import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.dstu3.hapi.ctx.DefaultProfileValidationSupport; import org.hl7.fhir.dstu3.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport; import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.CachingValidationSupport; import org.hl7.fhir.dstu3.hapi.validation.CachingValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator; import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.r5.utils.IResourceValidator; import org.hl7.fhir.r5.utils.IResourceValidator;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -95,8 +90,8 @@ public class BaseDstu3Config extends BaseConfigDstu3Plus {
} }
@Bean @Bean
public TransactionProcessor<Bundle, Bundle.BundleEntryComponent> transactionProcessor() { public TransactionProcessor transactionProcessor() {
return new TransactionProcessor<>(); return new TransactionProcessor();
} }
@Bean(name = "myInstanceValidatorDstu3") @Bean(name = "myInstanceValidatorDstu3")
@ -140,11 +135,6 @@ public class BaseDstu3Config extends BaseConfigDstu3Plus {
return new SearchParamExtractorDstu3(); return new SearchParamExtractorDstu3();
} }
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryDstu3();
}
@Bean(name = "mySystemDaoDstu3") @Bean(name = "mySystemDaoDstu3")
public IFhirSystemDao<org.hl7.fhir.dstu3.model.Bundle, org.hl7.fhir.dstu3.model.Meta> systemDaoDstu3() { public IFhirSystemDao<org.hl7.fhir.dstu3.model.Bundle, org.hl7.fhir.dstu3.model.Meta> systemDaoDstu3() {
return new ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3(); return new ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3();

View File

@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.config.r4;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.ParserOptions; import ca.uhn.fhir.context.ParserOptions;
import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus; import ca.uhn.fhir.jpa.config.BaseConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl; import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
@ -11,22 +10,20 @@ import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4; import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4;
import ca.uhn.fhir.jpa.provider.GraphQLProvider; import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryR4; import ca.uhn.fhir.jpa.term.TermReadSvcR4;
import ca.uhn.fhir.jpa.term.*; import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR4;
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc; import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4; import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc; import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
import ca.uhn.fhir.validation.IInstanceValidatorModule; import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidatorModule;
import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport; import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport; import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.hapi.validation.CachingValidationSupport; import org.hl7.fhir.r4.hapi.validation.CachingValidationSupport;
import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator; import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r5.utils.IResourceValidator; import org.hl7.fhir.r5.utils.IResourceValidator;
import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -88,8 +85,8 @@ public class BaseR4Config extends BaseConfigDstu3Plus {
} }
@Bean @Bean
public TransactionProcessor<Bundle, Bundle.BundleEntryComponent> transactionProcessor() { public TransactionProcessor transactionProcessor() {
return new TransactionProcessor<>(); return new TransactionProcessor();
} }
@Bean(name = GRAPHQL_PROVIDER_NAME) @Bean(name = GRAPHQL_PROVIDER_NAME)
@ -142,11 +139,6 @@ public class BaseR4Config extends BaseConfigDstu3Plus {
return new SearchParamExtractorR4(); return new SearchParamExtractorR4();
} }
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryR4();
}
@Bean(name = "mySystemDaoR4", autowire = Autowire.BY_NAME) @Bean(name = "mySystemDaoR4", autowire = Autowire.BY_NAME)
public IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDaoR4() { public IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDaoR4() {
ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4 retVal = new ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4(); ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4 retVal = new ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4();

View File

@ -10,8 +10,6 @@ import ca.uhn.fhir.jpa.dao.TransactionProcessor;
import ca.uhn.fhir.jpa.dao.r5.TransactionProcessorVersionAdapterR5; import ca.uhn.fhir.jpa.dao.r5.TransactionProcessorVersionAdapterR5;
import ca.uhn.fhir.jpa.provider.GraphQLProvider; import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR5; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR5;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryR5;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl; import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcR5; import ca.uhn.fhir.jpa.term.TermReadSvcR5;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR5; import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR5;
@ -88,8 +86,8 @@ public class BaseR5Config extends BaseConfigDstu3Plus {
} }
@Bean @Bean
public TransactionProcessor<Bundle, Bundle.BundleEntryComponent> transactionProcessor() { public TransactionProcessor transactionProcessor() {
return new TransactionProcessor<>(); return new TransactionProcessor();
} }
@Bean(name = GRAPHQL_PROVIDER_NAME) @Bean(name = GRAPHQL_PROVIDER_NAME)
@ -142,11 +140,6 @@ public class BaseR5Config extends BaseConfigDstu3Plus {
return new SearchParamExtractorR5(); return new SearchParamExtractorR5();
} }
@Bean
public ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryR5();
}
@Bean(name = "mySystemDaoR5", autowire = Autowire.BY_NAME) @Bean(name = "mySystemDaoR5", autowire = Autowire.BY_NAME)
public IFhirSystemDao<Bundle, org.hl7.fhir.r5.model.Meta> systemDaoR5() { public IFhirSystemDao<Bundle, org.hl7.fhir.r5.model.Meta> systemDaoR5() {
ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoR5 retVal = new ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoR5(); ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoR5 retVal = new ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoR5();

View File

@ -1,10 +1,21 @@
package ca.uhn.fhir.jpa.dao; package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.dao.data.*; import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
import ca.uhn.fhir.jpa.dao.data.IResourceProvenanceDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
import ca.uhn.fhir.jpa.dao.expunge.ExpungeService; import ca.uhn.fhir.jpa.dao.expunge.ExpungeService;
import ca.uhn.fhir.jpa.dao.index.DaoSearchParamSynchronizer; import ca.uhn.fhir.jpa.dao.index.DaoSearchParamSynchronizer;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
@ -13,6 +24,7 @@ import ca.uhn.fhir.jpa.delete.DeleteConflictService;
import ca.uhn.fhir.jpa.entity.ResourceSearchView; import ca.uhn.fhir.jpa.entity.ResourceSearchView;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum; import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
@ -74,7 +86,11 @@ import org.springframework.transaction.support.TransactionSynchronizationAdapter
import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.persistence.*; import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
@ -83,7 +99,12 @@ import javax.xml.stream.events.XMLEvent;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import static org.apache.commons.lang3.StringUtils.*; import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.trim;
/* /*
* #%L * #%L
@ -107,7 +128,7 @@ import static org.apache.commons.lang3.StringUtils.*;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@Repository @Repository
public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao, IJpaDao<T>, ApplicationContextAware { public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStorageDao implements IDao, IJpaDao<T>, ApplicationContextAware {
public static final long INDEX_STATUS_INDEXED = 1L; public static final long INDEX_STATUS_INDEXED = 1L;
public static final long INDEX_STATUS_INDEXING_FAILED = 2L; public static final long INDEX_STATUS_INDEXING_FAILED = 2L;
@ -168,6 +189,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
private FhirContext myContext; private FhirContext myContext;
private ApplicationContext myApplicationContext; private ApplicationContext myApplicationContext;
@Override
protected IInterceptorBroadcaster getInterceptorBroadcaster() {
return myInterceptorBroadcaster;
}
protected ApplicationContext getApplicationContext() { protected ApplicationContext getApplicationContext() {
return myApplicationContext; return myApplicationContext;
} }
@ -290,6 +316,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
return retVal; return retVal;
} }
@Override
protected DaoConfig getConfig() { protected DaoConfig getConfig() {
return myConfig; return myConfig;
} }
@ -925,34 +952,36 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, final IBaseResource theResource, ResourceTable public ResourceTable updateEntity(RequestDetails theRequest, final IBaseResource theResource, IBasePersistedResource
theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
Validate.notNull(theEntity); Validate.notNull(theEntity);
Validate.isTrue(theDeletedTimestampOrNull != null || theResource != null, "Must have either a resource[%s] or a deleted timestamp[%s] for resource PID[%s]", theDeletedTimestampOrNull != null, theResource != null, theEntity.getId()); Validate.isTrue(theDeletedTimestampOrNull != null || theResource != null, "Must have either a resource[%s] or a deleted timestamp[%s] for resource PID[%s]", theDeletedTimestampOrNull != null, theResource != null, theEntity.getPersistentId());
ourLog.debug("Starting entity update"); ourLog.debug("Starting entity update");
ResourceTable entity = (ResourceTable) theEntity;
/* /*
* This should be the very first thing.. * This should be the very first thing..
*/ */
if (theResource != null) { if (theResource != null) {
if (thePerformIndexing) { if (thePerformIndexing) {
if (!ourValidationDisabledForUnitTest) { if (!ourValidationDisabledForUnitTest) {
validateResourceForStorage((T) theResource, theEntity); validateResourceForStorage((T) theResource, entity);
} }
} }
String resourceType = myContext.getResourceDefinition(theResource).getName(); String resourceType = myContext.getResourceDefinition(theResource).getName();
if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) { if (isNotBlank(entity.getResourceType()) && !entity.getResourceType().equals(resourceType)) {
throw new UnprocessableEntityException( throw new UnprocessableEntityException(
"Existing resource ID[" + theEntity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + theEntity.getResourceType() + "] - Cannot update with [" + resourceType + "]"); "Existing resource ID[" + entity.getIdDt().toUnqualifiedVersionless() + "] is of type[" + entity.getResourceType() + "] - Cannot update with [" + resourceType + "]");
} }
} }
if (theEntity.getPublished() == null) { if (entity.getPublished() == null) {
ourLog.debug("Entity has published time: {}", new InstantDt(theUpdateTime)); ourLog.debug("Entity has published time: {}", new InstantDt(theUpdateTime));
theEntity.setPublished(theUpdateTime); entity.setPublished(theUpdateTime);
} }
ResourceIndexedSearchParams existingParams = null; ResourceIndexedSearchParams existingParams = null;
@ -963,89 +992,89 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
if (theDeletedTimestampOrNull != null) { if (theDeletedTimestampOrNull != null) {
// DELETE // DELETE
theEntity.setDeleted(theDeletedTimestampOrNull); entity.setDeleted(theDeletedTimestampOrNull);
theEntity.setUpdated(theDeletedTimestampOrNull); entity.setUpdated(theDeletedTimestampOrNull);
theEntity.setNarrativeTextParsedIntoWords(null); entity.setNarrativeTextParsedIntoWords(null);
theEntity.setContentTextParsedIntoWords(null); entity.setContentTextParsedIntoWords(null);
theEntity.setHashSha256(null); entity.setHashSha256(null);
theEntity.setIndexStatus(INDEX_STATUS_INDEXED); entity.setIndexStatus(INDEX_STATUS_INDEXED);
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true); changed = populateResourceIntoEntity(theRequest, theResource, entity, true);
} else { } else {
// CREATE or UPDATE // CREATE or UPDATE
existingParams = new ResourceIndexedSearchParams(theEntity); existingParams = new ResourceIndexedSearchParams(entity);
theEntity.setDeleted(null); entity.setDeleted(null);
if (thePerformIndexing) { if (thePerformIndexing) {
newParams = new ResourceIndexedSearchParams(); newParams = new ResourceIndexedSearchParams();
mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, theUpdateTime, theEntity, theResource, existingParams, theRequest); mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, theUpdateTime, entity, theResource, existingParams, theRequest);
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true); changed = populateResourceIntoEntity(theRequest, theResource, entity, true);
if (changed.isChanged()) { if (changed.isChanged()) {
theEntity.setUpdated(theUpdateTime); entity.setUpdated(theUpdateTime);
if (theResource instanceof IResource) { if (theResource instanceof IResource) {
theEntity.setLanguage(((IResource) theResource).getLanguage().getValue()); entity.setLanguage(((IResource) theResource).getLanguage().getValue());
} else { } else {
theEntity.setLanguage(((IAnyResource) theResource).getLanguageElement().getValue()); entity.setLanguage(((IAnyResource) theResource).getLanguageElement().getValue());
} }
newParams.setParamsOn(theEntity); newParams.setParamsOn(entity);
theEntity.setIndexStatus(INDEX_STATUS_INDEXED); entity.setIndexStatus(INDEX_STATUS_INDEXED);
populateFullTextFields(myContext, theResource, theEntity); populateFullTextFields(myContext, theResource, entity);
} }
} else { } else {
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, false); changed = populateResourceIntoEntity(theRequest, theResource, entity, false);
theEntity.setUpdated(theUpdateTime); entity.setUpdated(theUpdateTime);
theEntity.setIndexStatus(null); entity.setIndexStatus(null);
} }
} }
if (!changed.isChanged() && !theForceUpdate && myConfig.isSuppressUpdatesWithNoChange()) { if (!changed.isChanged() && !theForceUpdate && myConfig.isSuppressUpdatesWithNoChange()) {
ourLog.debug("Resource {} has not changed", theEntity.getIdDt().toUnqualified().getValue()); ourLog.debug("Resource {} has not changed", entity.getIdDt().toUnqualified().getValue());
if (theResource != null) { if (theResource != null) {
updateResourceMetadata(theEntity, theResource); updateResourceMetadata(entity, theResource);
} }
theEntity.setUnchangedInCurrentOperation(true); entity.setUnchangedInCurrentOperation(true);
return theEntity; return entity;
} }
if (theUpdateVersion) { if (theUpdateVersion) {
theEntity.setVersion(theEntity.getVersion() + 1); entity.setVersion(entity.getVersion() + 1);
} }
/* /*
* Save the resource itself * Save the resource itself
*/ */
if (theEntity.getId() == null) { if (entity.getId() == null) {
myEntityManager.persist(theEntity); myEntityManager.persist(entity);
if (theEntity.getForcedId() != null) { if (entity.getForcedId() != null) {
myEntityManager.persist(theEntity.getForcedId()); myEntityManager.persist(entity.getForcedId());
} }
postPersist(theEntity, (T) theResource); postPersist(entity, (T) theResource);
} else if (theEntity.getDeleted() != null) { } else if (entity.getDeleted() != null) {
theEntity = myEntityManager.merge(theEntity); entity = myEntityManager.merge(entity);
postDelete(theEntity); postDelete(entity);
} else { } else {
theEntity = myEntityManager.merge(theEntity); entity = myEntityManager.merge(entity);
postUpdate(theEntity, (T) theResource); postUpdate(entity, (T) theResource);
} }
/* /*
* Create history entry * Create history entry
*/ */
if (theCreateNewHistoryEntry) { if (theCreateNewHistoryEntry) {
final ResourceHistoryTable historyEntry = theEntity.toHistory(); final ResourceHistoryTable historyEntry = entity.toHistory();
historyEntry.setEncoding(changed.getEncoding()); historyEntry.setEncoding(changed.getEncoding());
historyEntry.setResource(changed.getResource()); historyEntry.setResource(changed.getResource());
@ -1076,7 +1105,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
if (haveSource || haveRequestId) { if (haveSource || haveRequestId) {
ResourceHistoryProvenanceEntity provenance = new ResourceHistoryProvenanceEntity(); ResourceHistoryProvenanceEntity provenance = new ResourceHistoryProvenanceEntity();
provenance.setResourceHistoryTable(historyEntry); provenance.setResourceHistoryTable(historyEntry);
provenance.setResourceTable(theEntity); provenance.setResourceTable(entity);
if (haveRequestId) { if (haveRequestId) {
provenance.setRequestId(left(requestId, Constants.REQUEST_ID_LENGTH)); provenance.setRequestId(left(requestId, Constants.REQUEST_ID_LENGTH));
} }
@ -1102,7 +1131,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
for (String nextKey : newParams.getPopulatedResourceLinkParameters()) { for (String nextKey : newParams.getPopulatedResourceLinkParameters()) {
presentSearchParams.put(nextKey, Boolean.TRUE); presentSearchParams.put(nextKey, Boolean.TRUE);
} }
Set<Entry<String, RuntimeSearchParam>> activeSearchParams = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).entrySet(); Set<Entry<String, RuntimeSearchParam>> activeSearchParams = mySearchParamRegistry.getActiveSearchParams(entity.getResourceType()).entrySet();
for (Entry<String, RuntimeSearchParam> nextSpEntry : activeSearchParams) { for (Entry<String, RuntimeSearchParam> nextSpEntry : activeSearchParams) {
if (nextSpEntry.getValue().getParamType() == RestSearchParameterTypeEnum.REFERENCE) { if (nextSpEntry.getValue().getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
if (!presentSearchParams.containsKey(nextSpEntry.getKey())) { if (!presentSearchParams.containsKey(nextSpEntry.getKey())) {
@ -1110,13 +1139,13 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
} }
} }
} }
AddRemoveCount presenceCount = mySearchParamPresenceSvc.updatePresence(theEntity, presentSearchParams); AddRemoveCount presenceCount = mySearchParamPresenceSvc.updatePresence(entity, presentSearchParams);
// Interceptor broadcast: JPA_PERFTRACE_INFO // Interceptor broadcast: JPA_PERFTRACE_INFO
if (!presenceCount.isEmpty()) { if (!presenceCount.isEmpty()) {
if (JpaInterceptorBroadcaster.hasHooks(Pointcut.JPA_PERFTRACE_INFO, myInterceptorBroadcaster, theRequest)) { if (JpaInterceptorBroadcaster.hasHooks(Pointcut.JPA_PERFTRACE_INFO, myInterceptorBroadcaster, theRequest)) {
StorageProcessingMessage message = new StorageProcessingMessage(); StorageProcessingMessage message = new StorageProcessingMessage();
message.setMessage("For " + theEntity.getIdDt().toUnqualifiedVersionless().getValue() + " added " + presenceCount.getAddCount() + " and removed " + presenceCount.getRemoveCount() + " resource search parameter presence entries"); message.setMessage("For " + entity.getIdDt().toUnqualifiedVersionless().getValue() + " added " + presenceCount.getAddCount() + " and removed " + presenceCount.getRemoveCount() + " resource search parameter presence entries");
HookParams params = new HookParams() HookParams params = new HookParams()
.add(RequestDetails.class, theRequest) .add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest) .addIfMatchesType(ServletRequestDetails.class, theRequest)
@ -1132,17 +1161,17 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
*/ */
if (thePerformIndexing) { if (thePerformIndexing) {
if (newParams == null) { if (newParams == null) {
myExpungeService.deleteAllSearchParams(theEntity.getId()); myExpungeService.deleteAllSearchParams(entity.getId());
} else { } else {
// Synchronize search param indexes // Synchronize search param indexes
AddRemoveCount searchParamAddRemoveCount = myDaoSearchParamSynchronizer.synchronizeSearchParamsToDatabase(newParams, theEntity, existingParams); AddRemoveCount searchParamAddRemoveCount = myDaoSearchParamSynchronizer.synchronizeSearchParamsToDatabase(newParams, entity, existingParams);
// Interceptor broadcast: JPA_PERFTRACE_INFO // Interceptor broadcast: JPA_PERFTRACE_INFO
if (!searchParamAddRemoveCount.isEmpty()) { if (!searchParamAddRemoveCount.isEmpty()) {
if (JpaInterceptorBroadcaster.hasHooks(Pointcut.JPA_PERFTRACE_INFO, myInterceptorBroadcaster, theRequest)) { if (JpaInterceptorBroadcaster.hasHooks(Pointcut.JPA_PERFTRACE_INFO, myInterceptorBroadcaster, theRequest)) {
StorageProcessingMessage message = new StorageProcessingMessage(); StorageProcessingMessage message = new StorageProcessingMessage();
message.setMessage("For " + theEntity.getIdDt().toUnqualifiedVersionless().getValue() + " added " + searchParamAddRemoveCount.getAddCount() + " and removed " + searchParamAddRemoveCount.getRemoveCount() + " resource search parameter index entries"); message.setMessage("For " + entity.getIdDt().toUnqualifiedVersionless().getValue() + " added " + searchParamAddRemoveCount.getAddCount() + " and removed " + searchParamAddRemoveCount.getRemoveCount() + " resource search parameter index entries");
HookParams params = new HookParams() HookParams params = new HookParams()
.add(RequestDetails.class, theRequest) .add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest) .addIfMatchesType(ServletRequestDetails.class, theRequest)
@ -1152,25 +1181,27 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
} }
// Syncrhonize composite params // Syncrhonize composite params
mySearchParamWithInlineReferencesExtractor.storeCompositeStringUniques(newParams, theEntity, existingParams); mySearchParamWithInlineReferencesExtractor.storeCompositeStringUniques(newParams, entity, existingParams);
} }
} }
if (theResource != null) { if (theResource != null) {
updateResourceMetadata(theEntity, theResource); updateResourceMetadata(entity, theResource);
} }
return theEntity; return entity;
} }
@Override @Override
public ResourceTable updateInternal(RequestDetails theRequestDetails, T theResource, boolean thePerformIndexing, boolean theForceUpdateVersion, public ResourceTable updateInternal(RequestDetails theRequestDetails, T theResource, boolean thePerformIndexing, boolean theForceUpdateVersion,
ResourceTable theEntity, IIdType theResourceId, IBaseResource theOldResource) { IBasePersistedResource theEntity2, IIdType theResourceId, IBaseResource theOldResource) {
ResourceTable entity = (ResourceTable) theEntity2;
// We'll update the resource ID with the correct version later but for // We'll update the resource ID with the correct version later but for
// now at least set it to something useful for the interceptors // now at least set it to something useful for the interceptors
theResource.setId(theEntity.getIdDt()); theResource.setId(entity.getIdDt());
// Notify interceptors // Notify interceptors
ActionRequestDetails requestDetails; ActionRequestDetails requestDetails;
@ -1188,7 +1219,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
doCallHooks(theRequestDetails, Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED, hookParams); doCallHooks(theRequestDetails, Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED, hookParams);
// Perform update // Perform update
ResourceTable savedEntity = updateEntity(theRequestDetails, theResource, theEntity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing); ResourceTable savedEntity = updateEntity(theRequestDetails, theResource, entity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
/* /*
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction), * If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
@ -1226,18 +1257,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
return savedEntity; return savedEntity;
} }
protected void addPidToResource(ResourceTable theEntity, IBaseResource theResource) { protected void addPidToResource(IBasePersistedResource theEntity, IBaseResource theResource) {
if (theResource instanceof IAnyResource) { if (theResource instanceof IAnyResource) {
IDao.RESOURCE_PID.put((IAnyResource) theResource, theEntity.getId()); IDao.RESOURCE_PID.put((IAnyResource) theResource, theEntity.getPersistentId().getIdAsLong());
} else if (theResource instanceof IResource) { } else if (theResource instanceof IResource) {
IDao.RESOURCE_PID.put((IResource) theResource, theEntity.getId()); IDao.RESOURCE_PID.put((IResource) theResource, theEntity.getPersistentId().getIdAsLong());
} }
} }
protected void doCallHooks(RequestDetails theRequestDetails, Pointcut thePointcut, HookParams theParams) {
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequestDetails, thePointcut, theParams);
}
protected void updateResourceMetadata(IBaseResourceEntity theEntity, IBaseResource theResource) { protected void updateResourceMetadata(IBaseResourceEntity theEntity, IBaseResource theResource) {
IIdType id = theEntity.getIdDt(); IIdType id = theEntity.getIdDt();
if (getContext().getVersion().getVersion().isRi()) { if (getContext().getVersion().getVersion().isRi()) {

View File

@ -26,7 +26,15 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.delete.DeleteConflictList; import ca.uhn.fhir.jpa.delete.DeleteConflictList;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.delete.DeleteConflictService;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.jpa.model.entity.BaseTag;
import ca.uhn.fhir.jpa.model.entity.ForcedId;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider; import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
@ -40,22 +48,50 @@ import ca.uhn.fhir.jpa.util.xmlpatch.XmlPatchUtils;
import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.*; import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.server.*; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
import ca.uhn.fhir.rest.param.ParameterUtil; import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.param.QualifierDetails; import ca.uhn.fhir.rest.param.QualifierDetails;
import ca.uhn.fhir.rest.server.exceptions.*; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.rest.server.method.SearchMethodBinding; import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.*; import ca.uhn.fhir.util.ObjectUtil;
import ca.uhn.fhir.validation.*; import ca.uhn.fhir.util.OperationOutcomeUtil;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.IInstanceValidatorModule;
import ca.uhn.fhir.validation.IValidationContext;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.ValidationOptions;
import ca.uhn.fhir.validation.ValidationResult;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*; import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.r4.model.InstantType; import org.hl7.fhir.instance.model.api.IBaseMetaType;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
@ -64,12 +100,10 @@ import org.springframework.transaction.support.TransactionSynchronizationAdapter
import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
@ -168,24 +202,10 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return create(theResource, theIfNoneExist, true, new Date(), theRequestDetails); return create(theResource, theIfNoneExist, true, new Date(), theRequestDetails);
} }
public IBaseOperationOutcome createErrorOperationOutcome(String theMessage, String theCode) {
return createOperationOutcome(OO_SEVERITY_ERROR, theMessage, theCode);
}
public IBaseOperationOutcome createInfoOperationOutcome(String theMessage) {
return createOperationOutcome(OO_SEVERITY_INFO, theMessage, "informational");
}
private IInstanceValidatorModule getInstanceValidator() { private IInstanceValidatorModule getInstanceValidator() {
return myInstanceValidator; return myInstanceValidator;
} }
private IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
OperationOutcomeUtil.addIssue(getContext(), oo, theSeverity, theMessage, null, theCode);
return oo;
}
@Override @Override
public DaoMethodOutcome delete(IIdType theId) { public DaoMethodOutcome delete(IIdType theId) {
return delete(theId, null); return delete(theId, null);
@ -281,7 +301,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
DaoMethodOutcome retVal = delete(theId, deleteConflicts, theRequestDetails); DaoMethodOutcome retVal = delete(theId, deleteConflicts, theRequestDetails);
myDeleteConflictService.validateDeleteConflictsEmptyOrThrowException(deleteConflicts); DeleteConflictService.validateDeleteConflictsEmptyOrThrowException(getContext(), deleteConflicts);
ourLog.debug("Processed delete on {} in {}ms", theId.getValue(), w.getMillisAndRestart()); ourLog.debug("Processed delete on {} in {}ms", theId.getValue(), w.getMillisAndRestart());
return retVal; return retVal;
@ -295,7 +315,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
public DeleteMethodOutcome deleteByUrl(String theUrl, DeleteConflictList deleteConflicts, RequestDetails theRequest) { public DeleteMethodOutcome deleteByUrl(String theUrl, DeleteConflictList deleteConflicts, RequestDetails theRequest) {
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
Set<Long> resourceIds = myMatchResourceUrlService.processMatchUrl(theUrl, myResourceType, theRequest); Set<ResourcePersistentId> resourceIds = myMatchResourceUrlService.processMatchUrl(theUrl, myResourceType, theRequest);
if (resourceIds.size() > 1) { if (resourceIds.size() > 1) {
if (myDaoConfig.isAllowMultipleDelete() == false) { if (myDaoConfig.isAllowMultipleDelete() == false) {
throw new PreconditionFailedException(getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resourceIds.size())); throw new PreconditionFailedException(getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "DELETE", theUrl, resourceIds.size()));
@ -303,8 +323,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
List<ResourceTable> deletedResources = new ArrayList<>(); List<ResourceTable> deletedResources = new ArrayList<>();
for (Long pid : resourceIds) { for (ResourcePersistentId pid : resourceIds) {
ResourceTable entity = myEntityManager.find(ResourceTable.class, pid); ResourceTable entity = myEntityManager.find(ResourceTable.class, pid.getId());
deletedResources.add(entity); deletedResources.add(entity);
T resourceToDelete = toResource(myResourceType, entity, null, false); T resourceToDelete = toResource(myResourceType, entity, null, false);
@ -372,7 +392,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
DeleteMethodOutcome outcome = deleteByUrl(theUrl, deleteConflicts, theRequestDetails); DeleteMethodOutcome outcome = deleteByUrl(theUrl, deleteConflicts, theRequestDetails);
myDeleteConflictService.validateDeleteConflictsEmptyOrThrowException(deleteConflicts); DeleteConflictService.validateDeleteConflictsEmptyOrThrowException(getContext(), deleteConflicts);
return outcome; return outcome;
} }
@ -399,13 +419,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
entity.setResourceType(toResourceName(theResource)); entity.setResourceType(toResourceName(theResource));
if (isNotBlank(theIfNoneExist)) { if (isNotBlank(theIfNoneExist)) {
Set<Long> match = myMatchResourceUrlService.processMatchUrl(theIfNoneExist, myResourceType, theRequest); Set<ResourcePersistentId> match = myMatchResourceUrlService.processMatchUrl(theIfNoneExist, myResourceType, theRequest);
if (match.size() > 1) { if (match.size() > 1) {
String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "CREATE", theIfNoneExist, match.size()); String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "CREATE", theIfNoneExist, match.size());
throw new PreconditionFailedException(msg); throw new PreconditionFailedException(msg);
} else if (match.size() == 1) { } else if (match.size() == 1) {
Long pid = match.iterator().next(); ResourcePersistentId pid = match.iterator().next();
entity = myEntityManager.find(ResourceTable.class, pid); entity = myEntityManager.find(ResourceTable.class, pid.getId());
IBaseResource resource = toResource(entity, false); IBaseResource resource = toResource(entity, false);
theResource.setId(resource.getIdElement().getValue()); theResource.setId(resource.getIdElement().getValue());
return toMethodOutcome(theRequest, entity, resource).setCreated(false); return toMethodOutcome(theRequest, entity, resource).setCreated(false);
@ -605,6 +625,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return myExpungeService.expunge(getResourceName(), null, null, theExpungeOptions, theRequestDetails); return myExpungeService.expunge(getResourceName(), null, null, theExpungeOptions, theRequestDetails);
} }
@Override
public String getResourceName() { public String getResourceName() {
return myResourceName; return myResourceName;
} }
@ -790,13 +811,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
ResourceTable entityToUpdate; ResourceTable entityToUpdate;
if (isNotBlank(theConditionalUrl)) { if (isNotBlank(theConditionalUrl)) {
Set<Long> match = myMatchResourceUrlService.processMatchUrl(theConditionalUrl, myResourceType, theRequest); Set<ResourcePersistentId> match = myMatchResourceUrlService.processMatchUrl(theConditionalUrl, myResourceType, theRequest);
if (match.size() > 1) { if (match.size() > 1) {
String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "PATCH", theConditionalUrl, match.size()); String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "PATCH", theConditionalUrl, match.size());
throw new PreconditionFailedException(msg); throw new PreconditionFailedException(msg);
} else if (match.size() == 1) { } else if (match.size() == 1) {
Long pid = match.iterator().next(); ResourcePersistentId pid = match.iterator().next();
entityToUpdate = myEntityManager.find(ResourceTable.class, pid); entityToUpdate = myEntityManager.find(ResourceTable.class, pid.getId());
} else { } else {
String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", theConditionalUrl); String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", theConditionalUrl);
throw new ResourceNotFoundException(msg); throw new ResourceNotFoundException(msg);
@ -848,57 +869,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
// nothing by default // nothing by default
} }
/**
* May be overridden by subclasses to validate resources prior to storage
*
* @param theResource The resource that is about to be stored
*/
protected void preProcessResourceForStorage(T theResource) {
String type = getContext().getResourceDefinition(theResource).getName();
if (!getResourceName().equals(type)) {
throw new InvalidRequestException(getContext().getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "incorrectResourceType", type, getResourceName()));
}
if (theResource.getIdElement().hasIdPart()) {
if (!theResource.getIdElement().isIdPartValid()) {
throw new InvalidRequestException(getContext().getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "failedToCreateWithInvalidId", theResource.getIdElement().getIdPart()));
}
}
/*
* Replace absolute references with relative ones if configured to do so
*/
if (getConfig().getTreatBaseUrlsAsLocal().isEmpty() == false) {
FhirTerser t = getContext().newTerser();
List<ResourceReferenceInfo> refs = t.getAllResourceReferences(theResource);
for (ResourceReferenceInfo nextRef : refs) {
IIdType refId = nextRef.getResourceReference().getReferenceElement();
if (refId != null && refId.hasBaseUrl()) {
if (getConfig().getTreatBaseUrlsAsLocal().contains(refId.getBaseUrl())) {
IIdType newRefId = refId.toUnqualified();
nextRef.getResourceReference().setReference(newRefId.getValue());
}
}
}
}
}
@Override @Override
public Set<Long> processMatchUrl(String theMatchUrl, RequestDetails theRequest) { public IBaseResource readByPid(ResourcePersistentId thePid) {
return myMatchResourceUrlService.processMatchUrl(theMatchUrl, getResourceType(), theRequest);
}
@Override
public IBaseResource readByPid(Long thePid) {
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
Optional<ResourceTable> entity = myResourceTableDao.findById(thePid); Optional<ResourceTable> entity = myResourceTableDao.findById(thePid.getIdAsLong());
if (!entity.isPresent()) { if (!entity.isPresent()) {
throw new ResourceNotFoundException("No resource found with PID " + thePid); throw new ResourceNotFoundException("No resource found with PID " + thePid);
} }
if (entity.get().getDeleted() != null) { if (entity.get().getDeleted() != null) {
throw newResourceGoneException(entity.get()); throw createResourceGoneException(entity.get());
} }
T retVal = toResource(myResourceType, entity.get(), null, false); T retVal = toResource(myResourceType, entity.get(), null, false);
@ -907,17 +887,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return retVal; return retVal;
} }
@NotNull
private ResourceGoneException newResourceGoneException(BaseHasResource theResourceEntity) {
StringBuilder b = new StringBuilder();
b.append("Resource was deleted at ");
b.append(new InstantType(theResourceEntity.getDeleted()).getValueAsString());
ResourceGoneException retVal = new ResourceGoneException(b.toString());
retVal.setResourceId(theResourceEntity.getIdDt());
return retVal;
}
@Override @Override
public T read(IIdType theId) { public T read(IIdType theId) {
return read(theId, null); return read(theId, null);
@ -947,7 +916,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
if (theDeletedOk == false) { if (theDeletedOk == false) {
if (entity.getDeleted() != null) { if (entity.getDeleted() != null) {
throw newResourceGoneException(entity); throw createResourceGoneException(entity);
} }
} }
@ -990,8 +959,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
public BaseHasResource readEntity(IIdType theId, boolean theCheckForForcedId, RequestDetails theRequest) { public BaseHasResource readEntity(IIdType theId, boolean theCheckForForcedId, RequestDetails theRequest) {
validateResourceTypeAndThrowInvalidRequestException(theId); validateResourceTypeAndThrowInvalidRequestException(theId);
Long pid = myIdHelperService.translateForcedIdToPid(getResourceName(), theId.getIdPart(), theRequest); ResourcePersistentId pid = myIdHelperService.translateForcedIdToPid(getResourceName(), theId.getIdPart(), theRequest);
BaseHasResource entity = myEntityManager.find(ResourceTable.class, pid); BaseHasResource entity = myEntityManager.find(ResourceTable.class, pid.getIdAsLong());
if (entity == null) { if (entity == null) {
throw new ResourceNotFoundException(theId); throw new ResourceNotFoundException(theId);
@ -1009,7 +978,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
if (entity == null) { if (entity == null) {
if (theId.hasVersionIdPart()) { if (theId.hasVersionIdPart()) {
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class); TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
q.setParameter("RID", pid); q.setParameter("RID", pid.getId());
q.setParameter("RTYP", myResourceName); q.setParameter("RTYP", myResourceName);
q.setParameter("RVER", theId.getVersionIdPartAsLong()); q.setParameter("RVER", theId.getVersionIdPartAsLong());
try { try {
@ -1029,7 +998,8 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
protected ResourceTable readEntityLatestVersion(IIdType theId, RequestDetails theRequest) { protected ResourceTable readEntityLatestVersion(IIdType theId, RequestDetails theRequest) {
ResourceTable entity = myEntityManager.find(ResourceTable.class, myIdHelperService.translateForcedIdToPid(getResourceName(), theId.getIdPart(), theRequest)); ResourcePersistentId persistentId = myIdHelperService.translateForcedIdToPid(getResourceName(), theId.getIdPart(), theRequest);
ResourceTable entity = myEntityManager.find(ResourceTable.class, persistentId.getId());
if (entity == null) { if (entity == null) {
throw new ResourceNotFoundException(theId); throw new ResourceNotFoundException(theId);
} }
@ -1154,14 +1124,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
@Override @Override
public Set<Long> searchForIds(SearchParameterMap theParams, RequestDetails theRequest) { public Set<ResourcePersistentId> searchForIds(SearchParameterMap theParams, RequestDetails theRequest) {
SearchBuilder builder = newSearchBuilder(); SearchBuilder builder = newSearchBuilder();
builder.setType(getResourceType(), getResourceName()); builder.setType(getResourceType(), getResourceName());
// FIXME: fail if too many results // FIXME: fail if too many results
HashSet<Long> retVal = new HashSet<>(); HashSet<ResourcePersistentId> retVal = new HashSet<>();
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
SearchRuntimeDetails searchRuntimeDetails = new SearchRuntimeDetails(theRequest, uuid); SearchRuntimeDetails searchRuntimeDetails = new SearchRuntimeDetails(theRequest, uuid);
@ -1178,12 +1148,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
} }
protected <MT extends IBaseMetaType> MT toMetaDt(Class<MT> theType, Collection<TagDefinition> tagDefinitions) { protected <MT extends IBaseMetaType> MT toMetaDt(Class<MT> theType, Collection<TagDefinition> tagDefinitions) {
MT retVal; MT retVal = ReflectionUtil.newInstance(theType);
try {
retVal = theType.newInstance();
} catch (Exception e) {
throw new InternalErrorException("Failed to instantiate " + theType.getName(), e);
}
for (TagDefinition next : tagDefinitions) { for (TagDefinition next : tagDefinitions) {
switch (next.getTagType()) { switch (next.getTagType()) {
case PROFILE: case PROFILE:
@ -1200,58 +1165,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return retVal; return retVal;
} }
private DaoMethodOutcome toMethodOutcome(RequestDetails theRequest, @Nonnull final ResourceTable theEntity, @Nonnull IBaseResource theResource) {
DaoMethodOutcome outcome = new DaoMethodOutcome();
IIdType id = null;
if (theResource.getIdElement().getValue() != null) {
id = theResource.getIdElement();
}
if (id == null) {
id = theEntity.getIdDt();
if (getContext().getVersion().getVersion().isRi()) {
id = getContext().getVersion().newIdType().setValue(id.getValue());
}
}
outcome.setId(id);
if (theEntity.getDeleted() == null) {
outcome.setResource(theResource);
}
outcome.setEntity(theEntity);
// Interceptor broadcast: STORAGE_PREACCESS_RESOURCES
if (outcome.getResource() != null) {
SimplePreResourceAccessDetails accessDetails = new SimplePreResourceAccessDetails(outcome.getResource());
HookParams params = new HookParams()
.add(IPreResourceAccessDetails.class, accessDetails)
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest);
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.STORAGE_PREACCESS_RESOURCES, params);
if (accessDetails.isDontReturnResourceAtIndex(0)) {
outcome.setResource(null);
}
}
// Interceptor broadcast: STORAGE_PRESHOW_RESOURCES
// Note that this will only fire if someone actually goes to use the
// resource in a response (it's their responsibility to call
// outcome.fireResourceViewCallback())
outcome.registerResourceViewCallback(() -> {
if (outcome.getResource() != null) {
SimplePreResourceShowDetails showDetails = new SimplePreResourceShowDetails(outcome.getResource());
HookParams params = new HookParams()
.add(IPreResourceShowDetails.class, showDetails)
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest);
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.STORAGE_PRESHOW_RESOURCES, params);
outcome.setResource(showDetails.getResource(0));
}
});
return outcome;
}
private ArrayList<TagDefinition> toTagList(IBaseMetaType theMeta) { private ArrayList<TagDefinition> toTagList(IBaseMetaType theMeta) {
ArrayList<TagDefinition> retVal = new ArrayList<>(); ArrayList<TagDefinition> retVal = new ArrayList<>();
@ -1340,13 +1253,13 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
IIdType resourceId; IIdType resourceId;
if (isNotBlank(theMatchUrl)) { if (isNotBlank(theMatchUrl)) {
Set<Long> match = myMatchResourceUrlService.processMatchUrl(theMatchUrl, myResourceType, theRequest); Set<ResourcePersistentId> match = myMatchResourceUrlService.processMatchUrl(theMatchUrl, myResourceType, theRequest);
if (match.size() > 1) { if (match.size() > 1) {
String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "UPDATE", theMatchUrl, match.size()); String msg = getContext().getLocalizer().getMessageSanitized(BaseHapiFhirDao.class, "transactionOperationWithMultipleMatchFailure", "UPDATE", theMatchUrl, match.size());
throw new PreconditionFailedException(msg); throw new PreconditionFailedException(msg);
} else if (match.size() == 1) { } else if (match.size() == 1) {
Long pid = match.iterator().next(); ResourcePersistentId pid = match.iterator().next();
entity = myEntityManager.find(ResourceTable.class, pid); entity = myEntityManager.find(ResourceTable.class, pid.getId());
resourceId = entity.getIdDt(); resourceId = entity.getIdDt();
} else { } else {
return create(theResource, null, thePerformIndexing, new Date(), theRequest); return create(theResource, null, thePerformIndexing, new Date(), theRequest);
@ -1440,7 +1353,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
if (myDaoConfig.isEnforceReferentialIntegrityOnDelete()) { if (myDaoConfig.isEnforceReferentialIntegrityOnDelete()) {
myDeleteConflictService.validateOkToDelete(deleteConflicts, entity, true, theRequest); myDeleteConflictService.validateOkToDelete(deleteConflicts, entity, true, theRequest);
} }
myDeleteConflictService.validateDeleteConflictsEmptyOrThrowException(deleteConflicts); DeleteConflictService.validateDeleteConflictsEmptyOrThrowException(getContext(), deleteConflicts);
IBaseOperationOutcome oo = createInfoOperationOutcome("Ok to delete"); IBaseOperationOutcome oo = createInfoOperationOutcome("Ok to delete");
return new MethodOutcome(new IdDt(theId.getValue()), oo); return new MethodOutcome(new IdDt(theId.getValue()), oo);

View File

@ -88,4 +88,9 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
} }
@Nullable
@Override
protected String getResourceName() {
return null;
}
} }

View File

@ -0,0 +1,204 @@
package ca.uhn.fhir.jpa.dao;
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 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.FhirContext;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.OperationOutcomeUtil;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.InstantType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Set;
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.OO_SEVERITY_ERROR;
import static ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.OO_SEVERITY_INFO;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public abstract class BaseStorageDao {
/**
* May be overridden by subclasses to validate resources prior to storage
*
* @param theResource The resource that is about to be stored
*/
protected void preProcessResourceForStorage(IBaseResource theResource) {
String type = getContext().getResourceDefinition(theResource).getName();
if (getResourceName() != null && !getResourceName().equals(type)) {
throw new InvalidRequestException(getContext().getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "incorrectResourceType", type, getResourceName()));
}
if (theResource.getIdElement().hasIdPart()) {
if (!theResource.getIdElement().isIdPartValid()) {
throw new InvalidRequestException(getContext().getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "failedToCreateWithInvalidId", theResource.getIdElement().getIdPart()));
}
}
/*
* Replace absolute references with relative ones if configured to do so
*/
if (getConfig().getTreatBaseUrlsAsLocal().isEmpty() == false) {
FhirTerser t = getContext().newTerser();
List<ResourceReferenceInfo> refs = t.getAllResourceReferences(theResource);
for (ResourceReferenceInfo nextRef : refs) {
IIdType refId = nextRef.getResourceReference().getReferenceElement();
if (refId != null && refId.hasBaseUrl()) {
if (getConfig().getTreatBaseUrlsAsLocal().contains(refId.getBaseUrl())) {
IIdType newRefId = refId.toUnqualified();
nextRef.getResourceReference().setReference(newRefId.getValue());
}
}
}
}
if ("Bundle".equals(type)) {
Set<String> allowedBundleTypes = getConfig().getBundleTypesAllowedForStorage();
String bundleType = BundleUtil.getBundleType(getContext(), (IBaseBundle) theResource);
if (isBlank(bundleType) || !allowedBundleTypes.contains(bundleType)) {
String message = "Unable to store a Bundle resource on this server with a Bundle.type value of: " + (isNotBlank(bundleType) ? bundleType : "(missing)");
throw new UnprocessableEntityException(message);
}
}
}
protected DaoMethodOutcome toMethodOutcome(RequestDetails theRequest, @Nonnull final IBasePersistedResource theEntity, @Nonnull IBaseResource theResource) {
DaoMethodOutcome outcome = new DaoMethodOutcome();
IIdType id = null;
if (theResource.getIdElement().getValue() != null) {
id = theResource.getIdElement();
}
if (id == null) {
id = theEntity.getIdDt();
if (getContext().getVersion().getVersion().isRi()) {
id = getContext().getVersion().newIdType().setValue(id.getValue());
}
}
outcome.setId(id);
if (theEntity.isDeleted() == false) {
outcome.setResource(theResource);
}
outcome.setEntity(theEntity);
// Interceptor broadcast: STORAGE_PREACCESS_RESOURCES
if (outcome.getResource() != null) {
SimplePreResourceAccessDetails accessDetails = new SimplePreResourceAccessDetails(outcome.getResource());
HookParams params = new HookParams()
.add(IPreResourceAccessDetails.class, accessDetails)
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest);
JpaInterceptorBroadcaster.doCallHooks(getInterceptorBroadcaster(), theRequest, Pointcut.STORAGE_PREACCESS_RESOURCES, params);
if (accessDetails.isDontReturnResourceAtIndex(0)) {
outcome.setResource(null);
}
}
// Interceptor broadcast: STORAGE_PRESHOW_RESOURCES
// Note that this will only fire if someone actually goes to use the
// resource in a response (it's their responsibility to call
// outcome.fireResourceViewCallback())
outcome.registerResourceViewCallback(() -> {
if (outcome.getResource() != null) {
SimplePreResourceShowDetails showDetails = new SimplePreResourceShowDetails(outcome.getResource());
HookParams params = new HookParams()
.add(IPreResourceShowDetails.class, showDetails)
.add(RequestDetails.class, theRequest)
.addIfMatchesType(ServletRequestDetails.class, theRequest);
JpaInterceptorBroadcaster.doCallHooks(getInterceptorBroadcaster(), theRequest, Pointcut.STORAGE_PRESHOW_RESOURCES, params);
outcome.setResource(showDetails.getResource(0));
}
});
return outcome;
}
protected void doCallHooks(RequestDetails theRequestDetails, Pointcut thePointcut, HookParams theParams) {
JpaInterceptorBroadcaster.doCallHooks(getInterceptorBroadcaster(), theRequestDetails, thePointcut, theParams);
}
protected abstract IInterceptorBroadcaster getInterceptorBroadcaster();
public IBaseOperationOutcome createErrorOperationOutcome(String theMessage, String theCode) {
return createOperationOutcome(OO_SEVERITY_ERROR, theMessage, theCode);
}
public IBaseOperationOutcome createInfoOperationOutcome(String theMessage) {
return createOperationOutcome(OO_SEVERITY_INFO, theMessage, "informational");
}
private IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
OperationOutcomeUtil.addIssue(getContext(), oo, theSeverity, theMessage, null, theCode);
return oo;
}
@NotNull
protected ResourceGoneException createResourceGoneException(IBasePersistedResource theResourceEntity) {
StringBuilder b = new StringBuilder();
b.append("Resource was deleted at ");
b.append(new InstantType(theResourceEntity.getDeleted()).getValueAsString());
ResourceGoneException retVal = new ResourceGoneException(b.toString());
retVal.setResourceId(theResourceEntity.getIdDt());
return retVal;
}
/**
* Provide the DaoConfig
*/
protected abstract DaoConfig getConfig();
/**
* Returns the resource type for this DAO, or null if this is a system-level DAO
*/
@Nullable
protected abstract String getResourceName();
/**
* Provides the FHIR context
*/
protected abstract FhirContext getContext();
}

View File

@ -20,13 +20,14 @@ package ca.uhn.fhir.jpa.dao;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
public class DaoMethodOutcome extends MethodOutcome { public class DaoMethodOutcome extends MethodOutcome {
private ResourceTable myEntity; private IBasePersistedResource myEntity;
private IBaseResource myPreviousResource; private IBaseResource myPreviousResource;
/** /**
@ -36,11 +37,11 @@ public class DaoMethodOutcome extends MethodOutcome {
super(); super();
} }
public ResourceTable getEntity() { public IBasePersistedResource getEntity() {
return myEntity; return myEntity;
} }
public DaoMethodOutcome setEntity(ResourceTable theEntity) { public DaoMethodOutcome setEntity(IBasePersistedResource theEntity) {
myEntity = theEntity; myEntity = theEntity;
return this; return this;
} }

View File

@ -80,8 +80,7 @@ public class DaoRegistry implements ApplicationContextAware, IDaoRegistry {
* @throws InvalidRequestException If the given resource type is not supported * @throws InvalidRequestException If the given resource type is not supported
*/ */
public IFhirResourceDao getResourceDao(String theResourceName) { public IFhirResourceDao getResourceDao(String theResourceName) {
init(); IFhirResourceDao<IBaseResource> retVal = getResourceDaoOrNull(theResourceName);
IFhirResourceDao retVal = myResourceNameToResourceDao.get(theResourceName);
if (retVal == null) { if (retVal == null) {
List<String> supportedResourceTypes = myResourceNameToResourceDao List<String> supportedResourceTypes = myResourceNameToResourceDao
.keySet() .keySet()
@ -126,12 +125,9 @@ public class DaoRegistry implements ApplicationContextAware, IDaoRegistry {
} }
@Nullable @Nullable
public <T extends IBaseResource> IFhirResourceDao<T> getResourceDaoOrNull(String theResourceType) { public <T extends IBaseResource> IFhirResourceDao<T> getResourceDaoOrNull(String theResourceName) {
try { init();
return (IFhirResourceDao<T>) getResourceDao(theResourceType); return (IFhirResourceDao<T>) myResourceNameToResourceDao.get(theResourceName);
} catch (InvalidRequestException e) {
return null;
}
} }
@Override @Override

View File

@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.dao;
*/ */
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.BaseSearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum; import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -44,7 +44,7 @@ public class DaoSearchParamProvider implements ISearchParamProvider {
} }
@Override @Override
public <SP extends IBaseResource> int refreshCache(BaseSearchParamRegistry<SP> theSearchParamRegistry, long theRefreshInterval) { public int refreshCache(SearchParamRegistryImpl theSearchParamRegistry, long theRefreshInterval) {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager); TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
return txTemplate.execute(t-> theSearchParamRegistry.doRefresh(theRefreshInterval)); return txTemplate.execute(t-> theSearchParamRegistry.doRefresh(theRefreshInterval));
} }

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import java.util.Set; import java.util.Set;
@ -31,16 +32,10 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleDstu2 extends BaseHapiFhirResourceDao<Bundle> { public class FhirResourceDaoBundleDstu2 extends BaseHapiFhirResourceDao<Bundle> {
@Override @Override
protected void preProcessResourceForStorage(Bundle theResource) { protected void preProcessResourceForStorage(IBaseResource theResource) {
super.preProcessResourceForStorage(theResource); super.preProcessResourceForStorage(theResource);
Set<String> allowedBundleTypes = getConfig().getBundleTypesAllowedForStorage(); for (Entry next : ((Bundle)theResource).getEntry()) {
if (!allowedBundleTypes.contains(defaultString(theResource.getType()))) {
String message = "Unable to store a Bundle resource on this server with a Bundle.type value of: " + (theResource.getType() != null ? theResource.getType() : "(missing)");
throw new UnprocessableEntityException(message);
}
for (Entry next : theResource.getEntry()) {
next.setFullUrl((String) null); next.setFullUrl((String) null);
} }
} }

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao; import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.SubscriptionTable; import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.model.dstu2.resource.Subscription; import ca.uhn.fhir.model.dstu2.resource.Subscription;
@ -73,12 +74,12 @@ public class FhirResourceDaoSubscriptionDstu2 extends BaseHapiFhirResourceDao<Su
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (theDeletedTimestampOrNull != null) { if (theDeletedTimestampOrNull != null) {
mySubscriptionTableDao.deleteAllForSubscription(theEntity); mySubscriptionTableDao.deleteAllForSubscription((ResourceTable) theEntity);
} }
return retVal; return retVal;
} }

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IContextValidationSupport; import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource; import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
@ -68,6 +69,8 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueS
@Autowired @Autowired
@Qualifier("myFhirContextDstu2Hl7Org") @Qualifier("myFhirContextDstu2Hl7Org")
private FhirContext myRiCtx; private FhirContext myRiCtx;
@Autowired
private FhirContext myFhirContext;
private CachingValidationSupport myValidationSupport; private CachingValidationSupport myValidationSupport;
@ -176,14 +179,15 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueS
@Override @Override
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) { public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
if (theSystem != null && theSystem.startsWith("http://hl7.org/fhir/")) { if (theSystem != null && theSystem.startsWith("http://hl7.org/fhir/")) {
return Collections.singletonList((IIdType) new IdDt(theSystem)); return Collections.singletonList(new IdDt(theSystem));
} }
List<IIdType> valueSetIds; List<IIdType> valueSetIds;
Set<Long> ids = searchForIds(new SearchParameterMap(ValueSet.SP_CODE, new TokenParam(theSystem, theCode)), theRequest); Set<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(ValueSet.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
valueSetIds = new ArrayList<IIdType>(); valueSetIds = new ArrayList<IIdType>();
for (Long next : ids) { for (ResourcePersistentId next : ids) {
valueSetIds.add(new IdDt("ValueSet", next)); IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "ValueSet", next);
valueSetIds.add(id);
} }
return valueSetIds; return valueSetIds;
} }
@ -309,10 +313,11 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueS
if (theId != null) { if (theId != null) {
valueSetIds = Collections.singletonList(theId); valueSetIds = Collections.singletonList(theId);
} else if (haveIdentifierParam) { } else if (haveIdentifierParam) {
Set<Long> ids = searchForIds(new SearchParameterMap(ValueSet.SP_IDENTIFIER, new TokenParam(null, theValueSetIdentifier.getValue())), theRequest); Set<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(ValueSet.SP_IDENTIFIER, new TokenParam(null, theValueSetIdentifier.getValue())), theRequest);
valueSetIds = new ArrayList<>(); valueSetIds = new ArrayList<>();
for (Long next : ids) { for (ResourcePersistentId next : ids) {
valueSetIds.add(new IdDt("ValueSet", next)); IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "ValueSet", next);
valueSetIds.add(id);
} }
} else { } else {
if (theCode == null || theCode.isEmpty()) { if (theCode == null || theCode.isEmpty()) {

View File

@ -22,6 +22,9 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.delete.DeleteConflictList; import ca.uhn.fhir.jpa.delete.DeleteConflictList;
import ca.uhn.fhir.jpa.delete.DeleteConflictService;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.TagDefinition; import ca.uhn.fhir.jpa.model.entity.TagDefinition;
import ca.uhn.fhir.rest.server.servlet.ServletSubRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletSubRequestDetails;
@ -86,6 +89,8 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
private MatchUrlService myMatchUrlService; private MatchUrlService myMatchUrlService;
@Autowired @Autowired
private DaoRegistry myDaoRegistry; private DaoRegistry myDaoRegistry;
@Autowired
private MatchResourceUrlService myMatchResourceUrlService;
private Bundle batch(final RequestDetails theRequestDetails, Bundle theRequest) { private Bundle batch(final RequestDetails theRequestDetails, Bundle theRequest) {
ourLog.info("Beginning batch with {} resources", theRequest.getEntry().size()); ourLog.info("Beginning batch with {} resources", theRequest.getEntry().size());
@ -213,9 +218,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
List<IIdType> deletedResources = new ArrayList<>(); List<IIdType> deletedResources = new ArrayList<>();
DeleteConflictList deleteConflicts = new DeleteConflictList(); DeleteConflictList deleteConflicts = new DeleteConflictList();
Map<Entry, ResourceTable> entriesToProcess = new IdentityHashMap<>(); Map<Entry, IBasePersistedResource> entriesToProcess = new IdentityHashMap<>();
Set<ResourceTable> nonUpdatedEntities = new HashSet<ResourceTable>(); Set<IBasePersistedResource> nonUpdatedEntities = new HashSet<>();
Set<ResourceTable> updatedEntities = new HashSet<>(); Set<IBasePersistedResource> updatedEntities = new HashSet<>();
/* /*
* Handle: GET/PUT/POST * Handle: GET/PUT/POST
@ -293,7 +298,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
} }
for (Map.Entry<Entry, ResourceTable> nextEntry : entriesToProcess.entrySet()) { for (Map.Entry<Entry, IBasePersistedResource> nextEntry : entriesToProcess.entrySet()) {
nextEntry.getKey().getResponse().setLocation(nextEntry.getValue().getIdDt().toUnqualified().getValue()); nextEntry.getKey().getResponse().setLocation(nextEntry.getValue().getIdDt().toUnqualified().getValue());
nextEntry.getKey().getResponse().setEtag(nextEntry.getValue().getIdDt().getVersionIdPart()); nextEntry.getKey().getResponse().setEtag(nextEntry.getValue().getIdDt().getVersionIdPart());
} }
@ -301,13 +306,13 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
long delay = System.currentTimeMillis() - start; long delay = System.currentTimeMillis() - start;
int numEntries = theRequest.getEntry().size(); int numEntries = theRequest.getEntry().size();
long delayPer = delay / numEntries; long delayPer = delay / numEntries;
ourLog.info("{} completed in {}ms ({} entries at {}ms per entry)", new Object[] {theActionName, delay, numEntries, delayPer}); ourLog.info("{} completed in {}ms ({} entries at {}ms per entry)", theActionName, delay, numEntries, delayPer);
response.setType(BundleTypeEnum.TRANSACTION_RESPONSE); response.setType(BundleTypeEnum.TRANSACTION_RESPONSE);
return response; return response;
} }
private void handleTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date theUpdateTime, Set<IdDt> theAllIds, Map<IdDt, IdDt> theIdSubstitutions, Map<IdDt, DaoMethodOutcome> theIdToPersistedOutcome, Bundle theResponse, IdentityHashMap<Entry, Integer> theOriginalRequestOrder, List<IIdType> theDeletedResources, DeleteConflictList theDeleteConflicts, Map<Entry, ResourceTable> theEntriesToProcess, Set<ResourceTable> theNonUpdatedEntities, Set<ResourceTable> theUpdatedEntities) { private void handleTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date theUpdateTime, Set<IdDt> theAllIds, Map<IdDt, IdDt> theIdSubstitutions, Map<IdDt, DaoMethodOutcome> theIdToPersistedOutcome, Bundle theResponse, IdentityHashMap<Entry, Integer> theOriginalRequestOrder, List<IIdType> theDeletedResources, DeleteConflictList theDeleteConflicts, Map<Entry, IBasePersistedResource> theEntriesToProcess, Set<IBasePersistedResource> theNonUpdatedEntities, Set<IBasePersistedResource> theUpdatedEntities) {
/* /*
* Loop through the request and process any entries of type * Loop through the request and process any entries of type
* PUT, POST or DELETE * PUT, POST or DELETE
@ -331,7 +336,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
} }
} }
if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+\\:.*") && !isPlaceholder(nextResourceId)) { if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+:.*") && !isPlaceholder(nextResourceId)) {
throw new InvalidRequestException("Invalid placeholder ID found: " + nextResourceId.getIdPart() + " - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'"); throw new InvalidRequestException("Invalid placeholder ID found: " + nextResourceId.getIdPart() + " - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'");
} }
@ -444,7 +449,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
*/ */
theDeleteConflicts.removeIf(next -> theDeletedResources.contains(next.getTargetId().toVersionless())); theDeleteConflicts.removeIf(next -> theDeletedResources.contains(next.getTargetId().toVersionless()));
myDeleteConflictService.validateDeleteConflictsEmptyOrThrowException(theDeleteConflicts); DeleteConflictService.validateDeleteConflictsEmptyOrThrowException(getContext(), theDeleteConflicts);
/* /*
* Perform ID substitutions and then index each resource we have saved * Perform ID substitutions and then index each resource we have saved
@ -508,8 +513,8 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
if (nextEntry.getRequest().getMethodElement().getValueAsEnum() == HTTPVerbEnum.POST) { if (nextEntry.getRequest().getMethodElement().getValueAsEnum() == HTTPVerbEnum.POST) {
String matchUrl = nextEntry.getRequest().getIfNoneExist(); String matchUrl = nextEntry.getRequest().getIfNoneExist();
if (isNotBlank(matchUrl)) { if (isNotBlank(matchUrl)) {
IFhirResourceDao<?> resourceDao = getDao(nextEntry.getResource().getClass()); Class<? extends IBaseResource> resType = nextEntry.getResource().getClass();
Set<Long> val = resourceDao.processMatchUrl(matchUrl, theRequestDetails); Set<ResourcePersistentId> val = myMatchResourceUrlService.processMatchUrl(matchUrl, resType, theRequestDetails);
if (val.size() > 1) { if (val.size() > 1) {
throw new InvalidRequestException( throw new InvalidRequestException(
"Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?"); "Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
@ -623,11 +628,11 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
} }
private Bundle transaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName) { private Bundle transaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName) {
super.markRequestAsProcessingSubRequest(theRequestDetails); markRequestAsProcessingSubRequest(theRequestDetails);
try { try {
return doTransaction(theRequestDetails, theRequest, theActionName); return doTransaction(theRequestDetails, theRequest, theActionName);
} finally { } finally {
super.clearRequestAsProcessingSubRequest(theRequestDetails); clearRequestAsProcessingSubRequest(theRequestDetails);
} }
} }
@ -655,15 +660,13 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
private static boolean isPlaceholder(IdDt theId) { private static boolean isPlaceholder(IdDt theId) {
if (theId.getValue() != null) { if (theId.getValue() != null) {
if (theId.getValue().startsWith("urn:oid:") || theId.getValue().startsWith("urn:uuid:")) { return theId.getValue().startsWith("urn:oid:") || theId.getValue().startsWith("urn:uuid:");
return true;
}
} }
return false; return false;
} }
private static String toStatusString(int theStatusCode) { private static String toStatusString(int theStatusCode) {
return Integer.toString(theStatusCode) + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode)); return theStatusCode + " " + defaultString(Constants.HTTP_STATUS_NAMES.get(theStatusCode));
} }
@Override @Override

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao; import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
@ -116,10 +117,10 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
} }
} }
private List<Long> doSearch(String theResourceName, SearchParameterMap theParams, Long theReferencingPid) { private List<ResourcePersistentId> doSearch(String theResourceName, SearchParameterMap theParams, ResourcePersistentId theReferencingPid) {
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager); FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);
List<Long> pids = null; List<ResourcePersistentId> pids = null;
/* /*
* Handle textual params * Handle textual params
@ -202,12 +203,12 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
// execute search // execute search
List<?> result = jpaQuery.getResultList(); List<?> result = jpaQuery.getResultList();
ArrayList<Long> retVal = new ArrayList<>(); ArrayList<ResourcePersistentId> retVal = new ArrayList<>();
for (Object object : result) { for (Object object : result) {
Object[] nextArray = (Object[]) object; Object[] nextArray = (Object[]) object;
Long next = (Long) nextArray[0]; Long next = (Long) nextArray[0];
if (next != null) { if (next != null) {
retVal.add(next); retVal.add(new ResourcePersistentId(next));
} }
} }
@ -215,9 +216,9 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
} }
@Override @Override
public List<Long> everything(String theResourceName, SearchParameterMap theParams, RequestDetails theRequest) { public List<ResourcePersistentId> everything(String theResourceName, SearchParameterMap theParams, RequestDetails theRequest) {
Long pid = null; ResourcePersistentId pid = null;
if (theParams.get(IAnyResource.SP_RES_ID) != null) { if (theParams.get(IAnyResource.SP_RES_ID) != null) {
String idParamValue; String idParamValue;
IQueryParameterType idParam = theParams.get(IAnyResource.SP_RES_ID).get(0).get(0); IQueryParameterType idParam = theParams.get(IAnyResource.SP_RES_ID).get(0).get(0);
@ -231,8 +232,8 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
pid = myIdHelperService.translateForcedIdToPid(theResourceName, idParamValue, theRequest); pid = myIdHelperService.translateForcedIdToPid(theResourceName, idParamValue, theRequest);
} }
Long referencingPid = pid; ResourcePersistentId referencingPid = pid;
List<Long> retVal = doSearch(null, theParams, referencingPid); List<ResourcePersistentId> retVal = doSearch(null, theParams, referencingPid);
if (referencingPid != null) { if (referencingPid != null) {
retVal.add(referencingPid); retVal.add(referencingPid);
} }
@ -264,7 +265,7 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
@Transactional() @Transactional()
@Override @Override
public List<Long> search(String theResourceName, SearchParameterMap theParams) { public List<ResourcePersistentId> search(String theResourceName, SearchParameterMap theParams) {
return doSearch(theResourceName, theParams, null); return doSearch(theResourceName, theParams, null);
} }
@ -281,7 +282,7 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
if (contextParts.length != 3 || "Patient".equals(contextParts[0]) == false || "$everything".equals(contextParts[2]) == false) { if (contextParts.length != 3 || "Patient".equals(contextParts[0]) == false || "$everything".equals(contextParts[2]) == false) {
throw new InvalidRequestException("Invalid context: " + theContext); throw new InvalidRequestException("Invalid context: " + theContext);
} }
Long pid = myIdHelperService.translateForcedIdToPid(contextParts[0], contextParts[1], theRequest); ResourcePersistentId pid = myIdHelperService.translateForcedIdToPid(contextParts[0], contextParts[1], theRequest);
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager); FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.delete.DeleteConflictList; import ca.uhn.fhir.jpa.delete.DeleteConflictList;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource; import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum; import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
@ -154,8 +155,6 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
DaoMethodOutcome patch(IIdType theId, String theConditionalUrl, PatchTypeEnum thePatchType, String thePatchBody, RequestDetails theRequestDetails); DaoMethodOutcome patch(IIdType theId, String theConditionalUrl, PatchTypeEnum thePatchType, String thePatchBody, RequestDetails theRequestDetails);
Set<Long> processMatchUrl(String theMatchUrl, RequestDetails theRequest);
/** /**
* Read a resource - Note that this variant of the method does not take in a {@link RequestDetails} and * Read a resource - Note that this variant of the method does not take in a {@link RequestDetails} and
* therefore can not fire any interceptors. Use only for internal system calls * therefore can not fire any interceptors. Use only for internal system calls
@ -165,7 +164,7 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
/** /**
* Read a resource by its internal PID * Read a resource by its internal PID
*/ */
IBaseResource readByPid(Long thePid); IBaseResource readByPid(ResourcePersistentId thePid);
/** /**
* @param theId * @param theId
@ -205,7 +204,7 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
@Transactional(propagation = Propagation.SUPPORTS) @Transactional(propagation = Propagation.SUPPORTS)
IBundleProvider search(SearchParameterMap theParams, RequestDetails theRequestDetails, HttpServletResponse theServletResponse); IBundleProvider search(SearchParameterMap theParams, RequestDetails theRequestDetails, HttpServletResponse theServletResponse);
Set<Long> searchForIds(SearchParameterMap theParams, RequestDetails theRequest); Set<ResourcePersistentId> searchForIds(SearchParameterMap theParams, RequestDetails theRequest);
/** /**
* Takes a map of incoming raw search parameters and translates/parses them into * Takes a map of incoming raw search parameters and translates/parses them into

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.dao;
import java.util.List; import java.util.List;
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion; import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
@ -30,9 +31,9 @@ public interface IFulltextSearchSvc {
List<Suggestion> suggestKeywords(String theContext, String theSearchParam, String theText, RequestDetails theRequest); List<Suggestion> suggestKeywords(String theContext, String theSearchParam, String theText, RequestDetails theRequest);
List<Long> search(String theResourceName, SearchParameterMap theParams); List<ResourcePersistentId> search(String theResourceName, SearchParameterMap theParams);
List<Long> everything(String theResourceName, SearchParameterMap theParams, RequestDetails theRequest); List<ResourcePersistentId> everything(String theResourceName, SearchParameterMap theParams, RequestDetails theRequest);
boolean isDisabled(); boolean isDisabled();

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -29,10 +30,10 @@ import java.util.Date;
public interface IJpaDao<T extends IBaseResource> { public interface IJpaDao<T extends IBaseResource> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable IBasePersistedResource updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource
theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry); boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry);
ResourceTable updateInternal(RequestDetails theRequestDetails, T theResource, boolean thePerformIndexing, boolean theForceUpdateVersion, IBasePersistedResource updateInternal(RequestDetails theRequestDetails, T theResource, boolean thePerformIndexing, boolean theForceUpdateVersion,
ResourceTable theEntity, IIdType theResourceId, IBaseResource theOldResource); IBasePersistedResource theEntity, IIdType theResourceId, IBaseResource theOldResource);
} }

View File

@ -20,10 +20,12 @@ package ca.uhn.fhir.jpa.dao;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import java.io.Closeable; import java.io.Closeable;
import java.util.Iterator; import java.util.Iterator;
public interface IResultIterator extends Iterator<Long>, Closeable { public interface IResultIterator extends Iterator<ResourcePersistentId>, Closeable {
int getSkippedCount(); int getSkippedCount();

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.dao;
*/ */
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.Include;
@ -43,9 +44,9 @@ public interface ISearchBuilder {
Iterator<Long> createCountQuery(SearchParameterMap theParams, String theSearchUuid, RequestDetails theRequest); Iterator<Long> createCountQuery(SearchParameterMap theParams, String theSearchUuid, RequestDetails theRequest);
void loadResourcesByPid(Collection<Long> thePids, Collection<Long> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, RequestDetails theDetails); void loadResourcesByPid(Collection<ResourcePersistentId> thePids, Collection<ResourcePersistentId> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, RequestDetails theDetails);
Set<Long> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode, Set<ResourcePersistentId> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<ResourcePersistentId> theMatches, Set<Include> theRevIncludes, boolean theReverseMode,
DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest); DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest);
/** /**
@ -55,6 +56,6 @@ public interface ISearchBuilder {
void setType(Class<? extends IBaseResource> theResourceType, String theResourceName); void setType(Class<? extends IBaseResource> theResourceType, String theResourceName);
void setPreviouslyAddedResourcePids(List<Long> thePreviouslyAddedResourcePids); void setPreviouslyAddedResourcePids(List<ResourcePersistentId> thePreviouslyAddedResourcePids);
} }

View File

@ -25,8 +25,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.dao.DaoRegistry; import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
@ -37,7 +36,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.StopWatch;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Request;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -54,7 +52,7 @@ public class MatchResourceUrlService {
@Autowired @Autowired
private IInterceptorBroadcaster myInterceptorBroadcaster; private IInterceptorBroadcaster myInterceptorBroadcaster;
public <R extends IBaseResource> Set<Long> processMatchUrl(String theMatchUrl, Class<R> theResourceType, RequestDetails theRequest) { public <R extends IBaseResource> Set<ResourcePersistentId> processMatchUrl(String theMatchUrl, Class<R> theResourceType, RequestDetails theRequest) {
StopWatch sw = new StopWatch(); StopWatch sw = new StopWatch();
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceType); RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceType);
@ -71,7 +69,7 @@ public class MatchResourceUrlService {
throw new InternalErrorException("No DAO for resource type: " + theResourceType.getName()); throw new InternalErrorException("No DAO for resource type: " + theResourceType.getName());
} }
Set<Long> retVal = dao.searchForIds(paramMap, theRequest); Set<ResourcePersistentId> retVal = dao.searchForIds(paramMap, theRequest);
// Interceptor broadcast: JPA_PERFTRACE_INFO // Interceptor broadcast: JPA_PERFTRACE_INFO
if (JpaInterceptorBroadcaster.hasHooks(Pointcut.JPA_PERFTRACE_INFO, myInterceptorBroadcaster, theRequest)) { if (JpaInterceptorBroadcaster.hasHooks(Pointcut.JPA_PERFTRACE_INFO, myInterceptorBroadcaster, theRequest)) {

View File

@ -20,7 +20,15 @@ package ca.uhn.fhir.jpa.dao;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
@ -30,6 +38,7 @@ import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.entity.ResourceSearchView; import ca.uhn.fhir.jpa.entity.ResourceSearchView;
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails; import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
@ -40,10 +49,20 @@ import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept; import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.jpa.util.*; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.jpa.util.BaseIterator;
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
import ca.uhn.fhir.jpa.util.SqlQueryList;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.model.base.composite.BaseQuantityDt; import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
@ -51,7 +70,11 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.*; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails; import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.param.*;
@ -96,7 +119,11 @@ import java.util.Map.Entry;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static org.apache.commons.lang3.StringUtils.*; import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim;
/** /**
* The SearchBuilder is responsible for actually forming the SQL query that handles * The SearchBuilder is responsible for actually forming the SQL query that handles
@ -106,14 +133,14 @@ import static org.apache.commons.lang3.StringUtils.*;
@Scope("prototype") @Scope("prototype")
public class SearchBuilder implements ISearchBuilder { public class SearchBuilder implements ISearchBuilder {
private static final List<Long> EMPTY_LONG_LIST = Collections.unmodifiableList(new ArrayList<>()); private static final List<ResourcePersistentId> EMPTY_LONG_LIST = Collections.unmodifiableList(new ArrayList<>());
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchBuilder.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchBuilder.class);
/** /**
* See loadResourcesByPid * See loadResourcesByPid
* for an explanation of why we use the constant 800 * for an explanation of why we use the constant 800
*/ */
private static final int MAXIMUM_PAGE_SIZE = 800; private static final int MAXIMUM_PAGE_SIZE = 800;
private static Long NO_MORE = -1L; private static ResourcePersistentId NO_MORE = new ResourcePersistentId(-1L);
private final boolean myDontUseHashesForSearch; private final boolean myDontUseHashesForSearch;
private final DaoConfig myDaoConfig; private final DaoConfig myDaoConfig;
@Autowired @Autowired
@ -138,7 +165,7 @@ public class SearchBuilder implements ISearchBuilder {
private ITermReadSvc myTerminologySvc; private ITermReadSvc myTerminologySvc;
@Autowired @Autowired
private MatchUrlService myMatchUrlService; private MatchUrlService myMatchUrlService;
private List<Long> myAlsoIncludePids; private List<ResourcePersistentId> myAlsoIncludePids;
private CriteriaBuilder myBuilder; private CriteriaBuilder myBuilder;
private BaseHapiFhirDao<?> myCallingDao; private BaseHapiFhirDao<?> myCallingDao;
private Map<JoinKey, Join<?, ?>> myIndexJoins = Maps.newHashMap(); private Map<JoinKey, Join<?, ?>> myIndexJoins = Maps.newHashMap();
@ -151,7 +178,7 @@ public class SearchBuilder implements ISearchBuilder {
private String mySearchUuid; private String mySearchUuid;
private int myFetchSize; private int myFetchSize;
private Integer myMaxResultsToFetch; private Integer myMaxResultsToFetch;
private Set<Long> myPidSet; private Set<ResourcePersistentId> myPidSet;
private boolean myHaveIndexJoins = false; private boolean myHaveIndexJoins = false;
/** /**
@ -542,11 +569,11 @@ public class SearchBuilder implements ISearchBuilder {
List<Predicate> codePredicates = new ArrayList<>(); List<Predicate> codePredicates = new ArrayList<>();
// Resources by ID // Resources by ID
List<Long> targetPids = myIdHelperService.translateForcedIdToPids(targetIds, theRequest); List<ResourcePersistentId> targetPids = myIdHelperService.translateForcedIdToPids(targetIds, theRequest);
if (!targetPids.isEmpty()) { if (!targetPids.isEmpty()) {
ourLog.debug("Searching for resource link with target PIDs: {}", targetPids); ourLog.debug("Searching for resource link with target PIDs: {}", targetPids);
Predicate pathPredicate = createResourceLinkPathPredicate(theResourceName, theParamName, join); Predicate pathPredicate = createResourceLinkPathPredicate(theResourceName, theParamName, join);
Predicate pidPredicate = join.get("myTargetResourcePid").in(targetPids); Predicate pidPredicate = join.get("myTargetResourcePid").in(ResourcePersistentId.toLongList(targetPids));
codePredicates.add(myBuilder.and(pathPredicate, pidPredicate)); codePredicates.add(myBuilder.and(pathPredicate, pidPredicate));
} }
@ -573,7 +600,6 @@ public class SearchBuilder implements ISearchBuilder {
private Predicate addPredicateReferenceWithChain(String theResourceName, String theParamName, List<? extends IQueryParameterType> theList, Join<ResourceTable, ResourceLink> theJoin, List<Predicate> theCodePredicates, ReferenceParam theRef, RequestDetails theRequest) { private Predicate addPredicateReferenceWithChain(String theResourceName, String theParamName, List<? extends IQueryParameterType> theList, Join<ResourceTable, ResourceLink> theJoin, List<Predicate> theCodePredicates, ReferenceParam theRef, RequestDetails theRequest) {
final List<Class<? extends IBaseResource>> resourceTypes; final List<Class<? extends IBaseResource>> resourceTypes;
String resourceId;
if (!theRef.hasResourceType()) { if (!theRef.hasResourceType()) {
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
@ -631,14 +657,11 @@ public class SearchBuilder implements ISearchBuilder {
} }
} }
resourceId = theRef.getValue();
} else { } else {
try { try {
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theRef.getResourceType()); RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theRef.getResourceType());
resourceTypes = new ArrayList<>(1); resourceTypes = new ArrayList<>(1);
resourceTypes.add(resDef.getImplementingClass()); resourceTypes.add(resDef.getImplementingClass());
resourceId = theRef.getIdPart();
} catch (DataFormatException e) { } catch (DataFormatException e) {
throw new InvalidRequestException("Invalid resource type: " + theRef.getResourceType()); throw new InvalidRequestException("Invalid resource type: " + theRef.getResourceType());
} }
@ -712,6 +735,42 @@ public class SearchBuilder implements ISearchBuilder {
return predicate; return predicate;
} }
private void addPredicateSource(List<List<IQueryParameterType>> theAndOrParams, RequestDetails theRequest) {
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
addPredicateSource(nextAnd, SearchFilterParser.CompareOperation.eq, theRequest);
}
}
private Predicate addPredicateSource(List<? extends IQueryParameterType> theList, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) {
if (myDaoConfig.getStoreMetaSourceInformation() == DaoConfig.StoreMetaSourceInformationEnum.NONE) {
String msg = myContext.getLocalizer().getMessage(SearchBuilder.class, "sourceParamDisabled");
throw new InvalidRequestException(msg);
}
Join<ResourceTable, ResourceHistoryProvenanceEntity> join = myResourceTableRoot.join("myProvenance", JoinType.LEFT);
List<Predicate> codePredicates = new ArrayList<>();
for (IQueryParameterType nextParameter : theList) {
SourceParam sourceParameter = new SourceParam(nextParameter.getValueAsQueryToken(myContext));
String sourceUri = sourceParameter.getSourceUri();
String requestId = sourceParameter.getRequestId();
Predicate sourceUriPredicate = myBuilder.equal(join.get("mySourceUri"), sourceUri);
Predicate requestIdPredicate = myBuilder.equal(join.get("myRequestId"), requestId);
if (isNotBlank(sourceUri) && isNotBlank(requestId)) {
codePredicates.add(myBuilder.and(sourceUriPredicate, requestIdPredicate));
} else if (isNotBlank(sourceUri)) {
codePredicates.add(sourceUriPredicate);
} else if (isNotBlank(requestId)) {
codePredicates.add(requestIdPredicate);
}
}
Predicate retVal = myBuilder.or(toArray(codePredicates));
myPredicates.add(retVal);
return retVal;
}
private Subquery<Long> createLinkSubquery(boolean theFoundChainMatch, String theChain, String theSubResourceName, List<IQueryParameterType> theOrValues, RequestDetails theRequest) { private Subquery<Long> createLinkSubquery(boolean theFoundChainMatch, String theChain, String theSubResourceName, List<IQueryParameterType> theOrValues, RequestDetails theRequest) {
Subquery<Long> subQ = myResourceTableQuery.subquery(Long.class); Subquery<Long> subQ = myResourceTableQuery.subquery(Long.class);
Root<ResourceTable> subQfrom = subQ.from(ResourceTable.class); Root<ResourceTable> subQfrom = subQ.from(ResourceTable.class);
@ -772,8 +831,8 @@ public class SearchBuilder implements ISearchBuilder {
return chainValue; return chainValue;
} }
private Predicate addPredicateResourceId(String theResourceName, List<List<IQueryParameterType>> theValues, RequestDetails theRequest) { private void addPredicateResourceId(String theResourceName, List<List<IQueryParameterType>> theValues, RequestDetails theRequest) {
return addPredicateResourceId(theValues, theResourceName, null, theRequest); addPredicateResourceId(theValues, theResourceName, null, theRequest);
} }
private Predicate addPredicateResourceId(List<List<IQueryParameterType>> theValues, String theResourceName, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) { private Predicate addPredicateResourceId(List<List<IQueryParameterType>> theValues, String theResourceName, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) {
@ -792,10 +851,10 @@ public class SearchBuilder implements ISearchBuilder {
private Predicate createPredicateResourceId(Root<ResourceTable> theRoot, String theResourceName, List<List<IQueryParameterType>> theValues, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) { private Predicate createPredicateResourceId(Root<ResourceTable> theRoot, String theResourceName, List<List<IQueryParameterType>> theValues, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) {
Predicate nextPredicate = null; Predicate nextPredicate = null;
Set<Long> allOrPids = null; Set<ResourcePersistentId> allOrPids = null;
for (List<? extends IQueryParameterType> nextValue : theValues) { for (List<? extends IQueryParameterType> nextValue : theValues) {
Set<Long> orPids = new HashSet<>(); Set<ResourcePersistentId> orPids = new HashSet<>();
boolean haveValue = false; boolean haveValue = false;
for (IQueryParameterType next : nextValue) { for (IQueryParameterType next : nextValue) {
String value = next.getValueAsQueryToken(myContext); String value = next.getValueAsQueryToken(myContext);
@ -807,7 +866,7 @@ public class SearchBuilder implements ISearchBuilder {
if (isNotBlank(value)) { if (isNotBlank(value)) {
haveValue = true; haveValue = true;
try { try {
Long pid = myIdHelperService.translateForcedIdToPid(theResourceName, valueAsId.getIdPart(), theRequest); ResourcePersistentId pid = myIdHelperService.translateForcedIdToPid(theResourceName, valueAsId.getIdPart(), theRequest);
orPids.add(pid); orPids.add(pid);
} catch (ResourceNotFoundException e) { } catch (ResourceNotFoundException e) {
// This is not an error in a search, it just results in no matchesFhirResourceDaoR4InterceptorTest // This is not an error in a search, it just results in no matchesFhirResourceDaoR4InterceptorTest
@ -838,12 +897,12 @@ public class SearchBuilder implements ISearchBuilder {
switch (operation) { switch (operation) {
default: default:
case eq: case eq:
codePredicates.add(theRoot.get("myId").as(Long.class).in(allOrPids)); codePredicates.add(theRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(allOrPids)));
codePredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theResourceName)); codePredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theResourceName));
nextPredicate = myBuilder.and(toArray(codePredicates)); nextPredicate = myBuilder.and(toArray(codePredicates));
break; break;
case ne: case ne:
codePredicates.add(theRoot.get("myId").as(Long.class).in(allOrPids).not()); codePredicates.add(theRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(allOrPids)).not());
codePredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theResourceName)); codePredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theResourceName));
nextPredicate = myBuilder.and(toArray(codePredicates)); nextPredicate = myBuilder.and(toArray(codePredicates));
break; break;
@ -855,41 +914,10 @@ public class SearchBuilder implements ISearchBuilder {
} }
private Predicate addPredicateSource(List<? extends IQueryParameterType> theList, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) { private void addPredicateString(String theResourceName,
if (myDaoConfig.getStoreMetaSourceInformation() == DaoConfig.StoreMetaSourceInformationEnum.NONE) {
String msg = myContext.getLocalizer().getMessage(SearchBuilder.class, "sourceParamDisabled");
throw new InvalidRequestException(msg);
}
Join<ResourceTable, ResourceHistoryProvenanceEntity> join = myResourceTableRoot.join("myProvenance", JoinType.LEFT);
List<Predicate> codePredicates = new ArrayList<>();
for (IQueryParameterType nextParameter : theList) {
SourceParam sourceParameter = new SourceParam(nextParameter.getValueAsQueryToken(myContext));
String sourceUri = sourceParameter.getSourceUri();
String requestId = sourceParameter.getRequestId();
Predicate sourceUriPredicate = myBuilder.equal(join.get("mySourceUri"), sourceUri);
Predicate requestIdPredicate = myBuilder.equal(join.get("myRequestId"), requestId);
if (isNotBlank(sourceUri) && isNotBlank(requestId)) {
codePredicates.add(myBuilder.and(sourceUriPredicate, requestIdPredicate));
} else if (isNotBlank(sourceUri)) {
codePredicates.add(sourceUriPredicate);
} else if (isNotBlank(requestId)) {
codePredicates.add(requestIdPredicate);
}
}
Predicate retVal = myBuilder.or(toArray(codePredicates));
myPredicates.add(retVal);
return retVal;
}
private Predicate addPredicateString(String theResourceName,
String theParamName, String theParamName,
List<? extends IQueryParameterType> theList) { List<? extends IQueryParameterType> theList) {
return addPredicateString(theResourceName, addPredicateString(theResourceName,
theParamName, theParamName,
theList, theList,
SearchFilterParser.CompareOperation.sw); SearchFilterParser.CompareOperation.sw);
@ -2015,7 +2043,7 @@ public class SearchBuilder implements ISearchBuilder {
* @param thePidSet May be null * @param thePidSet May be null
*/ */
@Override @Override
public void setPreviouslyAddedResourcePids(@Nullable List<Long> thePidSet) { public void setPreviouslyAddedResourcePids(@Nullable List<ResourcePersistentId> thePidSet) {
myPidSet = new HashSet<>(thePidSet); myPidSet = new HashSet<>(thePidSet);
} }
@ -2081,12 +2109,12 @@ public class SearchBuilder implements ISearchBuilder {
if (myParams.get(IAnyResource.SP_RES_ID) != null) { if (myParams.get(IAnyResource.SP_RES_ID) != null) {
StringParam idParm = (StringParam) myParams.get(IAnyResource.SP_RES_ID).get(0).get(0); StringParam idParm = (StringParam) myParams.get(IAnyResource.SP_RES_ID).get(0).get(0);
Long pid = myIdHelperService.translateForcedIdToPid(myResourceName, idParm.getValue(), theRequest); ResourcePersistentId pid = myIdHelperService.translateForcedIdToPid(myResourceName, idParm.getValue(), theRequest);
if (myAlsoIncludePids == null) { if (myAlsoIncludePids == null) {
myAlsoIncludePids = new ArrayList<>(1); myAlsoIncludePids = new ArrayList<>(1);
} }
myAlsoIncludePids.add(pid); myAlsoIncludePids.add(pid);
myPredicates.add(myBuilder.equal(join.get("myTargetResourcePid").as(Long.class), pid)); myPredicates.add(myBuilder.equal(join.get("myTargetResourcePid").as(Long.class), pid.getIdAsLong()));
} else { } else {
Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName); Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName);
Predicate sourceTypePredicate = myBuilder.equal(myResourceTableRoot.get("myResourceType").as(String.class), myResourceName); Predicate sourceTypePredicate = myBuilder.equal(myResourceTableRoot.get("myResourceType").as(String.class), myResourceName);
@ -2110,7 +2138,7 @@ public class SearchBuilder implements ISearchBuilder {
} }
} }
List<Long> pids; List<ResourcePersistentId> pids;
if (myParams.getEverythingMode() != null) { if (myParams.getEverythingMode() != null) {
pids = myFulltextSearchSvc.everything(myResourceName, myParams, theRequest); pids = myFulltextSearchSvc.everything(myResourceName, myParams, theRequest);
} else { } else {
@ -2118,10 +2146,10 @@ public class SearchBuilder implements ISearchBuilder {
} }
if (pids.isEmpty()) { if (pids.isEmpty()) {
// Will never match // Will never match
pids = Collections.singletonList(-1L); pids = Collections.singletonList(new ResourcePersistentId(-1L));
} }
myPredicates.add(myResourceTableRoot.get("myId").as(Long.class).in(pids)); myPredicates.add(myResourceTableRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
} }
/* /*
@ -2315,21 +2343,21 @@ public class SearchBuilder implements ISearchBuilder {
return retVal; return retVal;
} }
private void doLoadPids(Collection<Long> thePids, Collection<Long> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, private void doLoadPids(Collection<ResourcePersistentId> thePids, Collection<ResourcePersistentId> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation,
Map<Long, Integer> thePosition, RequestDetails theRequest) { Map<ResourcePersistentId, Integer> thePosition, RequestDetails theRequest) {
// -- get the resource from the searchView // -- get the resource from the searchView
Collection<ResourceSearchView> resourceSearchViewList = myResourceSearchViewDao.findByResourceIds(thePids); Collection<ResourceSearchView> resourceSearchViewList = myResourceSearchViewDao.findByResourceIds(ResourcePersistentId.toLongList(thePids));
//-- preload all tags with tag definition if any //-- preload all tags with tag definition if any
Map<Long, Collection<ResourceTag>> tagMap = getResourceTagMap(resourceSearchViewList); Map<ResourcePersistentId, Collection<ResourceTag>> tagMap = getResourceTagMap(resourceSearchViewList);
Long resourceId; ResourcePersistentId resourceId;
for (ResourceSearchView next : resourceSearchViewList) { for (ResourceSearchView next : resourceSearchViewList) {
Class<? extends IBaseResource> resourceType = myContext.getResourceDefinition(next.getResourceType()).getImplementingClass(); Class<? extends IBaseResource> resourceType = myContext.getResourceDefinition(next.getResourceType()).getImplementingClass();
resourceId = next.getId(); resourceId = new ResourcePersistentId(next.getId());
IBaseResource resource = myCallingDao.toResource(resourceType, next, tagMap.get(resourceId), theForHistoryOperation); IBaseResource resource = myCallingDao.toResource(resourceType, next, tagMap.get(resourceId), theForHistoryOperation);
if (resource == null) { if (resource == null) {
@ -2360,7 +2388,7 @@ public class SearchBuilder implements ISearchBuilder {
} }
} }
private Map<Long, Collection<ResourceTag>> getResourceTagMap(Collection<ResourceSearchView> theResourceSearchViewList) { private Map<ResourcePersistentId, Collection<ResourceTag>> getResourceTagMap(Collection<ResourceSearchView> theResourceSearchViewList) {
List<Long> idList = new ArrayList<>(theResourceSearchViewList.size()); List<Long> idList = new ArrayList<>(theResourceSearchViewList.size());
@ -2370,7 +2398,7 @@ public class SearchBuilder implements ISearchBuilder {
idList.add(resource.getId()); idList.add(resource.getId());
} }
Map<Long, Collection<ResourceTag>> tagMap = new HashMap<>(); Map<ResourcePersistentId, Collection<ResourceTag>> tagMap = new HashMap<>();
//-- no tags //-- no tags
if (idList.size() == 0) if (idList.size() == 0)
@ -2380,11 +2408,11 @@ public class SearchBuilder implements ISearchBuilder {
Collection<ResourceTag> tagList = myResourceTagDao.findByResourceIds(idList); Collection<ResourceTag> tagList = myResourceTagDao.findByResourceIds(idList);
//-- build the map, key = resourceId, value = list of ResourceTag //-- build the map, key = resourceId, value = list of ResourceTag
Long resourceId; ResourcePersistentId resourceId;
Collection<ResourceTag> tagCol; Collection<ResourceTag> tagCol;
for (ResourceTag tag : tagList) { for (ResourceTag tag : tagList) {
resourceId = tag.getResourceId(); resourceId = new ResourcePersistentId(tag.getResourceId());
tagCol = tagMap.get(resourceId); tagCol = tagMap.get(resourceId);
if (tagCol == null) { if (tagCol == null) {
tagCol = new ArrayList<>(); tagCol = new ArrayList<>();
@ -2399,7 +2427,7 @@ public class SearchBuilder implements ISearchBuilder {
} }
@Override @Override
public void loadResourcesByPid(Collection<Long> thePids, Collection<Long> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, RequestDetails theDetails) { public void loadResourcesByPid(Collection<ResourcePersistentId> thePids, Collection<ResourcePersistentId> theIncludedPids, List<IBaseResource> theResourceListToPopulate, boolean theForHistoryOperation, RequestDetails theDetails) {
if (thePids.isEmpty()) { if (thePids.isEmpty()) {
ourLog.debug("The include pids are empty"); ourLog.debug("The include pids are empty");
// return; // return;
@ -2409,8 +2437,8 @@ public class SearchBuilder implements ISearchBuilder {
// when running asserts // when running asserts
assert new HashSet<>(thePids).size() == thePids.size() : "PID list contains duplicates: " + thePids; assert new HashSet<>(thePids).size() == thePids.size() : "PID list contains duplicates: " + thePids;
Map<Long, Integer> position = new HashMap<>(); Map<ResourcePersistentId, Integer> position = new HashMap<>();
for (Long next : thePids) { for (ResourcePersistentId next : thePids) {
position.put(next, theResourceListToPopulate.size()); position.put(next, theResourceListToPopulate.size());
theResourceListToPopulate.add(null); theResourceListToPopulate.add(null);
} }
@ -2421,11 +2449,11 @@ public class SearchBuilder implements ISearchBuilder {
* if it's lots of IDs. I suppose maybe we should be doing this as a join anyhow * if it's lots of IDs. I suppose maybe we should be doing this as a join anyhow
* but this should work too. Sigh. * but this should work too. Sigh.
*/ */
List<Long> pids = new ArrayList<>(thePids); List<ResourcePersistentId> pids = new ArrayList<>(thePids);
for (int i = 0; i < pids.size(); i += MAXIMUM_PAGE_SIZE) { for (int i = 0; i < pids.size(); i += MAXIMUM_PAGE_SIZE) {
int to = i + MAXIMUM_PAGE_SIZE; int to = i + MAXIMUM_PAGE_SIZE;
to = Math.min(to, pids.size()); to = Math.min(to, pids.size());
List<Long> pidsSubList = pids.subList(i, to); List<ResourcePersistentId> pidsSubList = pids.subList(i, to);
doLoadPids(pidsSubList, theIncludedPids, theResourceListToPopulate, theForHistoryOperation, position, theDetails); doLoadPids(pidsSubList, theIncludedPids, theResourceListToPopulate, theForHistoryOperation, position, theDetails);
} }
@ -2436,7 +2464,7 @@ public class SearchBuilder implements ISearchBuilder {
* so it can't be Collections.emptySet() or some such thing * so it can't be Collections.emptySet() or some such thing
*/ */
@Override @Override
public HashSet<Long> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<Long> theMatches, Set<Include> theRevIncludes, public HashSet<ResourcePersistentId> loadIncludes(FhirContext theContext, EntityManager theEntityManager, Collection<ResourcePersistentId> theMatches, Set<Include> theRevIncludes,
boolean theReverseMode, DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest) { boolean theReverseMode, DateRangeParam theLastUpdated, String theSearchIdOrDescription, RequestDetails theRequest) {
if (theMatches.size() == 0) { if (theMatches.size() == 0) {
return new HashSet<>(); return new HashSet<>();
@ -2446,9 +2474,9 @@ public class SearchBuilder implements ISearchBuilder {
} }
String searchFieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid"; String searchFieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid";
Collection<Long> nextRoundMatches = theMatches; Collection<ResourcePersistentId> nextRoundMatches = theMatches;
HashSet<Long> allAdded = new HashSet<>(); HashSet<ResourcePersistentId> allAdded = new HashSet<>();
HashSet<Long> original = new HashSet<>(theMatches); HashSet<ResourcePersistentId> original = new HashSet<>(theMatches);
ArrayList<Include> includes = new ArrayList<>(theRevIncludes); ArrayList<Include> includes = new ArrayList<>(theRevIncludes);
int roundCounts = 0; int roundCounts = 0;
@ -2458,7 +2486,7 @@ public class SearchBuilder implements ISearchBuilder {
do { do {
roundCounts++; roundCounts++;
HashSet<Long> pidsToInclude = new HashSet<>(); HashSet<ResourcePersistentId> pidsToInclude = new HashSet<>();
for (Iterator<Include> iter = includes.iterator(); iter.hasNext(); ) { for (Iterator<Include> iter = includes.iterator(); iter.hasNext(); ) {
Include nextInclude = iter.next(); Include nextInclude = iter.next();
@ -2470,16 +2498,16 @@ public class SearchBuilder implements ISearchBuilder {
if (matchAll) { if (matchAll) {
String sql; String sql;
sql = "SELECT r FROM ResourceLink r WHERE r." + searchFieldName + " IN (:target_pids) "; sql = "SELECT r FROM ResourceLink r WHERE r." + searchFieldName + " IN (:target_pids) ";
List<Collection<Long>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE); List<Collection<ResourcePersistentId>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE);
for (Collection<Long> nextPartition : partitions) { for (Collection<ResourcePersistentId> nextPartition : partitions) {
TypedQuery<ResourceLink> q = theEntityManager.createQuery(sql, ResourceLink.class); TypedQuery<ResourceLink> q = theEntityManager.createQuery(sql, ResourceLink.class);
q.setParameter("target_pids", nextPartition); q.setParameter("target_pids", ResourcePersistentId.toLongList(nextPartition));
List<ResourceLink> results = q.getResultList(); List<ResourceLink> results = q.getResultList();
for (ResourceLink resourceLink : results) { for (ResourceLink resourceLink : results) {
if (theReverseMode) { if (theReverseMode) {
pidsToInclude.add(resourceLink.getSourceResourcePid()); pidsToInclude.add(new ResourcePersistentId(resourceLink.getSourceResourcePid()));
} else { } else {
pidsToInclude.add(resourceLink.getTargetResourcePid()); pidsToInclude.add(new ResourcePersistentId(resourceLink.getTargetResourcePid()));
} }
} }
} }
@ -2523,11 +2551,11 @@ public class SearchBuilder implements ISearchBuilder {
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)"; sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)";
} }
List<Collection<Long>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE); List<Collection<ResourcePersistentId>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE);
for (Collection<Long> nextPartition : partitions) { for (Collection<ResourcePersistentId> nextPartition : partitions) {
TypedQuery<ResourceLink> q = theEntityManager.createQuery(sql, ResourceLink.class); TypedQuery<ResourceLink> q = theEntityManager.createQuery(sql, ResourceLink.class);
q.setParameter("src_path", nextPath); q.setParameter("src_path", nextPath);
q.setParameter("target_pids", nextPartition); q.setParameter("target_pids", ResourcePersistentId.toLongList(nextPartition));
if (targetResourceType != null) { if (targetResourceType != null) {
q.setParameter("target_resource_type", targetResourceType); q.setParameter("target_resource_type", targetResourceType);
} else if (haveTargetTypesDefinedByParam) { } else if (haveTargetTypesDefinedByParam) {
@ -2538,12 +2566,12 @@ public class SearchBuilder implements ISearchBuilder {
if (theReverseMode) { if (theReverseMode) {
Long pid = resourceLink.getSourceResourcePid(); Long pid = resourceLink.getSourceResourcePid();
if (pid != null) { if (pid != null) {
pidsToInclude.add(pid); pidsToInclude.add(new ResourcePersistentId(pid));
} }
} else { } else {
Long pid = resourceLink.getTargetResourcePid(); Long pid = resourceLink.getTargetResourcePid();
if (pid != null) { if (pid != null) {
pidsToInclude.add(pid); pidsToInclude.add(new ResourcePersistentId(pid));
} }
} }
} }
@ -2557,7 +2585,7 @@ public class SearchBuilder implements ISearchBuilder {
pidsToInclude = new HashSet<>(filterResourceIdsByLastUpdated(theEntityManager, theLastUpdated, pidsToInclude)); pidsToInclude = new HashSet<>(filterResourceIdsByLastUpdated(theEntityManager, theLastUpdated, pidsToInclude));
} }
} }
for (Long next : pidsToInclude) { for (ResourcePersistentId next : pidsToInclude) {
if (original.contains(next) == false && allAdded.contains(next) == false) { if (original.contains(next) == false && allAdded.contains(next) == false) {
theMatches.add(next); theMatches.add(next);
} }
@ -2573,7 +2601,7 @@ public class SearchBuilder implements ISearchBuilder {
// This can be used to remove results from the search result details before // This can be used to remove results from the search result details before
// the user has a chance to know that they were in the results // the user has a chance to know that they were in the results
if (allAdded.size() > 0) { if (allAdded.size() > 0) {
List<Long> includedPidList = new ArrayList<>(allAdded); List<ResourcePersistentId> includedPidList = new ArrayList<>(allAdded);
JpaPreResourceAccessDetails accessDetails = new JpaPreResourceAccessDetails(includedPidList, () -> this); JpaPreResourceAccessDetails accessDetails = new JpaPreResourceAccessDetails(includedPidList, () -> this);
HookParams params = new HookParams() HookParams params = new HookParams()
.add(IPreResourceAccessDetails.class, accessDetails) .add(IPreResourceAccessDetails.class, accessDetails)
@ -2583,7 +2611,7 @@ public class SearchBuilder implements ISearchBuilder {
for (int i = includedPidList.size() - 1; i >= 0; i--) { for (int i = includedPidList.size() - 1; i >= 0; i--) {
if (accessDetails.isDontReturnResourceAtIndex(i)) { if (accessDetails.isDontReturnResourceAtIndex(i)) {
Long value = includedPidList.remove(i); ResourcePersistentId value = includedPidList.remove(i);
if (value != null) { if (value != null) {
theMatches.remove(value); theMatches.remove(value);
} }
@ -2596,14 +2624,14 @@ public class SearchBuilder implements ISearchBuilder {
return allAdded; return allAdded;
} }
private List<Collection<Long>> partition(Collection<Long> theNextRoundMatches, int theMaxLoad) { private List<Collection<ResourcePersistentId>> partition(Collection<ResourcePersistentId> theNextRoundMatches, int theMaxLoad) {
if (theNextRoundMatches.size() <= theMaxLoad) { if (theNextRoundMatches.size() <= theMaxLoad) {
return Collections.singletonList(theNextRoundMatches); return Collections.singletonList(theNextRoundMatches);
} else { } else {
List<Collection<Long>> retVal = new ArrayList<>(); List<Collection<ResourcePersistentId>> retVal = new ArrayList<>();
Collection<Long> current = null; Collection<ResourcePersistentId> current = null;
for (Long next : theNextRoundMatches) { for (ResourcePersistentId next : theNextRoundMatches) {
if (current == null) { if (current == null) {
current = new ArrayList<>(theMaxLoad); current = new ArrayList<>(theMaxLoad);
retVal.add(current); retVal.add(current);
@ -2834,28 +2862,28 @@ public class SearchBuilder implements ISearchBuilder {
return null; return null;
} }
private Predicate processFilter(SearchFilterParser.Filter filter, private Predicate processFilter(SearchFilterParser.Filter theFilter,
String theResourceName, RequestDetails theRequest) { String theResourceName, RequestDetails theRequest) {
if (filter instanceof SearchFilterParser.FilterParameter) { if (theFilter instanceof SearchFilterParser.FilterParameter) {
return processFilterParameter((SearchFilterParser.FilterParameter) filter, return processFilterParameter((SearchFilterParser.FilterParameter) theFilter,
theResourceName, theRequest); theResourceName, theRequest);
} else if (filter instanceof SearchFilterParser.FilterLogical) { } else if (theFilter instanceof SearchFilterParser.FilterLogical) {
// Left side // Left side
Predicate leftPredicate = processFilter(((SearchFilterParser.FilterLogical) filter).getFilter1(), Predicate xPredicate = processFilter(((SearchFilterParser.FilterLogical) theFilter).getFilter1(),
theResourceName, theRequest); theResourceName, theRequest);
// Right side // Right side
Predicate rightPredicate = processFilter(((SearchFilterParser.FilterLogical) filter).getFilter2(), Predicate yPredicate = processFilter(((SearchFilterParser.FilterLogical) theFilter).getFilter2(),
theResourceName, theRequest); theResourceName, theRequest);
if (((SearchFilterParser.FilterLogical) filter).getOperation() == SearchFilterParser.FilterLogicalOperation.and) { if (((SearchFilterParser.FilterLogical) theFilter).getOperation() == SearchFilterParser.FilterLogicalOperation.and) {
return myBuilder.and(leftPredicate, rightPredicate); return myBuilder.and(xPredicate, yPredicate);
} else if (((SearchFilterParser.FilterLogical) filter).getOperation() == SearchFilterParser.FilterLogicalOperation.or) { } else if (((SearchFilterParser.FilterLogical) theFilter).getOperation() == SearchFilterParser.FilterLogicalOperation.or) {
return myBuilder.or(leftPredicate, rightPredicate); return myBuilder.or(xPredicate, yPredicate);
} }
} else if (filter instanceof SearchFilterParser.FilterParameterGroup) { } else if (theFilter instanceof SearchFilterParser.FilterParameterGroup) {
return processFilter(((SearchFilterParser.FilterParameterGroup) filter).getContained(), return processFilter(((SearchFilterParser.FilterParameterGroup) theFilter).getContained(),
theResourceName, theRequest); theResourceName, theRequest);
} }
return null; return null;
@ -2867,29 +2895,30 @@ public class SearchBuilder implements ISearchBuilder {
return; return;
} }
if (theParamName.equals(IAnyResource.SP_RES_ID)) { switch (theParamName) {
case IAnyResource.SP_RES_ID:
addPredicateResourceId(theResourceName, theAndOrParams, theRequest); addPredicateResourceId(theResourceName, theAndOrParams, theRequest);
break;
} else if (theParamName.equals(IAnyResource.SP_RES_LANGUAGE)) { case IAnyResource.SP_RES_LANGUAGE:
addPredicateLanguage(theAndOrParams); addPredicateLanguage(theAndOrParams);
break;
} else if (theParamName.equals(Constants.PARAM_HAS)) { case Constants.PARAM_HAS:
addPredicateHas(theAndOrParams, theRequest); addPredicateHas(theAndOrParams, theRequest);
break;
} else if (theParamName.equals(Constants.PARAM_TAG) || theParamName.equals(Constants.PARAM_PROFILE) || theParamName.equals(Constants.PARAM_SECURITY)) { case Constants.PARAM_TAG:
case Constants.PARAM_PROFILE:
case Constants.PARAM_SECURITY:
addPredicateTag(theAndOrParams, theParamName); addPredicateTag(theAndOrParams, theParamName);
break;
} else if (theParamName.equals(Constants.PARAM_SOURCE)) { case Constants.PARAM_SOURCE:
addPredicateSource(theAndOrParams, theRequest);
break;
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) { default:
addPredicateSource(nextAnd, SearchFilterParser.CompareOperation.eq, theRequest);
}
} else {
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName); RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
if (nextParamDef != null) { if (nextParamDef != null) {
@ -2975,6 +3004,7 @@ public class SearchBuilder implements ISearchBuilder {
throw new InvalidRequestException("Unknown search parameter " + theParamName + " for resource type " + theResourceName); throw new InvalidRequestException("Unknown search parameter " + theParamName + " for resource type " + theResourceName);
} }
} }
break;
} }
} }
@ -3079,16 +3109,16 @@ public class SearchBuilder implements ISearchBuilder {
} }
public class IncludesIterator extends BaseIterator<Long> implements Iterator<Long> { public class IncludesIterator extends BaseIterator<ResourcePersistentId> implements Iterator<ResourcePersistentId> {
private final RequestDetails myRequest; private final RequestDetails myRequest;
private Iterator<Long> myCurrentIterator; private Iterator<ResourcePersistentId> myCurrentIterator;
private int myCurrentOffset; private int myCurrentOffset;
private ArrayList<Long> myCurrentPids; private ArrayList<ResourcePersistentId> myCurrentPids;
private Long myNext; private ResourcePersistentId myNext;
private int myPageSize = myDaoConfig.getEverythingIncludesFetchPageSize(); private int myPageSize = myDaoConfig.getEverythingIncludesFetchPageSize();
IncludesIterator(Set<Long> thePidSet, RequestDetails theRequest) { IncludesIterator(Set<ResourcePersistentId> thePidSet, RequestDetails theRequest) {
myCurrentPids = new ArrayList<>(thePidSet); myCurrentPids = new ArrayList<>(thePidSet);
myCurrentIterator = EMPTY_LONG_LIST.iterator(); myCurrentIterator = EMPTY_LONG_LIST.iterator();
myCurrentOffset = 0; myCurrentOffset = 0;
@ -3113,9 +3143,9 @@ public class SearchBuilder implements ISearchBuilder {
break; break;
} }
myCurrentOffset = end; myCurrentOffset = end;
Collection<Long> pidsToScan = myCurrentPids.subList(start, end); Collection<ResourcePersistentId> pidsToScan = myCurrentPids.subList(start, end);
Set<Include> includes = Collections.singleton(new Include("*", true)); Set<Include> includes = Collections.singleton(new Include("*", true));
Set<Long> newPids = loadIncludes(myContext, myEntityManager, pidsToScan, includes, false, myParams.getLastUpdated(), mySearchUuid, myRequest); Set<ResourcePersistentId> newPids = loadIncludes(myContext, myEntityManager, pidsToScan, includes, false, myParams.getLastUpdated(), mySearchUuid, myRequest);
myCurrentIterator = newPids.iterator(); myCurrentIterator = newPids.iterator();
} }
@ -3128,16 +3158,16 @@ public class SearchBuilder implements ISearchBuilder {
} }
@Override @Override
public Long next() { public ResourcePersistentId next() {
fetchNext(); fetchNext();
Long retVal = myNext; ResourcePersistentId retVal = myNext;
myNext = null; myNext = null;
return retVal; return retVal;
} }
} }
private final class QueryIterator extends BaseIterator<Long> implements IResultIterator { private final class QueryIterator extends BaseIterator<ResourcePersistentId> implements IResultIterator {
private final SearchRuntimeDetails mySearchRuntimeDetails; private final SearchRuntimeDetails mySearchRuntimeDetails;
private final RequestDetails myRequest; private final RequestDetails myRequest;
@ -3145,8 +3175,8 @@ public class SearchBuilder implements ISearchBuilder {
private final boolean myHavePerftraceFoundIdHook; private final boolean myHavePerftraceFoundIdHook;
private boolean myFirst = true; private boolean myFirst = true;
private IncludesIterator myIncludesIterator; private IncludesIterator myIncludesIterator;
private Long myNext; private ResourcePersistentId myNext;
private Iterator<Long> myPreResultsIterator; private Iterator<ResourcePersistentId> myPreResultsIterator;
private ScrollableResultsIterator<Long> myResultsIterator; private ScrollableResultsIterator<Long> myResultsIterator;
private SortSpec mySort; private SortSpec mySort;
private boolean myStillNeedToFetchIncludes; private boolean myStillNeedToFetchIncludes;
@ -3199,7 +3229,7 @@ public class SearchBuilder implements ISearchBuilder {
if (myPreResultsIterator != null && myPreResultsIterator.hasNext()) { if (myPreResultsIterator != null && myPreResultsIterator.hasNext()) {
while (myPreResultsIterator.hasNext()) { while (myPreResultsIterator.hasNext()) {
Long next = myPreResultsIterator.next(); ResourcePersistentId next = myPreResultsIterator.next();
if (next != null) if (next != null)
if (myPidSet.add(next)) { if (myPidSet.add(next)) {
myNext = next; myNext = next;
@ -3210,15 +3240,16 @@ public class SearchBuilder implements ISearchBuilder {
if (myNext == null) { if (myNext == null) {
while (myResultsIterator.hasNext()) { while (myResultsIterator.hasNext()) {
Long next = myResultsIterator.next(); Long nextLong = myResultsIterator.next();
if (myHavePerftraceFoundIdHook) { if (myHavePerftraceFoundIdHook) {
HookParams params = new HookParams() HookParams params = new HookParams()
.add(Integer.class, System.identityHashCode(this)) .add(Integer.class, System.identityHashCode(this))
.add(Object.class, next); .add(Object.class, nextLong);
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, myRequest, Pointcut.JPA_PERFTRACE_SEARCH_FOUND_ID, params); JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, myRequest, Pointcut.JPA_PERFTRACE_SEARCH_FOUND_ID, params);
} }
if (next != null) { if (nextLong != null) {
ResourcePersistentId next = new ResourcePersistentId(nextLong);
if (myPidSet.add(next)) { if (myPidSet.add(next)) {
myNext = next; myNext = next;
break; break;
@ -3236,7 +3267,7 @@ public class SearchBuilder implements ISearchBuilder {
} }
if (myIncludesIterator != null) { if (myIncludesIterator != null) {
while (myIncludesIterator.hasNext()) { while (myIncludesIterator.hasNext()) {
Long next = myIncludesIterator.next(); ResourcePersistentId next = myIncludesIterator.next();
if (next != null) if (next != null)
if (myPidSet.add(next)) { if (myPidSet.add(next)) {
myNext = next; myNext = next;
@ -3294,9 +3325,9 @@ public class SearchBuilder implements ISearchBuilder {
} }
@Override @Override
public Long next() { public ResourcePersistentId next() {
fetchNext(); fetchNext();
Long retVal = myNext; ResourcePersistentId retVal = myNext;
myNext = null; myNext = null;
Validate.isTrue(!NO_MORE.equals(retVal), "No more elements"); Validate.isTrue(!NO_MORE.equals(retVal), "No more elements");
return retVal; return retVal;
@ -3430,7 +3461,7 @@ public class SearchBuilder implements ISearchBuilder {
return likeExpression.replace("%", "[%]") + "%"; return likeExpression.replace("%", "[%]") + "%";
} }
private static List<Long> filterResourceIdsByLastUpdated(EntityManager theEntityManager, final DateRangeParam theLastUpdated, Collection<Long> thePids) { private static List<ResourcePersistentId> filterResourceIdsByLastUpdated(EntityManager theEntityManager, final DateRangeParam theLastUpdated, Collection<ResourcePersistentId> thePids) {
if (thePids.isEmpty()) { if (thePids.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -3440,12 +3471,12 @@ public class SearchBuilder implements ISearchBuilder {
cq.select(from.get("myId").as(Long.class)); cq.select(from.get("myId").as(Long.class));
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from); List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from);
lastUpdatedPredicates.add(from.get("myId").as(Long.class).in(thePids)); lastUpdatedPredicates.add(from.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(thePids)));
cq.where(SearchBuilder.toArray(lastUpdatedPredicates)); cq.where(SearchBuilder.toArray(lastUpdatedPredicates));
TypedQuery<Long> query = theEntityManager.createQuery(cq); TypedQuery<Long> query = theEntityManager.createQuery(cq);
return query.getResultList(); return ResourcePersistentId.fromLongList(query.getResultList());
} }

View File

@ -27,10 +27,9 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
public interface IResourceIndexedSearchParamStringDao extends JpaRepository<ResourceIndexedSearchParamString, Long> { import java.util.List;
@Query("select count(*) from ResourceIndexedSearchParamString t WHERE t.myResourcePid = :resid") public interface IResourceIndexedSearchParamStringDao extends JpaRepository<ResourceIndexedSearchParamString, Long> {
int countForResourceId(@Param("resid") Long theResourcePid);
@Modifying @Modifying
@Query("delete from ResourceIndexedSearchParamString t WHERE t.myResourcePid = :resid") @Query("delete from ResourceIndexedSearchParamString t WHERE t.myResourcePid = :resid")

View File

@ -32,18 +32,6 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleDstu3 extends BaseHapiFhirResourceDao<Bundle> { public class FhirResourceDaoBundleDstu3 extends BaseHapiFhirResourceDao<Bundle> {
@Override // nothing
protected void preProcessResourceForStorage(Bundle theResource) {
super.preProcessResourceForStorage(theResource);
Set<String> allowedBundleTypes = getConfig().getBundleTypesAllowedForStorage();
if (theResource.getType() == null || !allowedBundleTypes.contains(defaultString(theResource.getType().toCode()))) {
String message = "Unable to store a Bundle resource on this server with a Bundle.type value of: " + (theResource.getType() != null ? theResource.getType().toCode() : "(missing)");
throw new UnprocessableEntityException(message);
}
}
} }

View File

@ -20,9 +20,12 @@ package ca.uhn.fhir.jpa.dao.dstu3;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IContextValidationSupport; import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao; import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem; import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -37,7 +40,6 @@ import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.dstu3.model.CodeSystem; import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding; import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -63,6 +65,8 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
private ValidationSupportChain myValidationSupport; private ValidationSupportChain myValidationSupport;
@Autowired @Autowired
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc; protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
@Autowired
private FhirContext myFhirContext;
public FhirResourceDaoCodeSystemDstu3() { public FhirResourceDaoCodeSystemDstu3() {
super(); super();
@ -70,10 +74,11 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
@Override @Override
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) { public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
Set<Long> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest ); Set<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest );
List<IIdType> valueSetIds = new ArrayList<>(); List<IIdType> valueSetIds = new ArrayList<>();
for (Long next : ids) { for (ResourcePersistentId next : ids) {
valueSetIds.add(new IdType("CodeSystem", next)); IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
valueSetIds.add(id);
} }
return valueSetIds; return valueSetIds;
} }
@ -135,7 +140,7 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (!retVal.isUnchangedInCurrentOperation()) { if (!retVal.isUnchangedInCurrentOperation()) {
@ -145,7 +150,7 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
org.hl7.fhir.r4.model.CodeSystem cs = VersionConvertor_30_40.convertCodeSystem(csDstu3); org.hl7.fhir.r4.model.CodeSystem cs = VersionConvertor_30_40.convertCodeSystem(csDstu3);
addPidToResource(theEntity, cs); addPidToResource(theEntity, cs);
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity); myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, (ResourceTable) theEntity);
} }

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.term.TranslationMatch; import ca.uhn.fhir.jpa.term.TranslationMatch;
import ca.uhn.fhir.jpa.term.TranslationRequest; import ca.uhn.fhir.jpa.term.TranslationRequest;
import ca.uhn.fhir.jpa.term.TranslationResult; import ca.uhn.fhir.jpa.term.TranslationResult;
@ -157,7 +158,7 @@ public class FhirResourceDaoConceptMapDstu3 extends BaseHapiFhirResourceDao<Conc
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao; import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.entity.SubscriptionTable; import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.dstu3.model.Subscription; import org.hl7.fhir.dstu3.model.Subscription;
@ -65,12 +66,12 @@ public class FhirResourceDaoSubscriptionDstu3 extends BaseHapiFhirResourceDao<Su
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (theDeletedTimestampOrNull != null) { if (theDeletedTimestampOrNull != null) {
mySubscriptionTableDao.deleteAllForSubscription(theEntity); mySubscriptionTableDao.deleteAllForSubscription((ResourceTable) theEntity);
} }
return retVal; return retVal;
} }

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.util.LogicUtil; import ca.uhn.fhir.jpa.util.LogicUtil;
@ -411,7 +412,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -43,7 +43,7 @@ import java.util.List;
public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> { public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
@Autowired @Autowired
private TransactionProcessor<Bundle, BundleEntryComponent> myTransactionProcessor; private TransactionProcessor myTransactionProcessor;
@Override @Override
@PostConstruct @PostConstruct

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.DaoRegistry; import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.IResourceLinkResolver; import ca.uhn.fhir.jpa.searchparam.extractor.IResourceLinkResolver;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
@ -60,7 +61,7 @@ public class DaoResourceLinkResolver implements IResourceLinkResolver {
@Override @Override
public ResourceTable findTargetResource(RuntimeSearchParam theNextSpDef, String theNextPathsUnsplit, IIdType theNextId, String theTypeString, Class<? extends IBaseResource> theType, String theId, RequestDetails theRequest) { public ResourceTable findTargetResource(RuntimeSearchParam theNextSpDef, String theNextPathsUnsplit, IIdType theNextId, String theTypeString, Class<? extends IBaseResource> theType, String theId, RequestDetails theRequest) {
ResourceTable target; ResourceTable target;
Long valueOf; ResourcePersistentId valueOf;
try { try {
valueOf = myIdHelperService.translateForcedIdToPid(theTypeString, theId, theRequest); valueOf = myIdHelperService.translateForcedIdToPid(theTypeString, theId, theRequest);
ourLog.trace("Translated {}/{} to resource PID {}", theType, theId, valueOf); ourLog.trace("Translated {}/{} to resource PID {}", theType, theId, valueOf);
@ -76,12 +77,12 @@ public class DaoResourceLinkResolver implements IResourceLinkResolver {
newResource.setId(resName + "/" + theId); newResource.setId(resName + "/" + theId);
IFhirResourceDao<IBaseResource> placeholderResourceDao = (IFhirResourceDao<IBaseResource>) myDaoRegistry.getResourceDao(newResource.getClass()); IFhirResourceDao<IBaseResource> placeholderResourceDao = (IFhirResourceDao<IBaseResource>) myDaoRegistry.getResourceDao(newResource.getClass());
ourLog.debug("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue()); ourLog.debug("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue());
valueOf = placeholderResourceDao.update(newResource).getEntity().getId(); valueOf = placeholderResourceDao.update(newResource).getEntity().getPersistentId();
} else { } else {
throw new InvalidRequestException("Resource " + resName + "/" + theId + " not found, specified in path: " + theNextPathsUnsplit); throw new InvalidRequestException("Resource " + resName + "/" + theId + " not found, specified in path: " + theNextPathsUnsplit);
} }
} }
target = myEntityManager.find(ResourceTable.class, valueOf); target = myEntityManager.find(ResourceTable.class, valueOf.getIdAsLong());
RuntimeResourceDefinition targetResourceDef = myContext.getResourceDefinition(theType); RuntimeResourceDefinition targetResourceDef = myContext.getResourceDefinition(theType);
if (target == null) { if (target == null) {
String resName = targetResourceDef.getName(); String resName = targetResourceDef.getName();

View File

@ -20,8 +20,10 @@ package ca.uhn.fhir.jpa.dao.index;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao; import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.model.entity.ForcedId; import ca.uhn.fhir.jpa.model.entity.ForcedId;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
@ -61,7 +63,7 @@ public class IdHelperService {
* @throws ResourceNotFoundException If the ID can not be found * @throws ResourceNotFoundException If the ID can not be found
*/ */
@Nonnull @Nonnull
public Long translateForcedIdToPid(IIdType theId, RequestDetails theRequestDetails) { public ResourcePersistentId translateForcedIdToPid(IIdType theId, RequestDetails theRequestDetails) {
return translateForcedIdToPid(theId.getResourceType(), theId.getIdPart(), theRequestDetails); return translateForcedIdToPid(theId.getResourceType(), theId.getIdPart(), theRequestDetails);
} }
@ -69,10 +71,10 @@ public class IdHelperService {
* @throws ResourceNotFoundException If the ID can not be found * @throws ResourceNotFoundException If the ID can not be found
*/ */
@Nonnull @Nonnull
public Long translateForcedIdToPid(String theResourceName, String theResourceId, RequestDetails theRequestDetails) throws ResourceNotFoundException { public ResourcePersistentId translateForcedIdToPid(String theResourceName, String theResourceId, RequestDetails theRequestDetails) throws ResourceNotFoundException {
// We only pass 1 input in so only 0..1 will come back // We only pass 1 input in so only 0..1 will come back
IdDt id = new IdDt(theResourceName, theResourceId); IdDt id = new IdDt(theResourceName, theResourceId);
List<Long> matches = translateForcedIdToPids(myDaoConfig, myInterceptorBroadcaster, theRequestDetails, myForcedIdDao, Collections.singletonList(id)); List<ResourcePersistentId> matches = translateForcedIdToPids(myDaoConfig, myInterceptorBroadcaster, theRequestDetails, myForcedIdDao, Collections.singletonList(id));
assert matches.size() <= 1; assert matches.size() <= 1;
if (matches.isEmpty()) { if (matches.isEmpty()) {
throw new ResourceNotFoundException(id); throw new ResourceNotFoundException(id);
@ -80,23 +82,23 @@ public class IdHelperService {
return matches.get(0); return matches.get(0);
} }
public List<Long> translateForcedIdToPids(Collection<IIdType> theId, RequestDetails theRequestDetails) { public List<ResourcePersistentId> translateForcedIdToPids(Collection<IIdType> theId, RequestDetails theRequestDetails) {
return IdHelperService.translateForcedIdToPids(myDaoConfig, myInterceptorBroadcaster, theRequestDetails, myForcedIdDao, theId); return IdHelperService.translateForcedIdToPids(myDaoConfig, myInterceptorBroadcaster, theRequestDetails, myForcedIdDao, theId);
} }
private static List<Long> translateForcedIdToPids(DaoConfig theDaoConfig, IInterceptorBroadcaster theInterceptorBroadcaster, RequestDetails theRequest, IForcedIdDao theForcedIdDao, Collection<IIdType> theId) { private static List<ResourcePersistentId> translateForcedIdToPids(DaoConfig theDaoConfig, IInterceptorBroadcaster theInterceptorBroadcaster, RequestDetails theRequest, IForcedIdDao theForcedIdDao, Collection<IIdType> theId) {
theId.forEach(id -> Validate.isTrue(id.hasIdPart())); theId.forEach(id -> Validate.isTrue(id.hasIdPart()));
if (theId.isEmpty()) { if (theId.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<Long> retVal = new ArrayList<>(); List<ResourcePersistentId> retVal = new ArrayList<>();
ListMultimap<String, String> typeToIds = MultimapBuilder.hashKeys().arrayListValues().build(); ListMultimap<String, String> typeToIds = MultimapBuilder.hashKeys().arrayListValues().build();
for (IIdType nextId : theId) { for (IIdType nextId : theId) {
if (theDaoConfig.getResourceClientIdStrategy() != DaoConfig.ClientIdStrategyEnum.ANY && isValidPid(nextId)) { if (theDaoConfig.getResourceClientIdStrategy() != DaoConfig.ClientIdStrategyEnum.ANY && isValidPid(nextId)) {
retVal.add(nextId.getIdPartAsLong()); retVal.add(new ResourcePersistentId(nextId.getIdPartAsLong()));
} else { } else {
if (nextId.hasResourceType()) { if (nextId.hasResourceType()) {
typeToIds.put(nextId.getResourceType(), nextId.getIdPart()); typeToIds.put(nextId.getResourceType(), nextId.getIdPart());
@ -119,18 +121,34 @@ public class IdHelperService {
.add(StorageProcessingMessage.class, msg); .add(StorageProcessingMessage.class, msg);
JpaInterceptorBroadcaster.doCallHooks(theInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_WARNING, params); JpaInterceptorBroadcaster.doCallHooks(theInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_WARNING, params);
retVal.addAll(theForcedIdDao.findByForcedId(nextIds)); theForcedIdDao
.findByForcedId(nextIds)
.stream()
.map(t->new ResourcePersistentId(t))
.forEach(t->retVal.add(t));
} else { } else {
retVal.addAll(theForcedIdDao.findByTypeAndForcedId(nextResourceType, nextIds));
theForcedIdDao
.findByTypeAndForcedId(nextResourceType, nextIds)
.stream()
.map(t->new ResourcePersistentId(t))
.forEach(t->retVal.add(t));
} }
} }
return retVal; return retVal;
} }
String translatePidIdToForcedId(String theResourceType, Long theId) { public IIdType translatePidIdToForcedId(FhirContext theCtx, String theResourceType, ResourcePersistentId theId) {
ForcedId forcedId = myForcedIdDao.findByResourcePid(theId); IIdType retVal = theCtx.getVersion().newIdType();
retVal.setValue(translatePidIdToForcedId(theResourceType, theId));
return retVal;
}
public String translatePidIdToForcedId(String theResourceType, ResourcePersistentId theId) {
ForcedId forcedId = myForcedIdDao.findByResourcePid(theId.getIdAsLong());
if (forcedId != null) { if (forcedId != null) {
return forcedId.getResourceType() + '/' + forcedId.getForcedId(); return forcedId.getResourceType() + '/' + forcedId.getForcedId();
} else { } else {

View File

@ -25,9 +25,9 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig; 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.MatchResourceUrlService; import ca.uhn.fhir.jpa.dao.MatchResourceUrlService;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam; import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceLink; import ca.uhn.fhir.jpa.model.entity.ResourceLink;
@ -54,7 +54,14 @@ import org.springframework.stereotype.Service;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceContextType;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
@ -238,7 +245,7 @@ public class SearchParamWithInlineReferencesExtractor {
throw new InvalidRequestException(msg); throw new InvalidRequestException(msg);
} }
Class<? extends IBaseResource> matchResourceType = matchResourceDef.getImplementingClass(); Class<? extends IBaseResource> matchResourceType = matchResourceDef.getImplementingClass();
Set<Long> matches = myMatchResourceUrlService.processMatchUrl(nextIdText, matchResourceType, theRequest); Set<ResourcePersistentId> matches = myMatchResourceUrlService.processMatchUrl(nextIdText, matchResourceType, theRequest);
if (matches.isEmpty()) { if (matches.isEmpty()) {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", nextId.getValue()); String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlNoMatches", nextId.getValue());
throw new ResourceNotFoundException(msg); throw new ResourceNotFoundException(msg);
@ -247,7 +254,7 @@ public class SearchParamWithInlineReferencesExtractor {
String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlMultipleMatches", nextId.getValue()); String msg = myContext.getLocalizer().getMessage(BaseHapiFhirDao.class, "invalidMatchUrlMultipleMatches", nextId.getValue());
throw new PreconditionFailedException(msg); throw new PreconditionFailedException(msg);
} }
Long next = matches.iterator().next(); ResourcePersistentId next = matches.iterator().next();
String newId = myIdHelperService.translatePidIdToForcedId(resourceTypeString, next); String newId = myIdHelperService.translatePidIdToForcedId(resourceTypeString, next);
ourLog.debug("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId); ourLog.debug("Replacing inline match URL[{}] with ID[{}}", nextId.getValue(), newId);
nextRef.setReference(newId); nextRef.setReference(newId);

View File

@ -33,16 +33,6 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleR4 extends BaseHapiFhirResourceDao<Bundle> { public class FhirResourceDaoBundleR4 extends BaseHapiFhirResourceDao<Bundle> {
@Override // nothing for now
protected void preProcessResourceForStorage(Bundle theResource) {
super.preProcessResourceForStorage(theResource);
Set<String> allowedBundleTypes = getConfig().getBundleTypesAllowedForStorage();
if (theResource.getType() == null || !allowedBundleTypes.contains(defaultString(theResource.getType().toCode()))) {
String message = "Unable to store a Bundle resource on this server with a Bundle.type value of: " + (theResource.getType() != null ? theResource.getType().toCode() : "(missing)");
throw new UnprocessableEntityException(message);
}
}
} }

View File

@ -20,9 +20,12 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IContextValidationSupport; import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao; import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem; import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -39,7 +42,6 @@ import org.hl7.fhir.r4.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.IdType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -60,14 +62,17 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
private ValidationSupportChain myValidationSupport; private ValidationSupportChain myValidationSupport;
@Autowired @Autowired
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc; protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
@Autowired
private FhirContext myFhirContext;
@Override @Override
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) { public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
List<IIdType> valueSetIds; List<IIdType> valueSetIds;
Set<Long> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest); Set<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
valueSetIds = new ArrayList<>(); valueSetIds = new ArrayList<>();
for (Long next : ids) { for (ResourcePersistentId next : ids) {
valueSetIds.add(new IdType("CodeSystem", next)); IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
valueSetIds.add(id);
} }
return valueSetIds; return valueSetIds;
} }
@ -132,7 +137,7 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
@ -140,7 +145,7 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
CodeSystem cs = (CodeSystem) theResource; CodeSystem cs = (CodeSystem) theResource;
addPidToResource(theEntity, theResource); addPidToResource(theEntity, theResource);
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity); myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, (ResourceTable) theEntity);
} }
return retVal; return retVal;

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement; import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget; import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
@ -157,7 +158,7 @@ public class FhirResourceDaoConceptMapR4 extends BaseHapiFhirResourceDao<Concept
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao; import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.entity.SubscriptionTable; import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -65,7 +66,7 @@ public class FhirResourceDaoSubscriptionR4 extends BaseHapiFhirResourceDao<Subsc
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.util.LogicUtil; import ca.uhn.fhir.jpa.util.LogicUtil;
@ -392,7 +393,7 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -45,7 +45,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoR4.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoR4.class);
@Autowired @Autowired
private TransactionProcessor<Bundle, BundleEntryComponent> myTransactionProcessor; private TransactionProcessor myTransactionProcessor;
@Override @Override
@PostConstruct @PostConstruct

View File

@ -30,16 +30,6 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
public class FhirResourceDaoBundleR5 extends BaseHapiFhirResourceDao<Bundle> { public class FhirResourceDaoBundleR5 extends BaseHapiFhirResourceDao<Bundle> {
@Override // nothing
protected void preProcessResourceForStorage(Bundle theResource) {
super.preProcessResourceForStorage(theResource);
Set<String> allowedBundleTypes = getConfig().getBundleTypesAllowedForStorage();
if (theResource.getType() == null || !allowedBundleTypes.contains(defaultString(theResource.getType().toCode()))) {
String message = "Unable to store a Bundle resource on this server with a Bundle.type value of: " + (theResource.getType() != null ? theResource.getType().toCode() : "(missing)");
throw new UnprocessableEntityException(message);
}
}
} }

View File

@ -20,10 +20,14 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IContextValidationSupport; import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao; import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.entity.TermCodeSystem; import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
@ -39,7 +43,6 @@ import org.hl7.fhir.r5.hapi.validation.ValidationSupportChain;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.IdType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -60,14 +63,19 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
private ValidationSupportChain myValidationSupport; private ValidationSupportChain myValidationSupport;
@Autowired @Autowired
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc; protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
@Autowired
protected IdHelperService myIdHelperService;
@Autowired
private FhirContext myFhirContext;
@Override @Override
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) { public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
List<IIdType> valueSetIds; List<IIdType> valueSetIds;
Set<Long> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest); Set<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
valueSetIds = new ArrayList<>(); valueSetIds = new ArrayList<>();
for (Long next : ids) { for (ResourcePersistentId next : ids) {
valueSetIds.add(new IdType("CodeSystem", next)); IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
valueSetIds.add(id);
} }
return valueSetIds; return valueSetIds;
} }
@ -132,7 +140,7 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (!retVal.isUnchangedInCurrentOperation()) { if (!retVal.isUnchangedInCurrentOperation()) {
@ -140,7 +148,7 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
CodeSystem cs = (CodeSystem) theResource; CodeSystem cs = (CodeSystem) theResource;
addPidToResource(theEntity, theResource); addPidToResource(theEntity, theResource);
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(cs), theEntity); myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(cs), (ResourceTable) theEntity);
} }
return retVal; return retVal;

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoConceptMap;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement; import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget; import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.term.TranslationMatch; import ca.uhn.fhir.jpa.term.TranslationMatch;
@ -158,8 +159,8 @@ public class FhirResourceDaoConceptMapR5 extends BaseHapiFhirResourceDao<Concept
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (!retVal.isUnchangedInCurrentOperation()) { if (!retVal.isUnchangedInCurrentOperation()) {

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao; import ca.uhn.fhir.jpa.dao.data.ISubscriptionTableDao;
import ca.uhn.fhir.jpa.entity.SubscriptionTable; import ca.uhn.fhir.jpa.entity.SubscriptionTable;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
@ -74,7 +75,7 @@ public class FhirResourceDaoSubscriptionR5 extends BaseHapiFhirResourceDao<Subsc
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.util.LogicUtil; import ca.uhn.fhir.jpa.util.LogicUtil;
@ -404,7 +405,7 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
} }
@Override @Override
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) { boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry); ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);

View File

@ -45,7 +45,7 @@ public class FhirSystemDaoR5 extends BaseHapiFhirSystemDao<Bundle, Meta> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoR5.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoR5.class);
@Autowired @Autowired
private TransactionProcessor<Bundle, BundleEntryComponent> myTransactionProcessor; private TransactionProcessor myTransactionProcessor;
@Override @Override
@PostConstruct @PostConstruct

View File

@ -132,12 +132,12 @@ public class DeleteConflictService {
} }
} }
public void validateDeleteConflictsEmptyOrThrowException(DeleteConflictList theDeleteConflicts) { public static void validateDeleteConflictsEmptyOrThrowException(FhirContext theFhirContext, DeleteConflictList theDeleteConflicts) {
if (theDeleteConflicts.isEmpty()) { if (theDeleteConflicts.isEmpty()) {
return; return;
} }
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(myFhirContext); IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(theFhirContext);
String firstMsg = null; String firstMsg = null;
Iterator<DeleteConflict> iterator = theDeleteConflicts.iterator(); Iterator<DeleteConflict> iterator = theDeleteConflicts.iterator();
@ -154,7 +154,7 @@ public class DeleteConflictService {
if (firstMsg == null) { if (firstMsg == null) {
firstMsg = msg; firstMsg = msg;
} }
OperationOutcomeUtil.addIssue(myFhirContext, oo, BaseHapiFhirDao.OO_SEVERITY_ERROR, msg, null, "processing"); OperationOutcomeUtil.addIssue(theFhirContext, oo, BaseHapiFhirDao.OO_SEVERITY_ERROR, msg, null, "processing");
} }
throw new ResourceVersionConflictException(firstMsg, oo); throw new ResourceVersionConflictException(firstMsg, oo);

View File

@ -42,6 +42,7 @@ import org.hl7.fhir.utilities.graphql.Value;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class JpaStorageServices extends BaseHapiFhirDao<IBaseResource> implements IGraphQLStorageServices { public class JpaStorageServices extends BaseHapiFhirDao<IBaseResource> implements IGraphQLStorageServices {
@ -145,4 +146,10 @@ public class JpaStorageServices extends BaseHapiFhirDao<IBaseResource> implement
public IBaseBundle search(Object theAppInfo, String theType, List<Argument> theSearchParams) throws FHIRException { public IBaseBundle search(Object theAppInfo, String theType, List<Argument> theSearchParams) throws FHIRException {
throw new NotImplementedOperationException("Not yet able to handle this GraphQL request"); throw new NotImplementedOperationException("Not yet able to handle this GraphQL request");
} }
@Nullable
@Override
protected String getResourceName() {
return null;
}
} }

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.interceptor;
*/ */
import ca.uhn.fhir.jpa.dao.ISearchBuilder; import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails; import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.util.ICallable; import ca.uhn.fhir.util.ICallable;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -36,12 +37,12 @@ import java.util.List;
@NotThreadSafe @NotThreadSafe
public class JpaPreResourceAccessDetails implements IPreResourceAccessDetails { public class JpaPreResourceAccessDetails implements IPreResourceAccessDetails {
private final List<Long> myResourcePids; private final List<ResourcePersistentId> myResourcePids;
private final boolean[] myBlocked; private final boolean[] myBlocked;
private final ICallable<ISearchBuilder> mySearchBuilderSupplier; private final ICallable<ISearchBuilder> mySearchBuilderSupplier;
private List<IBaseResource> myResources; private List<IBaseResource> myResources;
public JpaPreResourceAccessDetails(List<Long> theResourcePids, ICallable<ISearchBuilder> theSearchBuilderSupplier) { public JpaPreResourceAccessDetails(List<ResourcePersistentId> theResourcePids, ICallable<ISearchBuilder> theSearchBuilderSupplier) {
myResourcePids = theResourcePids; myResourcePids = theResourcePids;
myBlocked = new boolean[myResourcePids.size()]; myBlocked = new boolean[myResourcePids.size()];
mySearchBuilderSupplier = theSearchBuilderSupplier; mySearchBuilderSupplier = theSearchBuilderSupplier;

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.search;
*/ */
import ca.uhn.fhir.jpa.dao.IDao; import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -34,7 +35,7 @@ public interface ISearchCoordinatorSvc {
void cancelAllActiveSearches(); void cancelAllActiveSearches();
List<Long> getResources(String theUuid, int theFrom, int theTo, @Nullable RequestDetails theRequestDetails); List<ResourcePersistentId> getResources(String theUuid, int theFrom, int theTo, @Nullable RequestDetails theRequestDetails);
IBundleProvider registerSearch(IDao theCallingDao, SearchParameterMap theParams, String theResourceType, CacheControlDirective theCacheControlDirective, @Nullable RequestDetails theRequestDetails); IBundleProvider registerSearch(IDao theCallingDao, SearchParameterMap theParams, String theResourceType, CacheControlDirective theCacheControlDirective, @Nullable RequestDetails theRequestDetails);

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.dao.IDao; import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.ISearchBuilder; import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum; import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.jpa.model.entity.BaseHasResource; import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
@ -175,7 +176,7 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
Class<? extends IBaseResource> resourceType = myContext.getResourceDefinition(resourceName).getImplementingClass(); Class<? extends IBaseResource> resourceType = myContext.getResourceDefinition(resourceName).getImplementingClass();
sb.setType(resourceType, resourceName); sb.setType(resourceType, resourceName);
final List<Long> pidsSubList = mySearchCoordinatorSvc.getResources(myUuid, theFromIndex, theToIndex, myRequest); final List<ResourcePersistentId> pidsSubList = mySearchCoordinatorSvc.getResources(myUuid, theFromIndex, theToIndex, myRequest);
TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager); TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager);
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
@ -310,15 +311,15 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
// Note: Leave as protected, HSPC depends on this // Note: Leave as protected, HSPC depends on this
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected List<IBaseResource> toResourceList(ISearchBuilder theSearchBuilder, List<Long> thePids) { protected List<IBaseResource> toResourceList(ISearchBuilder theSearchBuilder, List<ResourcePersistentId> thePids) {
Set<Long> includedPids = new HashSet<>(); Set<ResourcePersistentId> includedPids = new HashSet<>();
if (mySearchEntity.getSearchType() == SearchTypeEnum.SEARCH) { if (mySearchEntity.getSearchType() == SearchTypeEnum.SEARCH) {
includedPids.addAll(theSearchBuilder.loadIncludes(myContext, myEntityManager, thePids, mySearchEntity.toRevIncludesList(), true, mySearchEntity.getLastUpdated(), myUuid, myRequest)); includedPids.addAll(theSearchBuilder.loadIncludes(myContext, myEntityManager, thePids, mySearchEntity.toRevIncludesList(), true, mySearchEntity.getLastUpdated(), myUuid, myRequest));
includedPids.addAll(theSearchBuilder.loadIncludes(myContext, myEntityManager, thePids, mySearchEntity.toIncludesList(), false, mySearchEntity.getLastUpdated(), myUuid, myRequest)); includedPids.addAll(theSearchBuilder.loadIncludes(myContext, myEntityManager, thePids, mySearchEntity.toIncludesList(), false, mySearchEntity.getLastUpdated(), myUuid, myRequest));
} }
List<Long> includedPidList = new ArrayList<>(includedPids); List<ResourcePersistentId> includedPidList = new ArrayList<>(includedPids);
// Execute the query and make sure we return distinct results // Execute the query and make sure we return distinct results
List<IBaseResource> resources = new ArrayList<>(); List<IBaseResource> resources = new ArrayList<>();

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.search;
import ca.uhn.fhir.jpa.dao.IDao; import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.ISearchBuilder; import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl.SearchTask; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl.SearchTask;
@ -66,7 +67,7 @@ public class PersistedJpaSearchFirstPageBundleProvider extends PersistedJpaBundl
mySearchTask.awaitInitialSync(); mySearchTask.awaitInitialSync();
ourLog.trace("Fetching search resource PIDs from task: {}", mySearchTask.getClass()); ourLog.trace("Fetching search resource PIDs from task: {}", mySearchTask.getClass());
final List<Long> pids = mySearchTask.getResourcePids(theFromIndex, theToIndex); final List<ResourcePersistentId> pids = mySearchTask.getResourcePids(theFromIndex, theToIndex);
ourLog.trace("Done fetching search resource PIDs"); ourLog.trace("Done fetching search resource PIDs");
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager); TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);

View File

@ -29,6 +29,7 @@ import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchInclude; import ca.uhn.fhir.jpa.entity.SearchInclude;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum; import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails; import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc; import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
@ -173,7 +174,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
*/ */
@Override @Override
@Transactional(propagation = Propagation.NEVER) @Transactional(propagation = Propagation.NEVER)
public List<Long> getResources(final String theUuid, int theFrom, int theTo, @Nullable RequestDetails theRequestDetails) { public List<ResourcePersistentId> getResources(final String theUuid, int theFrom, int theTo, @Nullable RequestDetails theRequestDetails) {
TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager); TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
@ -193,7 +194,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
if (myNeverUseLocalSearchForUnitTests == false) { if (myNeverUseLocalSearchForUnitTests == false) {
if (searchTask != null) { if (searchTask != null) {
ourLog.trace("Local search found"); ourLog.trace("Local search found");
List<Long> resourcePids = searchTask.getResourcePids(theFrom, theTo); List<ResourcePersistentId> resourcePids = searchTask.getResourcePids(theFrom, theTo);
ourLog.trace("Local search returned {} pids, wanted {}-{} - Search: {}", resourcePids.size(), theFrom, theTo, searchTask.getSearch()); ourLog.trace("Local search returned {} pids, wanted {}-{} - Search: {}", resourcePids.size(), theFrom, theTo, searchTask.getSearch());
/* /*
@ -249,7 +250,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
ourLog.trace("Finished looping"); ourLog.trace("Finished looping");
List<Long> pids = mySearchResultCacheSvc.fetchResultPids(search, theFrom, theTo); List<ResourcePersistentId> pids = mySearchResultCacheSvc.fetchResultPids(search, theFrom, theTo);
if (pids == null) { if (pids == null) {
throw newResourceGoneException(theUuid); throw newResourceGoneException(theUuid);
} }
@ -446,7 +447,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
return txTemplate.execute(t -> { return txTemplate.execute(t -> {
// Load the results synchronously // Load the results synchronously
final List<Long> pids = new ArrayList<>(); final List<ResourcePersistentId> pids = new ArrayList<>();
try (IResultIterator resultIter = theSb.createQuery(theParams, searchRuntimeDetails, theRequestDetails)) { try (IResultIterator resultIter = theSb.createQuery(theParams, searchRuntimeDetails, theRequestDetails)) {
while (resultIter.hasNext()) { while (resultIter.hasNext()) {
@ -485,10 +486,10 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
* On the other hand for async queries we load includes/revincludes * On the other hand for async queries we load includes/revincludes
* individually for pages as we return them to clients * individually for pages as we return them to clients
*/ */
final Set<Long> includedPids = new HashSet<>(); final Set<ResourcePersistentId> includedPids = new HashSet<>();
includedPids.addAll(theSb.loadIncludes(myContext, myEntityManager, pids, theParams.getRevIncludes(), true, theParams.getLastUpdated(), "(synchronous)", theRequestDetails)); includedPids.addAll(theSb.loadIncludes(myContext, myEntityManager, pids, theParams.getRevIncludes(), true, theParams.getLastUpdated(), "(synchronous)", theRequestDetails));
includedPids.addAll(theSb.loadIncludes(myContext, myEntityManager, pids, theParams.getIncludes(), false, theParams.getLastUpdated(), "(synchronous)", theRequestDetails)); includedPids.addAll(theSb.loadIncludes(myContext, myEntityManager, pids, theParams.getIncludes(), false, theParams.getLastUpdated(), "(synchronous)", theRequestDetails));
List<Long> includedPidsList = new ArrayList<>(includedPids); List<ResourcePersistentId> includedPidsList = new ArrayList<>(includedPids);
List<IBaseResource> resources = new ArrayList<>(); List<IBaseResource> resources = new ArrayList<>();
theSb.loadResourcesByPid(pids, includedPidsList, resources, false, theRequestDetails); theSb.loadResourcesByPid(pids, includedPidsList, resources, false, theRequestDetails);
@ -580,10 +581,10 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
private final SearchParameterMap myParams; private final SearchParameterMap myParams;
private final IDao myCallingDao; private final IDao myCallingDao;
private final String myResourceType; private final String myResourceType;
private final ArrayList<Long> mySyncedPids = new ArrayList<>(); private final ArrayList<ResourcePersistentId> mySyncedPids = new ArrayList<>();
private final CountDownLatch myInitialCollectionLatch = new CountDownLatch(1); private final CountDownLatch myInitialCollectionLatch = new CountDownLatch(1);
private final CountDownLatch myCompletionLatch; private final CountDownLatch myCompletionLatch;
private final ArrayList<Long> myUnsyncedPids = new ArrayList<>(); private final ArrayList<ResourcePersistentId> myUnsyncedPids = new ArrayList<>();
private final RequestDetails myRequest; private final RequestDetails myRequest;
private Search mySearch; private Search mySearch;
private boolean myAbortRequested; private boolean myAbortRequested;
@ -591,7 +592,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
private int myCountSavedThisPass = 0; private int myCountSavedThisPass = 0;
private int myCountBlockedThisPass = 0; private int myCountBlockedThisPass = 0;
private boolean myAdditionalPrefetchThresholdsRemaining; private boolean myAdditionalPrefetchThresholdsRemaining;
private List<Long> myPreviouslyAddedResourcePids; private List<ResourcePersistentId> myPreviouslyAddedResourcePids;
private Integer myMaxResultsToFetch; private Integer myMaxResultsToFetch;
private SearchRuntimeDetails mySearchRuntimeDetails; private SearchRuntimeDetails mySearchRuntimeDetails;
@ -635,7 +636,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
return myInitialCollectionLatch; return myInitialCollectionLatch;
} }
void setPreviouslyAddedResourcePids(List<Long> thePreviouslyAddedResourcePids) { void setPreviouslyAddedResourcePids(List<ResourcePersistentId> thePreviouslyAddedResourcePids) {
myPreviouslyAddedResourcePids = thePreviouslyAddedResourcePids; myPreviouslyAddedResourcePids = thePreviouslyAddedResourcePids;
myCountSavedTotal = myPreviouslyAddedResourcePids.size(); myCountSavedTotal = myPreviouslyAddedResourcePids.size();
} }
@ -649,7 +650,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
} }
@Nonnull @Nonnull
List<Long> getResourcePids(int theFromIndex, int theToIndex) { List<ResourcePersistentId> getResourcePids(int theFromIndex, int theToIndex) {
ourLog.debug("Requesting search PIDs from {}-{}", theFromIndex, theToIndex); ourLog.debug("Requesting search PIDs from {}-{}", theFromIndex, theToIndex);
boolean keepWaiting; boolean keepWaiting;
@ -673,6 +674,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
break; break;
case FAILED: case FAILED:
case FINISHED: case FINISHED:
case GONE:
default: default:
keepWaiting = false; keepWaiting = false;
break; break;
@ -690,7 +692,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
ourLog.debug("Proceeding, as we have {} results", mySyncedPids.size()); ourLog.debug("Proceeding, as we have {} results", mySyncedPids.size());
ArrayList<Long> retVal = new ArrayList<>(); ArrayList<ResourcePersistentId> retVal = new ArrayList<>();
synchronized (mySyncedPids) { synchronized (mySyncedPids) {
verifySearchHasntFailedOrThrowInternalErrorException(mySearch); verifySearchHasntFailedOrThrowInternalErrorException(mySearch);
@ -713,7 +715,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
txTemplate.execute(new TransactionCallbackWithoutResult() { txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override @Override
protected void doInTransactionWithoutResult(@NotNull TransactionStatus theArg0) { protected void doInTransactionWithoutResult(@Nonnull @NotNull TransactionStatus theArg0) {
doSaveSearch(); doSaveSearch();
} }
@ -725,12 +727,12 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
txTemplate.execute(new TransactionCallbackWithoutResult() { txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override @Override
protected void doInTransactionWithoutResult(@NotNull TransactionStatus theArg0) { protected void doInTransactionWithoutResult(@Nonnull @NotNull TransactionStatus theArg0) {
if (mySearch.getId() == null) { if (mySearch.getId() == null) {
doSaveSearch(); doSaveSearch();
} }
ArrayList<Long> unsyncedPids = myUnsyncedPids; ArrayList<ResourcePersistentId> unsyncedPids = myUnsyncedPids;
int countBlocked = 0; int countBlocked = 0;
// Interceptor call: STORAGE_PREACCESS_RESOURCES // Interceptor call: STORAGE_PREACCESS_RESOURCES
@ -847,7 +849,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
txTemplate.execute(new TransactionCallbackWithoutResult() { txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override @Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) { protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
doSearch(); doSearch();
} }
}); });
@ -962,7 +964,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager); TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager);
txTemplate.execute(new TransactionCallbackWithoutResult() { txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override @Override
protected void doInTransactionWithoutResult(TransactionStatus theArg0) { protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theArg0) {
mySearch.setTotalCount(count.intValue()); mySearch.setTotalCount(count.intValue());
if (wantOnlyCount) { if (wantOnlyCount) {
mySearch.setStatus(SearchStatusEnum.FINISHED); mySearch.setStatus(SearchStatusEnum.FINISHED);
@ -1093,7 +1095,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager); TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager);
txTemplate.afterPropertiesSet(); txTemplate.afterPropertiesSet();
txTemplate.execute(t -> { txTemplate.execute(t -> {
List<Long> previouslyAddedResourcePids = mySearchResultCacheSvc.fetchAllResultPids(getSearch()); List<ResourcePersistentId> previouslyAddedResourcePids = mySearchResultCacheSvc.fetchAllResultPids(getSearch());
if (previouslyAddedResourcePids == null) { if (previouslyAddedResourcePids == null) {
throw newResourceGoneException(getSearch().getUuid()); throw newResourceGoneException(getSearch().getUuid());
} }

View File

@ -20,19 +20,17 @@ package ca.uhn.fhir.jpa.search.cache;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao; import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchResult; import ca.uhn.fhir.jpa.entity.SearchResult;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -46,7 +44,7 @@ public class DatabaseSearchResultCacheSvcImpl implements ISearchResultCacheSvc {
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public List<Long> fetchResultPids(Search theSearch, int theFrom, int theTo) { public List<ResourcePersistentId> fetchResultPids(Search theSearch, int theFrom, int theTo) {
final Pageable page = toPage(theFrom, theTo); final Pageable page = toPage(theFrom, theTo);
if (page == null) { if (page == null) {
return Collections.emptyList(); return Collections.emptyList();
@ -58,28 +56,28 @@ public class DatabaseSearchResultCacheSvcImpl implements ISearchResultCacheSvc {
ourLog.debug("fetchResultPids for range {}-{} returned {} pids", theFrom, theTo, retVal.size()); ourLog.debug("fetchResultPids for range {}-{} returned {} pids", theFrom, theTo, retVal.size());
return new ArrayList<>(retVal); return ResourcePersistentId.fromLongList(retVal);
} }
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public List<Long> fetchAllResultPids(Search theSearch) { public List<ResourcePersistentId> fetchAllResultPids(Search theSearch) {
List<Long> retVal = mySearchResultDao.findWithSearchPidOrderIndependent(theSearch.getId()); List<Long> retVal = mySearchResultDao.findWithSearchPidOrderIndependent(theSearch.getId());
ourLog.trace("fetchAllResultPids returned {} pids", retVal.size()); ourLog.trace("fetchAllResultPids returned {} pids", retVal.size());
return retVal; return ResourcePersistentId.fromLongList(retVal);
} }
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public void storeResults(Search theSearch, List<Long> thePreviouslyStoredResourcePids, List<Long> theNewResourcePids) { public void storeResults(Search theSearch, List<ResourcePersistentId> thePreviouslyStoredResourcePids, List<ResourcePersistentId> theNewResourcePids) {
List<SearchResult> resultsToSave = Lists.newArrayList(); List<SearchResult> resultsToSave = Lists.newArrayList();
ourLog.trace("Storing {} results with {} previous for search", theNewResourcePids.size(), thePreviouslyStoredResourcePids.size()); ourLog.trace("Storing {} results with {} previous for search", theNewResourcePids.size(), thePreviouslyStoredResourcePids.size());
int order = thePreviouslyStoredResourcePids.size(); int order = thePreviouslyStoredResourcePids.size();
for (Long nextPid : theNewResourcePids) { for (ResourcePersistentId nextPid : theNewResourcePids) {
SearchResult nextResult = new SearchResult(theSearch); SearchResult nextResult = new SearchResult(theSearch);
nextResult.setResourcePid(nextPid); nextResult.setResourcePid(nextPid.getIdAsLong());
nextResult.setOrder(order); nextResult.setOrder(order);
resultsToSave.add(nextResult); resultsToSave.add(nextResult);
ourLog.trace("Saving ORDER[{}] Resource {}", order, nextResult.getResourcePid()); ourLog.trace("Saving ORDER[{}] Resource {}", order, nextResult.getResourcePid());
@ -90,10 +88,4 @@ public class DatabaseSearchResultCacheSvcImpl implements ISearchResultCacheSvc {
mySearchResultDao.saveAll(resultsToSave); mySearchResultDao.saveAll(resultsToSave);
} }
@VisibleForTesting
void setSearchDaoResultForUnitTest(ISearchResultDao theSearchResultDao) {
mySearchResultDao = theSearchResultDao;
}
} }

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.search.cache;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -31,7 +32,7 @@ public interface ISearchResultCacheSvc {
* @param thePreviouslyStoredResourcePids A list of resource PIDs that have previously been saved to this search * @param thePreviouslyStoredResourcePids A list of resource PIDs that have previously been saved to this search
* @param theNewResourcePids A list of new resoure PIDs to add to this search (these ones have not been previously saved) * @param theNewResourcePids A list of new resoure PIDs to add to this search (these ones have not been previously saved)
*/ */
void storeResults(Search theSearch, List<Long> thePreviouslyStoredResourcePids, List<Long> theNewResourcePids); void storeResults(Search theSearch, List<ResourcePersistentId> thePreviouslyStoredResourcePids, List<ResourcePersistentId> theNewResourcePids);
/** /**
* Fetch a sunset of the search result IDs from the cache * Fetch a sunset of the search result IDs from the cache
@ -43,7 +44,7 @@ public interface ISearchResultCacheSvc {
* have been removed from the cache for some reason, such as expiry or manual purge) * have been removed from the cache for some reason, such as expiry or manual purge)
*/ */
@Nullable @Nullable
List<Long> fetchResultPids(Search theSearch, int theFrom, int theTo); List<ResourcePersistentId> fetchResultPids(Search theSearch, int theFrom, int theTo);
/** /**
* Fetch all result PIDs for a given search with no particular order required * Fetch all result PIDs for a given search with no particular order required
@ -53,6 +54,6 @@ public interface ISearchResultCacheSvc {
* have been removed from the cache for some reason, such as expiry or manual purge) * have been removed from the cache for some reason, such as expiry or manual purge)
*/ */
@Nullable @Nullable
List<Long> fetchAllResultPids(Search theSearch); List<ResourcePersistentId> fetchAllResultPids(Search theSearch);
} }

View File

@ -25,6 +25,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.DaoRegistry; import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.sched.FireAtIntervalJob; import ca.uhn.fhir.jpa.model.sched.FireAtIntervalJob;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition; import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
@ -37,8 +38,6 @@ import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
@ -252,12 +251,12 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
toIndex = Math.min(toIndex, theJobDetails.getCurrentSearchCount()); toIndex = Math.min(toIndex, theJobDetails.getCurrentSearchCount());
} }
ourLog.info("Triggering job[{}] search {} requesting resources {} - {}", theJobDetails.getJobId(), theJobDetails.getCurrentSearchUuid(), fromIndex, toIndex); ourLog.info("Triggering job[{}] search {} requesting resources {} - {}", theJobDetails.getJobId(), theJobDetails.getCurrentSearchUuid(), fromIndex, toIndex);
List<Long> resourceIds = mySearchCoordinatorSvc.getResources(theJobDetails.getCurrentSearchUuid(), fromIndex, toIndex, null); List<ResourcePersistentId> resourceIds = mySearchCoordinatorSvc.getResources(theJobDetails.getCurrentSearchUuid(), fromIndex, toIndex, null);
ourLog.info("Triggering job[{}] delivering {} resources", theJobDetails.getJobId(), resourceIds.size()); ourLog.info("Triggering job[{}] delivering {} resources", theJobDetails.getJobId(), resourceIds.size());
int highestIndexSubmitted = theJobDetails.getCurrentSearchLastUploadedIndex(); int highestIndexSubmitted = theJobDetails.getCurrentSearchLastUploadedIndex();
for (Long next : resourceIds) { for (ResourcePersistentId next : resourceIds) {
IBaseResource nextResource = resourceDao.readByPid(next); IBaseResource nextResource = resourceDao.readByPid(next);
Future<Void> future = submitResource(theJobDetails.getSubscriptionId(), nextResource); Future<Void> future = submitResource(theJobDetails.getSubscriptionId(), nextResource);
futures.add(Pair.of(nextResource.getIdElement().getIdPart(), future)); futures.add(Pair.of(nextResource.getIdElement().getIdPart(), future));

View File

@ -33,6 +33,7 @@ import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.data.*; import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition; import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
@ -338,8 +339,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
Optional<TermValueSet> optionalTermValueSet; Optional<TermValueSet> optionalTermValueSet;
if (theValueSetToExpand.hasId()) { if (theValueSetToExpand.hasId()) {
Long valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSetToExpand.getIdElement()); ResourcePersistentId valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSetToExpand.getIdElement());
optionalTermValueSet = myValueSetDao.findByResourcePid(valueSetResourcePid); optionalTermValueSet = myValueSetDao.findByResourcePid(valueSetResourcePid.getIdAsLong());
} else if (theValueSetToExpand.hasUrl()) { } else if (theValueSetToExpand.hasUrl()) {
optionalTermValueSet = myValueSetDao.findByUrl(theValueSetToExpand.getUrl()); optionalTermValueSet = myValueSetDao.findByUrl(theValueSetToExpand.getUrl());
} else { } else {
@ -1113,8 +1114,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
@Override @Override
public boolean isValueSetPreExpandedForCodeValidation(ValueSet theValueSet) { public boolean isValueSetPreExpandedForCodeValidation(ValueSet theValueSet) {
Long valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSet.getIdElement()); ResourcePersistentId valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSet.getIdElement());
Optional<TermValueSet> optionalTermValueSet = myValueSetDao.findByResourcePid(valueSetResourcePid); Optional<TermValueSet> optionalTermValueSet = myValueSetDao.findByResourcePid(valueSetResourcePid.getIdAsLong());
if (!optionalTermValueSet.isPresent()) { if (!optionalTermValueSet.isPresent()) {
ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory code validation. {}", getValueSetInfo(theValueSet)); ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory code validation. {}", getValueSetInfo(theValueSet));
@ -1136,14 +1137,14 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Coding theCoding, CodeableConcept theCodeableConcept) { ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Coding theCoding, CodeableConcept theCodeableConcept) {
ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet.hasId(), "ValueSet.id is required"); ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSet.hasId(), "ValueSet.id is required");
Long valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSet.getIdElement()); ResourcePersistentId valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSet.getIdElement());
List<TermValueSetConcept> concepts = new ArrayList<>(); List<TermValueSetConcept> concepts = new ArrayList<>();
if (isNotBlank(theCode)) { if (isNotBlank(theCode)) {
if (isNotBlank(theSystem)) { if (Constants.codeSystemNotNeeded(theSystem)) {
concepts.addAll(myValueSetConceptDao.findByValueSetResourcePidAndCode(valueSetResourcePid.getIdAsLong(), theCode));
} else if (isNotBlank(theSystem)) {
concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, theSystem, theCode)); concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, theSystem, theCode));
} if (Constants.codeSystemNotNeeded(theSystem)) {
concepts.addAll(myValueSetConceptDao.findByValueSetResourcePidAndCode(valueSetResourcePid, theCode));
} }
} else if (theCoding != null) { } else if (theCoding != null) {
if (theCoding.hasSystem() && theCoding.hasCode()) { if (theCoding.hasSystem() && theCoding.hasCode()) {
@ -1173,9 +1174,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
return null; return null;
} }
private List<TermValueSetConcept> findByValueSetResourcePidSystemAndCode(Long theResourcePid, String theSystem, String theCode) { private List<TermValueSetConcept> findByValueSetResourcePidSystemAndCode(ResourcePersistentId theResourcePid, String theSystem, String theCode) {
List<TermValueSetConcept> retVal = new ArrayList<>(); List<TermValueSetConcept> retVal = new ArrayList<>();
Optional<TermValueSetConcept> optionalTermValueSetConcept = myValueSetConceptDao.findByValueSetResourcePidSystemAndCode(theResourcePid, theSystem, theCode); Optional<TermValueSetConcept> optionalTermValueSetConcept = myValueSetConceptDao.findByValueSetResourcePidSystemAndCode(theResourcePid.getIdAsLong(), theSystem, theCode);
optionalTermValueSetConcept.ifPresent(retVal::add); optionalTermValueSetConcept.ifPresent(retVal::add);
return retVal; return retVal;
} }

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.data.*; import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.*;
@ -114,11 +115,11 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
private IResourceTableDao myResourceTableDao; private IResourceTableDao myResourceTableDao;
@Override @Override
public Long getValueSetResourcePid(IIdType theIdType) { public ResourcePersistentId getValueSetResourcePid(IIdType theIdType) {
return getValueSetResourcePid(theIdType, null); return getValueSetResourcePid(theIdType, null);
} }
private Long getValueSetResourcePid(IIdType theIdType, RequestDetails theRequestDetails) { private ResourcePersistentId getValueSetResourcePid(IIdType theIdType, RequestDetails theRequestDetails) {
return myIdHelperService.translateForcedIdToPid(theIdType, theRequestDetails); return myIdHelperService.translateForcedIdToPid(theIdType, theRequestDetails);
} }
@ -315,7 +316,7 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
if (theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.COMPLETE || theCodeSystem.getContent() == null || theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.NOTPRESENT) { if (theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.COMPLETE || theCodeSystem.getContent() == null || theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.NOTPRESENT) {
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", theResourceEntity.getIdDt().getValue(), theCodeSystem.getContentElement().getValueAsString()); ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", theResourceEntity.getIdDt().getValue(), theCodeSystem.getContentElement().getValueAsString());
Long codeSystemResourcePid = getCodeSystemResourcePid(theCodeSystem.getIdElement()); ResourcePersistentId codeSystemResourcePid = getCodeSystemResourcePid(theCodeSystem.getIdElement());
/* /*
* If this is a not-present codesystem, we don't want to store a new version if one * If this is a not-present codesystem, we don't want to store a new version if one
@ -349,8 +350,8 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
Validate.notBlank(theCodeSystemResource.getUrl(), "theCodeSystemResource must have a URL"); Validate.notBlank(theCodeSystemResource.getUrl(), "theCodeSystemResource must have a URL");
IIdType csId = myTerminologyVersionAdapterSvc.createOrUpdateCodeSystem(theCodeSystemResource); IIdType csId = myTerminologyVersionAdapterSvc.createOrUpdateCodeSystem(theCodeSystemResource);
Long codeSystemResourcePid = myIdHelperService.translateForcedIdToPid(csId, theRequest); ResourcePersistentId codeSystemResourcePid = myIdHelperService.translateForcedIdToPid(csId, theRequest);
ResourceTable resource = myResourceTableDao.getOne(codeSystemResourcePid); ResourceTable resource = myResourceTableDao.getOne(codeSystemResourcePid.getIdAsLong());
ourLog.info("CodeSystem resource has ID: {}", csId.getValue()); ourLog.info("CodeSystem resource has ID: {}", csId.getValue());
@ -366,14 +367,14 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
@Override @Override
@Transactional(propagation = Propagation.REQUIRED) @Transactional(propagation = Propagation.REQUIRED)
public void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, TermCodeSystemVersion theCodeSystemVersion, ResourceTable theCodeSystemResourceTable) { public void storeNewCodeSystemVersion(ResourcePersistentId theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, TermCodeSystemVersion theCodeSystemVersion, ResourceTable theCodeSystemResourceTable) {
ourLog.debug("Storing code system"); ourLog.debug("Storing code system");
ValidateUtil.isTrueOrThrowInvalidRequest(theCodeSystemVersion.getResource() != null, "No resource supplied"); ValidateUtil.isTrueOrThrowInvalidRequest(theCodeSystemVersion.getResource() != null, "No resource supplied");
ValidateUtil.isNotBlankOrThrowInvalidRequest(theSystemUri, "No system URI supplied"); ValidateUtil.isNotBlankOrThrowInvalidRequest(theSystemUri, "No system URI supplied");
// Grab the existing versions so we can delete them later // Grab the existing versions so we can delete them later
List<TermCodeSystemVersion> existing = myCodeSystemVersionDao.findByCodeSystemResourcePid(theCodeSystemResourcePid); List<TermCodeSystemVersion> existing = myCodeSystemVersionDao.findByCodeSystemResourcePid(theCodeSystemResourcePid.getIdAsLong());
/* /*
* For now we always delete old versions. At some point it would be nice to allow configuration to keep old versions. * For now we always delete old versions. At some point it would be nice to allow configuration to keep old versions.
@ -598,11 +599,11 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
} }
private Long getCodeSystemResourcePid(IIdType theIdType) { private ResourcePersistentId getCodeSystemResourcePid(IIdType theIdType) {
return getCodeSystemResourcePid(theIdType, null); return getCodeSystemResourcePid(theIdType, null);
} }
private Long getCodeSystemResourcePid(IIdType theIdType, RequestDetails theRequestDetails) { private ResourcePersistentId getCodeSystemResourcePid(IIdType theIdType, RequestDetails theRequestDetails) {
return myIdHelperService.translateForcedIdToPid(theIdType, theRequestDetails); return myIdHelperService.translateForcedIdToPid(theIdType, theRequestDetails);
} }
@ -676,10 +677,10 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
} }
@Nonnull @Nonnull
private TermCodeSystem getOrCreateTermCodeSystem(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, ResourceTable theCodeSystemResourceTable) { private TermCodeSystem getOrCreateTermCodeSystem(ResourcePersistentId theCodeSystemResourcePid, String theSystemUri, String theSystemName, ResourceTable theCodeSystemResourceTable) {
TermCodeSystem codeSystem = myCodeSystemDao.findByCodeSystemUri(theSystemUri); TermCodeSystem codeSystem = myCodeSystemDao.findByCodeSystemUri(theSystemUri);
if (codeSystem == null) { if (codeSystem == null) {
codeSystem = myCodeSystemDao.findByResourcePid(theCodeSystemResourcePid); codeSystem = myCodeSystemDao.findByResourcePid(theCodeSystemResourcePid.getIdAsLong());
if (codeSystem == null) { if (codeSystem == null) {
codeSystem = new TermCodeSystem(); codeSystem = new TermCodeSystem();
} }

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.term.api;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.entity.TermCodeSystem; import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
@ -40,7 +41,7 @@ public interface ITermCodeSystemStorageSvc {
void deleteCodeSystem(TermCodeSystem theCodeSystem); void deleteCodeSystem(TermCodeSystem theCodeSystem);
void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, TermCodeSystemVersion theCodeSystemVersion, ResourceTable theCodeSystemResourceTable); void storeNewCodeSystemVersion(ResourcePersistentId theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, TermCodeSystemVersion theCodeSystemVersion, ResourceTable theCodeSystemResourceTable);
/** /**
* @return Returns the ID of the created/updated code system * @return Returns the ID of the created/updated code system
@ -55,5 +56,5 @@ public interface ITermCodeSystemStorageSvc {
int saveConcept(TermConcept theNextConcept); int saveConcept(TermConcept theNextConcept);
Long getValueSetResourcePid(IIdType theIdElement); ResourcePersistentId getValueSetResourcePid(IIdType theIdElement);
} }

View File

@ -24,7 +24,7 @@ import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*; import static org.junit.Assert.fail;
@Configuration @Configuration
@Import(TestJPAConfig.class) @Import(TestJPAConfig.class)

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.dstu2; package ca.uhn.fhir.jpa.dao.dstu2;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants; import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao; import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao;
@ -1537,7 +1538,7 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
String methodName = "testSearchValueQuantity"; String methodName = "testSearchValueQuantity";
QuantityParam param; QuantityParam param;
Set<Long> found; Set<ResourcePersistentId> found;
param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null); param = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, new BigDecimal("10"), null, null);
found = myObservationDao.searchForIds(new SearchParameterMap("value-quantity", param), null); found = myObservationDao.searchForIds(new SearchParameterMap("value-quantity", param), null);
int initialSize = found.size(); int initialSize = found.size();

View File

@ -3,7 +3,7 @@ package ca.uhn.fhir.jpa.dao.dstu2;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.JpaResourceDao; import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3Test; import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3Test;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum; import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
@ -221,8 +221,8 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertThat(toUnqualifiedVersionlessIdValues(found), hasItem(id2.getValue())); assertThat(toUnqualifiedVersionlessIdValues(found), hasItem(id2.getValue()));
} }
{ {
Set<Long> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2016-01-02")), null); Set<ResourcePersistentId> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2016-01-02")), null);
assertThat(found, not(hasItem(id2.getIdPartAsLong()))); assertThat(ResourcePersistentId.toLongList(found), not(hasItem(id2.getIdPartAsLong())));
} }
} }
@ -1548,7 +1548,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
"}\n"; "}\n";
//@formatter:on //@formatter:on
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null);
int initial = val.size(); int initial = val.size();
Organization org = myFhirCtx.newJsonParser().parseResource(Organization.class, inputStr); Organization org = myFhirCtx.newJsonParser().parseResource(Organization.class, inputStr);
@ -2677,7 +2677,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
assertThat(str.length(), greaterThan(ResourceIndexedSearchParamString.MAX_LENGTH)); assertThat(str.length(), greaterThan(ResourceIndexedSearchParamString.MAX_LENGTH));
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null);
int initial = val.size(); int initial = val.size();
myOrganizationDao.create(org, mySrd); myOrganizationDao.create(org, mySrd);
@ -2825,7 +2825,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
String subStr1 = longStr1.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH); String subStr1 = longStr1.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
String subStr2 = longStr2.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH); String subStr2 = longStr2.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("type", new IdentifierDt(subStr1, subStr2)), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("type", new IdentifierDt(subStr1, subStr2)), null);
int initial = val.size(); int initial = val.size();
myOrganizationDao.create(org, mySrd); myOrganizationDao.create(org, mySrd);

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.dstu2; package ca.uhn.fhir.jpa.dao.dstu2;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag; import ca.uhn.fhir.model.api.Tag;
@ -166,9 +167,9 @@ public class FhirResourceDaoDstu2UpdateTest extends BaseJpaDstu2Test {
p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB"); p2.addName().addFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB");
myPatientDao.create(p2, mySrd); myPatientDao.create(p2, mySrd);
Set<Long> ids = myPatientDao.searchForIds(new SearchParameterMap(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2AAA")), null); Set<ResourcePersistentId> ids = myPatientDao.searchForIds(new SearchParameterMap(Patient.SP_GIVEN, new StringDt("testUpdateMaintainsSearchParamsDstu2AAA")), null);
assertEquals(1, ids.size()); assertEquals(1, ids.size());
assertThat(ids, contains(p1id.getIdPartAsLong())); assertThat(ResourcePersistentId.toLongList(ids), contains(p1id.getIdPartAsLong()));
// Update the name // Update the name
p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsDstu2BBB"); p1.getNameFirstRep().getGivenFirstRep().setValue("testUpdateMaintainsSearchParamsDstu2BBB");

View File

@ -6,6 +6,7 @@ import static org.junit.Assert.assertThat;
import java.util.List; import java.util.List;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -65,8 +66,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// OR // OR
{ {
@ -74,8 +75,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// AND // AND
{ {
@ -84,8 +85,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// AND OR // AND OR
{ {
@ -94,8 +95,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// All Resource Types // All Resource Types
{ {
@ -103,8 +104,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")).addOr(new StringParam("DDD"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")).addOr(new StringParam("DDD")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(null, map); List<ResourcePersistentId> found = mySearchDao.search(null, map);
assertThat(found, containsInAnyOrder(id1, id2, id3)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2, id3));
} }
} }
@ -133,8 +134,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// OR // OR
{ {
@ -142,8 +143,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// AND // AND
{ {
@ -152,8 +153,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// AND OR // AND OR
{ {
@ -162,8 +163,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// Tag Contents // Tag Contents
{ {
@ -171,8 +172,8 @@ public class FhirSearchDaoDstu2Test extends BaseJpaDstu2Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("div"))); content.addAnd(new StringOrListParam().addOr(new StringParam("div")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, empty()); assertThat(ResourcePersistentId.toLongList(found), empty());
} }
} }

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
@ -101,7 +102,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA"); TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
parentC.addChild(childCA, RelationshipTypeEnum.ISA); parentC.addChild(childCA, RelationshipTypeEnum.ISA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return codeSystem; return codeSystem;
} }
@ -132,7 +133,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
parentB.addChild(childI, RelationshipTypeEnum.ISA); parentB.addChild(childI, RelationshipTypeEnum.ISA);
} }
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
} }
private void createExternalCsAndLocalVs() { private void createExternalCsAndLocalVs() {
@ -167,7 +168,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle"); TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
dogs.addChild(beagle, RelationshipTypeEnum.ISA); dogs.addChild(beagle, RelationshipTypeEnum.ISA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM,"SYSTEM NAME", "SYSTEM VERSION" , cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM,"SYSTEM NAME", "SYSTEM VERSION" , cs, table);
return codeSystem; return codeSystem;
} }
@ -686,7 +687,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
cs.setResource(table); cs.setResource(table);
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A"); TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
cs.getConcepts().add(parentA); cs.getConcepts().add(parentA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs, table);
StringType code = new StringType("ParentA"); StringType code = new StringType("ParentA");
StringType system = new StringType("http://snomed.info/sct"); StringType system = new StringType("http://snomed.info/sct");

View File

@ -4,6 +4,7 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum; import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants; import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
@ -43,6 +44,7 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;
@ -214,12 +216,12 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
IIdType id2 = myObservationDao.create(o2, mySrd).getId(); IIdType id2 = myObservationDao.create(o2, mySrd).getId();
{ {
Set<Long> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2001-01-02")), null); Set<ResourcePersistentId> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2001-01-02")), null);
assertThat(found, hasItem(id2.getIdPartAsLong())); assertThat(ResourcePersistentId.toLongList(found), hasItem(id2.getIdPartAsLong()));
} }
{ {
Set<Long> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2016-01-02")), null); Set<ResourcePersistentId> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2016-01-02")), null);
assertThat(found, not(hasItem(id2.getIdPartAsLong()))); assertThat(ResourcePersistentId.toLongList(found), not(hasItem(id2.getIdPartAsLong())));
} }
} }
@ -421,7 +423,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
String name = "profiles-resources"; String name = "profiles-resources";
ourLog.info("Uploading " + name); ourLog.info("Uploading " + name);
String vsContents; String vsContents;
vsContents = IOUtils.toString(FhirResourceDaoDstu3Test.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/profile/" + name + ".xml"), "UTF-8"); vsContents = IOUtils.toString(FhirResourceDaoDstu3Test.class.getResourceAsStream("/org/hl7/fhir/dstu3/model/profile/" + name + ".xml"), StandardCharsets.UTF_8);
bundle = myFhirCtx.newXmlParser().parseResource(org.hl7.fhir.dstu3.model.Bundle.class, vsContents); bundle = myFhirCtx.newXmlParser().parseResource(org.hl7.fhir.dstu3.model.Bundle.class, vsContents);
for (BundleEntryComponent i : bundle.getEntry()) { for (BundleEntryComponent i : bundle.getEntry()) {
@ -603,13 +605,13 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
* be fixed. * be fixed.
*/ */
assertEquals(org.hl7.fhir.dstu2.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR); assertEquals(org.hl7.fhir.dstu2.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR);
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_ERROR); assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR);
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR); assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.ERROR.toCode(), BaseHapiFhirDao.OO_SEVERITY_ERROR);
assertEquals(org.hl7.fhir.dstu2.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO); assertEquals(org.hl7.fhir.dstu2.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO);
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_INFO); assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO);
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO); assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.INFORMATION.toCode(), BaseHapiFhirDao.OO_SEVERITY_INFO);
assertEquals(org.hl7.fhir.dstu2.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN); assertEquals(org.hl7.fhir.dstu2.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirResourceDao.OO_SEVERITY_WARN); assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN); assertEquals(org.hl7.fhir.dstu3.model.OperationOutcome.IssueSeverity.WARNING.toCode(), BaseHapiFhirDao.OO_SEVERITY_WARN);
} }
@ -985,7 +987,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
@Test @Test
public void testDeleteResource() { public void testDeleteResource() {
int initialHistory = myPatientDao.history((Date) null, null, mySrd).size(); int initialHistory = myPatientDao.history(null, null, mySrd).size();
IIdType id1; IIdType id1;
IIdType id2; IIdType id2;
@ -1007,7 +1009,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
patient.addIdentifier().setSystem("ZZZZZZZ").setValue("ZZZZZZZZZ"); patient.addIdentifier().setSystem("ZZZZZZZ").setValue("ZZZZZZZZZ");
id2b = myPatientDao.update(patient, mySrd).getId(); id2b = myPatientDao.update(patient, mySrd).getId();
} }
ourLog.info("ID1:{} ID2:{} ID2b:{}", new Object[]{id1, id2, id2b}); ourLog.info("ID1:{} ID2:{} ID2b:{}", id1, id2, id2b);
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronous(true); params.setLoadSynchronous(true);
@ -1028,7 +1030,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
// good // good
} }
IBundleProvider history = myPatientDao.history((Date) null, null, mySrd); IBundleProvider history = myPatientDao.history(null, null, mySrd);
assertEquals(4 + initialHistory, history.size().intValue()); assertEquals(4 + initialHistory, history.size().intValue());
List<IBaseResource> resources = history.getResources(0, 4); List<IBaseResource> resources = history.getResources(0, 4);
assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) resources.get(0))); assertNotNull(ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) resources.get(0)));
@ -1400,7 +1402,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
} }
// By type // By type
history = myPatientDao.history((Date) null, null, mySrd); history = myPatientDao.history(null, null, mySrd);
assertEquals(fullSize + 1, history.size().intValue()); assertEquals(fullSize + 1, history.size().intValue());
for (int i = 0; i < fullSize; i++) { for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue(); String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
@ -1467,7 +1469,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
} }
// By type // By type
history = myPatientDao.history((Date) null, null, mySrd); history = myPatientDao.history(null, null, mySrd);
assertEquals(fullSize + 1, history.size().intValue()); assertEquals(fullSize + 1, history.size().intValue());
for (int i = 0; i < fullSize; i++) { for (int i = 0; i < fullSize; i++) {
String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue(); String expected = id.withVersion(Integer.toString(fullSize + 1 - i)).getValue();
@ -1524,7 +1526,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
inPatient.getMeta().addProfile("http://example.com/1"); inPatient.getMeta().addProfile("http://example.com/1");
IIdType id = myPatientDao.create(inPatient, mySrd).getId().toUnqualifiedVersionless(); IIdType id = myPatientDao.create(inPatient, mySrd).getId().toUnqualifiedVersionless();
IBundleProvider history = myPatientDao.history((Date) null, null, mySrd); IBundleProvider history = myPatientDao.history(null, null, mySrd);
assertEquals(1, history.size().intValue()); assertEquals(1, history.size().intValue());
Patient outPatient = (Patient) history.getResources(0, 1).get(0); Patient outPatient = (Patient) history.getResources(0, 1).get(0);
assertEquals("version1", inPatient.getName().get(0).getFamily()); assertEquals("version1", inPatient.getName().get(0).getFamily());
@ -1538,7 +1540,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
inPatient.getMeta().addProfile("http://example.com/2"); inPatient.getMeta().addProfile("http://example.com/2");
myPatientDao.metaAddOperation(id, inPatient.getMeta(), mySrd); myPatientDao.metaAddOperation(id, inPatient.getMeta(), mySrd);
history = myPatientDao.history((Date) null, null, mySrd); history = myPatientDao.history(null, null, mySrd);
assertEquals(1, history.size().intValue()); assertEquals(1, history.size().intValue());
outPatient = (Patient) history.getResources(0, 1).get(0); outPatient = (Patient) history.getResources(0, 1).get(0);
assertEquals("version1", inPatient.getName().get(0).getFamily()); assertEquals("version1", inPatient.getName().get(0).getFamily());
@ -1554,7 +1556,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
inPatient.getName().get(0).setFamily("version2"); inPatient.getName().get(0).setFamily("version2");
myPatientDao.update(inPatient, mySrd); myPatientDao.update(inPatient, mySrd);
history = myPatientDao.history((Date) null, null, mySrd); history = myPatientDao.history(null, null, mySrd);
assertEquals(2, history.size().intValue()); assertEquals(2, history.size().intValue());
outPatient = (Patient) history.getResources(0, 2).get(0); outPatient = (Patient) history.getResources(0, 2).get(0);
assertEquals("version2", outPatient.getName().get(0).getFamily()); assertEquals("version2", outPatient.getName().get(0).getFamily());
@ -1582,9 +1584,9 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
IBundleProvider history = myPatientDao.history(id, null, null, mySrd); IBundleProvider history = myPatientDao.history(id, null, null, mySrd);
List<IBaseResource> entries = history.getResources(0, 3); List<IBaseResource> entries = history.getResources(0, 3);
ourLog.info(((IAnyResource) entries.get(0)).getIdElement() + " - " + ((IAnyResource) entries.get(0)).getMeta().getLastUpdated()); ourLog.info(entries.get(0).getIdElement() + " - " + entries.get(0).getMeta().getLastUpdated());
ourLog.info(((IAnyResource) entries.get(1)).getIdElement() + " - " + ((IAnyResource) entries.get(1)).getMeta().getLastUpdated()); ourLog.info(entries.get(1).getIdElement() + " - " + entries.get(1).getMeta().getLastUpdated());
ourLog.info(((IAnyResource) entries.get(2)).getIdElement() + " - " + ((IAnyResource) entries.get(2)).getMeta().getLastUpdated()); ourLog.info(entries.get(2).getIdElement() + " - " + entries.get(2).getMeta().getLastUpdated());
assertEquals(3, history.size().intValue()); assertEquals(3, history.size().intValue());
assertEquals(id.withVersion("3"), entries.get(0).getIdElement()); assertEquals(id.withVersion("3"), entries.get(0).getIdElement());
@ -1648,7 +1650,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
// No since // No since
IBundleProvider history = myPatientDao.history((Date) null, null, mySrd); IBundleProvider history = myPatientDao.history(null, null, mySrd);
assertEquals(1, history.size().intValue()); assertEquals(1, history.size().intValue());
Patient outPatient = (Patient) history.getResources(0, 1).get(0); Patient outPatient = (Patient) history.getResources(0, 1).get(0);
assertEquals("version1", inPatient.getName().get(0).getFamily()); assertEquals("version1", inPatient.getName().get(0).getFamily());
@ -1999,7 +2001,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
"}\n"; "}\n";
//@formatter:on //@formatter:on
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null);
int initial = val.size(); int initial = val.size();
Organization org = myFhirCtx.newJsonParser().parseResource(Organization.class, inputStr); Organization org = myFhirCtx.newJsonParser().parseResource(Organization.class, inputStr);
@ -2050,7 +2052,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
dr01.setSubject(new Reference(patientId01)); dr01.setSubject(new Reference(patientId01));
IIdType drId01 = myDiagnosticReportDao.create(dr01, mySrd).getId(); IIdType drId01 = myDiagnosticReportDao.create(dr01, mySrd).getId();
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", new Object[]{patientId01, patientId02, obsId01, obsId02, drId01}); ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", patientId01, patientId02, obsId01, obsId02, drId01);
List<Observation> result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getIdPart())).setLoadSynchronous(true))); List<Observation> result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getIdPart())).setLoadSynchronous(true)));
assertEquals(1, result.size()); assertEquals(1, result.size());
@ -2061,7 +2063,6 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
assertEquals(obsId02.getIdPart(), result.get(0).getIdElement().getIdPart()); assertEquals(obsId02.getIdPart(), result.get(0).getIdElement().getIdPart());
result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam("999999999999")).setLoadSynchronous(true))); result = toList(myObservationDao.search(new SearchParameterMap(Observation.SP_SUBJECT, new ReferenceParam("999999999999")).setLoadSynchronous(true)));
;
assertEquals(0, result.size()); assertEquals(0, result.size());
} }
@ -2145,7 +2146,6 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
TokenParam value = new TokenParam("urn:system", "001testPersistSearchParams"); TokenParam value = new TokenParam("urn:system", "001testPersistSearchParams");
List<Patient> found = toList(myPatientDao.search(new SearchParameterMap(Patient.SP_IDENTIFIER, value).setLoadSynchronous(true))); List<Patient> found = toList(myPatientDao.search(new SearchParameterMap(Patient.SP_IDENTIFIER, value).setLoadSynchronous(true)));
;
assertEquals(1, found.size()); assertEquals(1, found.size());
assertEquals(id, found.get(0).getIdElement().getIdPartAsLong().longValue()); assertEquals(id, found.get(0).getIdElement().getIdPartAsLong().longValue());
@ -2402,7 +2402,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
id1 = myPatientDao.create(patient, mySrd).getId(); id1 = myPatientDao.create(patient, mySrd).getId();
Meta metaAdd = new Meta(); Meta metaAdd = new Meta();
metaAdd.addTag().setSystem((String) null).setCode("Dog").setDisplay("Puppies"); metaAdd.addTag().setSystem(null).setCode("Dog").setDisplay("Puppies");
metaAdd.addSecurity().setSystem("seclabel:sys:1").setCode("seclabel:code:1").setDisplay("seclabel:dis:1"); metaAdd.addSecurity().setSystem("seclabel:sys:1").setCode("seclabel:code:1").setDisplay("seclabel:dis:1");
metaAdd.addProfile("http://profile/1"); metaAdd.addProfile("http://profile/1");
myPatientDao.metaAddOperation(id1, metaAdd, mySrd); myPatientDao.metaAddOperation(id1, metaAdd, mySrd);
@ -2472,7 +2472,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
{ {
Meta metaDel = new Meta(); Meta metaDel = new Meta();
metaDel.addTag().setSystem((String) null).setCode("Dog"); metaDel.addTag().setSystem(null).setCode("Dog");
metaDel.addSecurity().setSystem("seclabel:sys:1").setCode("seclabel:code:1"); metaDel.addSecurity().setSystem("seclabel:sys:1").setCode("seclabel:code:1");
metaDel.addProfile("http://profile/1"); metaDel.addProfile("http://profile/1");
myPatientDao.metaDeleteOperation(id1, metaDel, mySrd); myPatientDao.metaDeleteOperation(id1, metaDel, mySrd);
@ -3192,7 +3192,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
assertThat(str.length(), greaterThan(ResourceIndexedSearchParamString.MAX_LENGTH)); assertThat(str.length(), greaterThan(ResourceIndexedSearchParamString.MAX_LENGTH));
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null);
int initial = val.size(); int initial = val.size();
myOrganizationDao.create(org, mySrd); myOrganizationDao.create(org, mySrd);
@ -3371,7 +3371,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
String subStr1 = longStr1.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH); String subStr1 = longStr1.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
String subStr2 = longStr2.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH); String subStr2 = longStr2.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("type", new TokenParam(subStr1, subStr2)), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("type", new TokenParam(subStr1, subStr2)), null);
int initial = val.size(); int initial = val.size();
myOrganizationDao.create(org, mySrd); myOrganizationDao.create(org, mySrd);

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.dao.dstu3; package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
@ -41,7 +42,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
} }
@Test @Test
public void testCreateAndUpdateWithoutRequest() throws Exception { public void testCreateAndUpdateWithoutRequest() {
String methodName = "testUpdateByUrl"; String methodName = "testUpdateByUrl";
Patient p = new Patient(); Patient p = new Patient();
@ -447,9 +448,9 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
p2.addName().setFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB"); p2.addName().setFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB");
myPatientDao.create(p2, mySrd).getId(); myPatientDao.create(p2, mySrd).getId();
Set<Long> ids = myPatientDao.searchForIds(new SearchParameterMap(Patient.SP_GIVEN, new StringParam("testUpdateMaintainsSearchParamsDstu2AAA")), null); Set<ResourcePersistentId> ids = myPatientDao.searchForIds(new SearchParameterMap(Patient.SP_GIVEN, new StringParam("testUpdateMaintainsSearchParamsDstu2AAA")), null);
assertEquals(1, ids.size()); assertEquals(1, ids.size());
assertThat(ids, contains(p1id.getIdPartAsLong())); assertThat(ResourcePersistentId.toLongList(ids), contains(p1id.getIdPartAsLong()));
// Update the name // Update the name
p1.getName().get(0).getGiven().get(0).setValue("testUpdateMaintainsSearchParamsDstu2BBB"); p1.getName().get(0).getGiven().get(0).setValue("testUpdateMaintainsSearchParamsDstu2BBB");
@ -503,7 +504,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
{ {
Patient p1 = myPatientDao.read(p1id, mySrd); Patient p1 = myPatientDao.read(p1id, mySrd);
List<Coding> tagList = p1.getMeta().getTag(); List<Coding> tagList = p1.getMeta().getTag();
Set<String> secListValues = new HashSet<String>(); Set<String> secListValues = new HashSet<>();
for (Coding next : tagList) { for (Coding next : tagList) {
secListValues.add(next.getSystemElement().getValue() + "|" + next.getCodeElement().getValue()); secListValues.add(next.getSystemElement().getValue() + "|" + next.getCodeElement().getValue());
} }
@ -528,7 +529,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
Patient patient = new Patient(); Patient patient = new Patient();
patient.addName().setFamily(name); patient.addName().setFamily(name);
List<IdType> tl = new ArrayList<IdType>(); List<IdType> tl = new ArrayList<>();
tl.add(new IdType("http://foo/bar")); tl.add(new IdType("http://foo/bar"));
patient.getMeta().getProfile().addAll(tl); patient.getMeta().getProfile().addAll(tl);
@ -549,7 +550,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
patient.setId(id); patient.setId(id);
patient.addName().setFamily(name); patient.addName().setFamily(name);
List<IdType> tl = new ArrayList<IdType>(); List<IdType> tl = new ArrayList<>();
tl.add(new IdType("http://foo/baz")); tl.add(new IdType("http://foo/baz"));
patient.getMeta().getProfile().clear(); patient.getMeta().getProfile().clear();
patient.getMeta().getProfile().addAll(tl); patient.getMeta().getProfile().addAll(tl);

View File

@ -6,6 +6,7 @@ import static org.junit.Assert.assertThat;
import java.util.List; import java.util.List;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import org.hl7.fhir.dstu3.model.Organization; import org.hl7.fhir.dstu3.model.Organization;
import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.Patient;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -65,8 +66,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// OR // OR
{ {
@ -74,8 +75,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// AND // AND
{ {
@ -84,8 +85,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// AND OR // AND OR
{ {
@ -94,8 +95,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// All Resource Types // All Resource Types
{ {
@ -103,8 +104,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")).addOr(new StringParam("DDD"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")).addOr(new StringParam("DDD")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(null, map); List<ResourcePersistentId> found = mySearchDao.search(null, map);
assertThat(found, containsInAnyOrder(id1, id2, id3)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2, id3));
} }
} }
@ -138,8 +139,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// OR // OR
{ {
@ -147,8 +148,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// AND // AND
{ {
@ -157,8 +158,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// AND OR // AND OR
{ {
@ -167,8 +168,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// Tag Contents // Tag Contents
{ {
@ -176,8 +177,8 @@ public class FhirSearchDaoDstu3Test extends BaseJpaDstu3Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("div"))); content.addAnd(new StringOrListParam().addOr(new StringParam("div")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, empty()); assertThat(ResourcePersistentId.toLongList(found), empty());
} }
} }

View File

@ -22,7 +22,7 @@ import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.search.warm.ICacheWarmingSvc; import ca.uhn.fhir.jpa.search.warm.ICacheWarmingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.BaseSearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry; import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl; import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
import ca.uhn.fhir.jpa.term.TermDeferredStorageSvcImpl; import ca.uhn.fhir.jpa.term.TermDeferredStorageSvcImpl;
@ -277,7 +277,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Qualifier("mySearchParameterDaoR4") @Qualifier("mySearchParameterDaoR4")
protected IFhirResourceDao<SearchParameter> mySearchParameterDao; protected IFhirResourceDao<SearchParameter> mySearchParameterDao;
@Autowired @Autowired
protected BaseSearchParamRegistry mySearchParamRegistry; protected SearchParamRegistryImpl mySearchParamRegistry;
@Autowired @Autowired
protected IStaleSearchDeletingSvc myStaleSearchDeletingSvc; protected IStaleSearchDeletingSvc myStaleSearchDeletingSvc;
@Autowired @Autowired

View File

@ -19,6 +19,7 @@ import org.junit.Test;
import java.util.List; import java.util.List;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -43,7 +44,7 @@ public class FhirResourceDaoCreatePlaceholdersR4Test extends BaseJpaR4Test {
myObservationDao.create(o, mySrd); myObservationDao.create(o, mySrd);
fail(); fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("Resource Patient/FOO not found, specified in path: Observation.subject", e.getMessage()); assertThat(e.getMessage(), startsWith("Resource Patient/FOO not found, specified in path: Observation.subject"));
} }
} }
@ -98,7 +99,7 @@ public class FhirResourceDaoCreatePlaceholdersR4Test extends BaseJpaR4Test {
myObservationDao.update(o, mySrd); myObservationDao.update(o, mySrd);
fail(); fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("Resource Patient/FOO not found, specified in path: Observation.subject", e.getMessage()); assertThat(e.getMessage(), startsWith("Resource Patient/FOO not found, specified in path: Observation.subject"));
} }
} }

View File

@ -32,12 +32,14 @@ public class FhirResourceDaoR4DeleteTest extends BaseJpaR4Test {
runInTransaction(()->{ runInTransaction(()->{
ResourceTable resourceTable = myResourceTableDao.findById(id.getIdPartAsLong()).get(); ResourceTable resourceTable = myResourceTableDao.findById(id.getIdPartAsLong()).get();
assertNotNull(resourceTable.getDeleted()); assertNotNull(resourceTable.getDeleted());
assertTrue(resourceTable.isDeleted());
}); });
// Current version should be marked as deleted // Current version should be marked as deleted
runInTransaction(()->{ runInTransaction(()->{
ResourceHistoryTable resourceTable = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(id.getIdPartAsLong(), 1); ResourceHistoryTable resourceTable = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(id.getIdPartAsLong(), 1);
assertNull(resourceTable.getDeleted()); assertNull(resourceTable.getDeleted());
assertNotNull(resourceTable.getPersistentId());
}); });
runInTransaction(()->{ runInTransaction(()->{
ResourceHistoryTable resourceTable = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(id.getIdPartAsLong(), 2); ResourceHistoryTable resourceTable = myResourceHistoryTableDao.findForIdAndVersionAndFetchProvenance(id.getIdPartAsLong(), 2);

View File

@ -3867,6 +3867,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
result = myValueSetDao.search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/FOOOOOO"))); result = myValueSetDao.search(new SearchParameterMap().setLoadSynchronous(true).add(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/FOOOOOO")));
assertThat(toUnqualifiedVersionlessIds(result), empty()); assertThat(toUnqualifiedVersionlessIds(result), empty());
} }
@Test @Test

View File

@ -8,6 +8,7 @@ import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
@ -181,7 +182,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchTest extends BaseJpaTest {
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA"); TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
parentC.addChild(childCA, TermConceptParentChildLink.RelationshipTypeEnum.ISA); parentC.addChild(childCA, TermConceptParentChildLink.RelationshipTypeEnum.ISA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return codeSystem; return codeSystem;
} }
@ -199,7 +200,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchTest extends BaseJpaTest {
} }
private ArrayList<String> toCodesContains(List<ValueSet.ValueSetExpansionContainsComponent> theContains) { private ArrayList<String> toCodesContains(List<ValueSet.ValueSetExpansionContainsComponent> theContains) {
ArrayList<String> retVal = new ArrayList<String>(); ArrayList<String> retVal = new ArrayList<>();
for (ValueSet.ValueSetExpansionContainsComponent next : theContains) { for (ValueSet.ValueSetExpansionContainsComponent next : theContains) {
retVal.add(next.getCode()); retVal.add(next.getCode());
} }

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
@ -95,7 +96,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA"); TermConcept childCA = new TermConcept(cs, "childCA").setDisplay("Child CA");
parentC.addChild(childCA, RelationshipTypeEnum.ISA); parentC.addChild(childCA, RelationshipTypeEnum.ISA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return codeSystem; return codeSystem;
} }
@ -131,7 +132,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle"); TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle");
dogs.addChild(beagle, RelationshipTypeEnum.ISA); dogs.addChild(beagle, RelationshipTypeEnum.ISA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return codeSystem; return codeSystem;
} }
@ -162,7 +163,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
parentB.addChild(childI, RelationshipTypeEnum.ISA); parentB.addChild(childI, RelationshipTypeEnum.ISA);
} }
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
} }
private void createLocalCsAndVs() { private void createLocalCsAndVs() {
@ -474,7 +475,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
concept = new TermConcept(cs, "LA9999-7"); concept = new TermConcept(cs, "LA9999-7");
cs.getConcepts().add(concept); cs.getConcepts().add(concept);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
ValueSet valueSet = new ValueSet(); ValueSet valueSet = new ValueSet();
valueSet.setUrl(URL_MY_VALUE_SET); valueSet.setUrl(URL_MY_VALUE_SET);
@ -801,7 +802,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
cs.setResource(table); cs.setResource(table);
TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A"); TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A");
cs.getConcepts().add(parentA); cs.getConcepts().add(parentA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs, table);
StringType code = new StringType("ParentA"); StringType code = new StringType("ParentA");
StringType system = new StringType("http://snomed.info/sct"); StringType system = new StringType("http://snomed.info/sct");

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.*; import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
@ -317,12 +318,12 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
IIdType id2 = myObservationDao.create(o2, mySrd).getId(); IIdType id2 = myObservationDao.create(o2, mySrd).getId();
{ {
Set<Long> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2001-01-02")), null); Set<ResourcePersistentId> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2001-01-02")), null);
assertThat(found, hasItem(id2.getIdPartAsLong())); assertThat(ResourcePersistentId.toLongList(found), hasItem(id2.getIdPartAsLong()));
} }
{ {
Set<Long> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2016-01-02")), null); Set<ResourcePersistentId> found = myObservationDao.searchForIds(new SearchParameterMap(Observation.SP_DATE, new DateParam(">2016-01-02")), null);
assertThat(found, not(hasItem(id2.getIdPartAsLong()))); assertThat(ResourcePersistentId.toLongList(found), not(hasItem(id2.getIdPartAsLong())));
} }
} }
@ -2297,7 +2298,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
"}\n"; "}\n";
//@formatter:on //@formatter:on
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null);
int initial = val.size(); int initial = val.size();
Organization org = myFhirCtx.newJsonParser().parseResource(Organization.class, inputStr); Organization org = myFhirCtx.newJsonParser().parseResource(Organization.class, inputStr);
@ -3592,7 +3593,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
assertThat(str.length(), greaterThan(ResourceIndexedSearchParamString.MAX_LENGTH)); assertThat(str.length(), greaterThan(ResourceIndexedSearchParamString.MAX_LENGTH));
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("name", new StringParam("P")), null);
int initial = val.size(); int initial = val.size();
myOrganizationDao.create(org, mySrd); myOrganizationDao.create(org, mySrd);
@ -3771,7 +3772,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
String subStr1 = longStr1.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH); String subStr1 = longStr1.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
String subStr2 = longStr2.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH); String subStr2 = longStr2.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
Set<Long> val = myOrganizationDao.searchForIds(new SearchParameterMap("type", new TokenParam(subStr1, subStr2)), null); Set<ResourcePersistentId> val = myOrganizationDao.searchForIds(new SearchParameterMap("type", new TokenParam(subStr1, subStr2)), null);
int initial = val.size(); int initial = val.size();
myOrganizationDao.create(org, mySrd); myOrganizationDao.create(org, mySrd);

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.dao.r4; package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable; import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
@ -568,9 +569,9 @@ public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
p2.addName().setFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB"); p2.addName().setFamily("Tester").addGiven("testUpdateMaintainsSearchParamsDstu2BBB");
myPatientDao.create(p2, mySrd).getId(); myPatientDao.create(p2, mySrd).getId();
Set<Long> ids = myPatientDao.searchForIds(new SearchParameterMap(Patient.SP_GIVEN, new StringParam("testUpdateMaintainsSearchParamsDstu2AAA")), null); Set<ResourcePersistentId> ids = myPatientDao.searchForIds(new SearchParameterMap(Patient.SP_GIVEN, new StringParam("testUpdateMaintainsSearchParamsDstu2AAA")), null);
assertEquals(1, ids.size()); assertEquals(1, ids.size());
assertThat(ids, contains(p1id.getIdPartAsLong())); assertThat(ResourcePersistentId.toLongList(ids), contains(p1id.getIdPartAsLong()));
// Update the name // Update the name
p1.getName().get(0).getGiven().get(0).setValue("testUpdateMaintainsSearchParamsDstu2BBB"); p1.getName().get(0).getGiven().get(0).setValue("testUpdateMaintainsSearchParamsDstu2BBB");

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.dao.r4; package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc; import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.param.StringAndListParam; import ca.uhn.fhir.rest.param.StringAndListParam;
@ -66,8 +67,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// OR // OR
{ {
@ -75,8 +76,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// AND // AND
{ {
@ -85,8 +86,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// AND OR // AND OR
{ {
@ -95,8 +96,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// All Resource Types // All Resource Types
{ {
@ -104,8 +105,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")).addOr(new StringParam("DDD"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")).addOr(new StringParam("DDD")));
map.add(Constants.PARAM_CONTENT, content); map.add(Constants.PARAM_CONTENT, content);
List<Long> found = mySearchDao.search(null, map); List<ResourcePersistentId> found = mySearchDao.search(null, map);
assertThat(found, containsInAnyOrder(id1, id2, id3)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2, id3));
} }
} }
@ -139,8 +140,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// OR // OR
{ {
@ -148,8 +149,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB"))); content.addAnd(new StringOrListParam().addOr(new StringParam("AAAS")).addOr(new StringParam("AAAB")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// AND // AND
{ {
@ -158,8 +159,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1));
} }
// AND OR // AND OR
{ {
@ -168,8 +169,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("CCC"))); content.addAnd(new StringOrListParam().addOr(new StringParam("CCC")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, containsInAnyOrder(id1, id2)); assertThat(ResourcePersistentId.toLongList(found), containsInAnyOrder(id1, id2));
} }
// Tag Contents // Tag Contents
{ {
@ -177,8 +178,8 @@ public class FhirSearchDaoR4Test extends BaseJpaR4Test {
content.addAnd(new StringOrListParam().addOr(new StringParam("div"))); content.addAnd(new StringOrListParam().addOr(new StringParam("div")));
map.add(Constants.PARAM_TEXT, content); map.add(Constants.PARAM_TEXT, content);
List<Long> found = mySearchDao.search(resourceName, map); List<ResourcePersistentId> found = mySearchDao.search(resourceName, map);
assertThat(found, empty()); assertThat(ResourcePersistentId.toLongList(found), empty());
} }
} }

View File

@ -3,8 +3,12 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam; import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef; import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
@ -13,7 +17,15 @@ import ca.uhn.fhir.util.TestUtil;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport; import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport; import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Consent;
import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.SearchParameter;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -21,7 +33,13 @@ import org.junit.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -32,7 +50,7 @@ public class SearchParamExtractorR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamExtractorR4Test.class); private static final Logger ourLog = LoggerFactory.getLogger(SearchParamExtractorR4Test.class);
private static FhirContext ourCtx = FhirContext.forR4(); private static FhirContext ourCtx = FhirContext.forR4();
private static IValidationSupport ourValidationSupport; private static IValidationSupport ourValidationSupport;
private ISearchParamRegistry mySearchParamRegistry; private MySearchParamRegistry mySearchParamRegistry;
@Before @Before
public void before() { public void before() {
@ -77,10 +95,11 @@ public class SearchParamExtractorR4Test {
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry); SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Encounter", "location"); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Encounter", "location");
assertNotNull(param); assertNotNull(param);
List<PathAndRef> links = extractor.extractResourceLinks(enc, param); ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(enc);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertEquals("Encounter.location.location", links.get(0).getPath()); assertEquals("location", links.iterator().next().getSearchParamName());
assertEquals("Location/123", ((Reference) links.get(0).getRef()).getReference()); assertEquals("Encounter.location.location", links.iterator().next().getPath());
assertEquals("Location/123", ((Reference) links.iterator().next().getRef()).getReference());
} }
@Test @Test
@ -91,10 +110,10 @@ public class SearchParamExtractorR4Test {
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry); SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Consent", Consent.SP_SOURCE_REFERENCE); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Consent", Consent.SP_SOURCE_REFERENCE);
assertNotNull(param); assertNotNull(param);
List<PathAndRef> links = extractor.extractResourceLinks(consent, param); ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(consent);
assertEquals(1, links.size()); assertEquals(1, links.size());
assertEquals("Consent.source", links.get(0).getPath()); assertEquals("Consent.source", links.iterator().next().getPath());
assertEquals("Consent/999", ((Reference) links.get(0).getRef()).getReference()); assertEquals("Consent/999", ((Reference) links.iterator().next().getRef()).getReference());
} }
@ -103,13 +122,15 @@ public class SearchParamExtractorR4Test {
String path = "Patient.extension('http://patext').value.as(Reference)"; String path = "Patient.extension('http://patext').value.as(Reference)";
RuntimeSearchParam sp = new RuntimeSearchParam("extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE); RuntimeSearchParam sp = new RuntimeSearchParam("extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE);
mySearchParamRegistry.addSearchParam(sp);
Patient patient = new Patient(); Patient patient = new Patient();
patient.addExtension("http://patext", new Reference("Organization/AAA")); patient.addExtension("http://patext", new Reference("Organization/AAA"));
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry); SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
List<PathAndRef> links = extractor.extractResourceLinks(patient, sp); ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(patient);
assertEquals(1, links.size()); assertEquals(1, links.size());
} }
@Test @Test
@ -129,6 +150,10 @@ public class SearchParamExtractorR4Test {
} }
private static class MySearchParamRegistry implements ISearchParamRegistry { private static class MySearchParamRegistry implements ISearchParamRegistry {
private List<RuntimeSearchParam> myExtraSearchParams = new ArrayList<>();
@Override @Override
public void forceRefresh() { public void forceRefresh() {
// nothing // nothing
@ -158,9 +183,17 @@ public class SearchParamExtractorR4Test {
sps.put(nextSp.getName(), nextSp); sps.put(nextSp.getName(), nextSp);
} }
for (RuntimeSearchParam next : myExtraSearchParams) {
sps.put(next.getName(), next);
}
return sps; return sps;
} }
public void addSearchParam(RuntimeSearchParam theSearchParam) {
myExtraSearchParams.add(theSearchParam);
}
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) { public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View File

@ -19,7 +19,7 @@ import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.search.warm.ICacheWarmingSvc; import ca.uhn.fhir.jpa.search.warm.ICacheWarmingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.BaseSearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry; import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl; import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
import ca.uhn.fhir.jpa.term.TermDeferredStorageSvcImpl; import ca.uhn.fhir.jpa.term.TermDeferredStorageSvcImpl;
@ -261,7 +261,7 @@ public abstract class BaseJpaR5Test extends BaseJpaTest {
@Qualifier("mySearchParameterDaoR5") @Qualifier("mySearchParameterDaoR5")
protected IFhirResourceDao<SearchParameter> mySearchParameterDao; protected IFhirResourceDao<SearchParameter> mySearchParameterDao;
@Autowired @Autowired
protected BaseSearchParamRegistry mySearchParamRegistry; protected SearchParamRegistryImpl mySearchParamRegistry;
@Autowired @Autowired
protected IStaleSearchDeletingSvc myStaleSearchDeletingSvc; protected IStaleSearchDeletingSvc myStaleSearchDeletingSvc;
@Autowired @Autowired

View File

@ -7,7 +7,7 @@ import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryDstu3; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.parser.StrictErrorHandler; import ca.uhn.fhir.parser.StrictErrorHandler;
@ -58,7 +58,7 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
protected static RestfulServer ourRestServer; protected static RestfulServer ourRestServer;
protected static String ourServerBase; protected static String ourServerBase;
protected static GenericWebApplicationContext ourWebApplicationContext; protected static GenericWebApplicationContext ourWebApplicationContext;
protected static SearchParamRegistryDstu3 ourSearchParamRegistry; protected static SearchParamRegistryImpl ourSearchParamRegistry;
protected static DatabaseBackedPagingProvider ourPagingProvider; protected static DatabaseBackedPagingProvider ourPagingProvider;
protected static ISearchCoordinatorSvc ourSearchCoordinatorSvc; protected static ISearchCoordinatorSvc ourSearchCoordinatorSvc;
private static Server ourServer; private static Server ourServer;
@ -153,7 +153,7 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(subsServletHolder.getServlet().getServletConfig().getServletContext()); WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(subsServletHolder.getServlet().getServletConfig().getServletContext());
myValidationSupport = wac.getBean(JpaValidationSupportChainDstu3.class); myValidationSupport = wac.getBean(JpaValidationSupportChainDstu3.class);
ourSearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class); ourSearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class);
ourSearchParamRegistry = wac.getBean(SearchParamRegistryDstu3.class); ourSearchParamRegistry = wac.getBean(SearchParamRegistryImpl.class);
ourSubscriptionTriggeringProvider = wac.getBean(SubscriptionTriggeringProvider.class); ourSubscriptionTriggeringProvider = wac.getBean(SubscriptionTriggeringProvider.class);
myFhirCtx.getRestfulClientFactory().setSocketTimeout(5000000); myFhirCtx.getRestfulClientFactory().setSocketTimeout(5000000);

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -151,7 +152,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
code.addPropertyString("HELLO", "12345-2"); code.addPropertyString("HELLO", "12345-2");
cs.getConcepts().add(code); cs.getConcepts().add(code);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getPersistentId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
}); });
} }
@ -849,7 +850,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B"); TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
cs.getConcepts().add(parentB); cs.getConcepts().add(parentB);
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return codeSystem; return codeSystem;
} }

View File

@ -7,7 +7,7 @@ import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryR4; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.SubscriptionMatcherInterceptor; import ca.uhn.fhir.jpa.subscription.SubscriptionMatcherInterceptor;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionLoader; import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionLoader;
import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.util.ResourceCountCache;
@ -61,7 +61,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
protected static int ourPort; protected static int ourPort;
protected static RestfulServer ourRestServer; protected static RestfulServer ourRestServer;
protected static String ourServerBase; protected static String ourServerBase;
protected static SearchParamRegistryR4 ourSearchParamRegistry; protected static SearchParamRegistryImpl ourSearchParamRegistry;
private static DatabaseBackedPagingProvider ourPagingProvider; private static DatabaseBackedPagingProvider ourPagingProvider;
protected static ISearchCoordinatorSvc mySearchCoordinatorSvc; protected static ISearchCoordinatorSvc mySearchCoordinatorSvc;
private static GenericWebApplicationContext ourWebApplicationContext; private static GenericWebApplicationContext ourWebApplicationContext;
@ -163,7 +163,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(subsServletHolder.getServlet().getServletConfig().getServletContext()); WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(subsServletHolder.getServlet().getServletConfig().getServletContext());
myValidationSupport = wac.getBean(JpaValidationSupportChainR4.class); myValidationSupport = wac.getBean(JpaValidationSupportChainR4.class);
mySearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class); mySearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class);
ourSearchParamRegistry = wac.getBean(SearchParamRegistryR4.class); ourSearchParamRegistry = wac.getBean(SearchParamRegistryImpl.class);
ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class); ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class);
ourSubscriptionMatcherInterceptor.start(); ourSubscriptionMatcherInterceptor.start();

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity; import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
@ -37,13 +38,16 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.Query;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.in;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
@ -59,15 +63,14 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
@After @After
public void after() throws Exception { public void after() throws Exception {
super.after(); super.after();
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden()); myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches()); myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
} }
@Override @Override
public void before() throws Exception { public void before() throws Exception {
super.before(); super.before();
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
} }
@Override @Override
@ -462,8 +465,6 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
Interceptor interceptor = new Interceptor(); Interceptor interceptor = new Interceptor();
myInterceptorRegistry.registerInterceptor(interceptor); myInterceptorRegistry.registerInterceptor(interceptor);
try { try {
myDaoConfig.setAllowContainsSearches(true);
// Add a custom search parameter // Add a custom search parameter
SearchParameter fooSp = new SearchParameter(); SearchParameter fooSp = new SearchParameter();
fooSp.addBase("Questionnaire"); fooSp.addBase("Questionnaire");
@ -520,6 +521,8 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
ids.add(myQuestionnaireDao.create(q).getId().getIdPartAsLong()); ids.add(myQuestionnaireDao.create(q).getId().getIdPartAsLong());
} }
myCaptureQueriesListener.clear();
int foundCount = 0; int foundCount = 0;
Bundle bundle = null; Bundle bundle = null;
List<Long> actualIds = new ArrayList<>(); List<Long> actualIds = new ArrayList<>();
@ -543,17 +546,42 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
} while (bundle.getLink("next") != null); } while (bundle.getLink("next") != null);
String queries = " * " + myCaptureQueriesListener
.getSelectQueries()
.stream()
.map(t->t.getSql(true, false))
.collect(Collectors.joining("\n * "));
ourLog.info("Found: {}", found); ourLog.info("Found: {}", found);
runInTransaction(() -> { runInTransaction(() -> {
List currentResults = myEntityManager.createNativeQuery("select distinct resourceta0_.RES_ID as col_0_0_ from HFJ_RESOURCE resourceta0_ left outer join HFJ_SPIDX_STRING myparamsst1_ on resourceta0_.RES_ID=myparamsst1_.RES_ID where myparamsst1_.HASH_NORM_PREFIX='5901791607832193956' and (myparamsst1_.SP_VALUE_NORMALIZED like 'SECTION%') limit '500'") .getResultList();
List currentResources = myEntityManager.createNativeQuery("select resourceta0_.RES_ID as col_0_0_ from HFJ_RESOURCE resourceta0_") .getResultList();
List<Search> searches = mySearchEntityDao.findAll(); List<Search> searches = mySearchEntityDao.findAll();
assertEquals(1, searches.size()); assertEquals(1, searches.size());
Search search = searches.get(0); Search search = searches.get(0);
String message = "\nWanted: " + (ids) + "\n" + String message = "\nWanted : " + (ids) + "\n" +
"Actual: " + (actualIds) + "\n" + "Actual : " + (actualIds) + "\n" +
"Found : " + (found) + "\n" + "Found : " + (found) + "\n" +
search.toString(); "Current: " + currentResults + "\n" +
"Current: " + currentResources + "\n" +
search.toString() +
"\nQueries :\n" + queries;
for (Long next :ids) {
if (!actualIds.contains(next)) {
List<ResourceIndexedSearchParamString> indexes = myResourceIndexedSearchParamStringDao
.findAll()
.stream()
.filter(t->t.getResourcePid().equals(next))
.collect(Collectors.toList());
message += "\n\nResource " + next + " has prefixes:\n * " + indexes.stream().map(t->t.toString()).collect(Collectors.joining("\n * "));
break;
}
}
assertEquals(message, 200, search.getNumFound()); assertEquals(message, 200, search.getNumFound());
assertEquals(message, 200, search.getTotalCount().intValue()); assertEquals(message, 200, search.getTotalCount().intValue());
assertEquals(message, SearchStatusEnum.FINISHED, search.getStatus()); assertEquals(message, SearchStatusEnum.FINISHED, search.getStatus());

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
@ -1053,7 +1054,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B"); TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
cs.getConcepts().add(parentB); cs.getConcepts().add(parentB);
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table); theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
return codeSystem; return codeSystem;
} }

View File

@ -14,6 +14,7 @@ import ca.uhn.fhir.jpa.search.cache.DatabaseSearchCacheSvcImpl;
import ca.uhn.fhir.rest.gclient.IClientExecutable; import ca.uhn.fhir.rest.gclient.IClientExecutable;
import ca.uhn.fhir.rest.gclient.IQuery; import ca.uhn.fhir.rest.gclient.IQuery;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle;
@ -24,6 +25,7 @@ import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.util.AopTestUtils; import org.springframework.test.util.AopTestUtils;
import java.util.Date; import java.util.Date;
@ -33,6 +35,11 @@ import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@TestPropertySource(properties = {
// Since scheduled tasks can cause searches, which messes up the
// value returned by SearchBuilder.getLastHandlerMechanismForUnitTest()
UnregisterScheduledProcessor.SCHEDULING_DISABLED_EQUALS_TRUE
})
public class StaleSearchDeletingSvcR4Test extends BaseResourceProviderR4Test { public class StaleSearchDeletingSvcR4Test extends BaseResourceProviderR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StaleSearchDeletingSvcR4Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StaleSearchDeletingSvcR4Test.class);

View File

@ -7,7 +7,7 @@ import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryR5; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.SubscriptionMatcherInterceptor; import ca.uhn.fhir.jpa.subscription.SubscriptionMatcherInterceptor;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionLoader; import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionLoader;
import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.util.ResourceCountCache;
@ -61,7 +61,7 @@ public abstract class BaseResourceProviderR5Test extends BaseJpaR5Test {
protected static int ourPort; protected static int ourPort;
protected static RestfulServer ourRestServer; protected static RestfulServer ourRestServer;
protected static String ourServerBase; protected static String ourServerBase;
protected static SearchParamRegistryR5 ourSearchParamRegistry; protected static SearchParamRegistryImpl ourSearchParamRegistry;
private static DatabaseBackedPagingProvider ourPagingProvider; private static DatabaseBackedPagingProvider ourPagingProvider;
protected static ISearchCoordinatorSvc mySearchCoordinatorSvc; protected static ISearchCoordinatorSvc mySearchCoordinatorSvc;
private static GenericWebApplicationContext ourWebApplicationContext; private static GenericWebApplicationContext ourWebApplicationContext;
@ -164,7 +164,7 @@ public abstract class BaseResourceProviderR5Test extends BaseJpaR5Test {
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(subsServletHolder.getServlet().getServletConfig().getServletContext()); WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(subsServletHolder.getServlet().getServletConfig().getServletContext());
myValidationSupport = wac.getBean(JpaValidationSupportChainR5.class); myValidationSupport = wac.getBean(JpaValidationSupportChainR5.class);
mySearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class); mySearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class);
ourSearchParamRegistry = wac.getBean(SearchParamRegistryR5.class); ourSearchParamRegistry = wac.getBean(SearchParamRegistryImpl.class);
ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class); ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class);
ourSubscriptionMatcherInterceptor.start(); ourSubscriptionMatcherInterceptor.start();

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
@ -1063,7 +1064,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B"); TermConcept parentB = new TermConcept(cs, "ParentB").setDisplay("Parent B");
cs.getConcepts().add(parentB); cs.getConcepts().add(parentB);
theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table); theTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table);
return codeSystem; return codeSystem;
} }

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.jpa.dao.*; import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum; import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc; import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc;
@ -110,19 +111,19 @@ public class SearchCoordinatorSvcImplTest {
}).when(myCallingDao).injectDependenciesIntoBundleProvider(any(PersistedJpaBundleProvider.class)); }).when(myCallingDao).injectDependenciesIntoBundleProvider(any(PersistedJpaBundleProvider.class));
} }
private List<Long> createPidSequence(int to) { private List<ResourcePersistentId> createPidSequence(int to) {
List<Long> pids = new ArrayList<>(); List<ResourcePersistentId> pids = new ArrayList<>();
for (long i = 10; i < to; i++) { for (long i = 10; i < to; i++) {
pids.add(i); pids.add(new ResourcePersistentId(i));
} }
return pids; return pids;
} }
private Answer<Void> loadPids() { private Answer<Void> loadPids() {
return theInvocation -> { return theInvocation -> {
List<Long> pids = (List<Long>) theInvocation.getArguments()[0]; List<ResourcePersistentId> pids = (List<ResourcePersistentId>) theInvocation.getArguments()[0];
List<IBaseResource> resources = (List<IBaseResource>) theInvocation.getArguments()[2]; List<IBaseResource> resources = (List<IBaseResource>) theInvocation.getArguments()[2];
for (Long nextPid : pids) { for (ResourcePersistentId nextPid : pids) {
Patient pt = new Patient(); Patient pt = new Patient();
pt.setId(nextPid.toString()); pt.setId(nextPid.toString());
resources.add(pt); resources.add(pt);
@ -136,7 +137,7 @@ public class SearchCoordinatorSvcImplTest {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
IResultIterator iter = new FailAfterNIterator(new SlowIterator(pids.iterator(), 2), 300); IResultIterator iter = new FailAfterNIterator(new SlowIterator(pids.iterator(), 2), 300);
when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter); when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter);
@ -154,10 +155,10 @@ public class SearchCoordinatorSvcImplTest {
@Test @Test
public void testAsyncSearchLargeResultSetBigCountSameCoordinator() { public void testAsyncSearchLargeResultSetBigCountSameCoordinator() {
List<Long> allResults = new ArrayList<>(); List<ResourcePersistentId> allResults = new ArrayList<>();
doAnswer(t -> { doAnswer(t -> {
List<Long> oldResults = t.getArgument(1, List.class); List<ResourcePersistentId> oldResults = t.getArgument(1, List.class);
List<Long> newResults = t.getArgument(2, List.class); List<ResourcePersistentId> newResults = t.getArgument(2, List.class);
ourLog.info("Saving {} new results - have {} old results", newResults.size(), oldResults.size()); ourLog.info("Saving {} new results - have {} old results", newResults.size(), oldResults.size());
assertEquals(allResults.size(), oldResults.size()); assertEquals(allResults.size(), oldResults.size());
allResults.addAll(newResults); allResults.addAll(newResults);
@ -168,13 +169,13 @@ public class SearchCoordinatorSvcImplTest {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
SlowIterator iter = new SlowIterator(pids.iterator(), 1); SlowIterator iter = new SlowIterator(pids.iterator(), 1);
when(mySearchBuilder.createQuery(any(), any(), any())).thenReturn(iter); when(mySearchBuilder.createQuery(any(), any(), any())).thenReturn(iter);
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any()); doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
when(mySearchResultCacheSvc.fetchResultPids(any(), anyInt(), anyInt())).thenAnswer(t -> { when(mySearchResultCacheSvc.fetchResultPids(any(), anyInt(), anyInt())).thenAnswer(t -> {
List<Long> returnedValues = iter.getReturnedValues(); List<ResourcePersistentId> returnedValues = iter.getReturnedValues();
int offset = t.getArgument(1, Integer.class); int offset = t.getArgument(1, Integer.class);
int end = t.getArgument(2, Integer.class); int end = t.getArgument(2, Integer.class);
end = Math.min(end, returnedValues.size()); end = Math.min(end, returnedValues.size());
@ -218,8 +219,8 @@ public class SearchCoordinatorSvcImplTest {
verify(mySearchCacheSvc, atLeastOnce()).save(searchCaptor.capture()); verify(mySearchCacheSvc, atLeastOnce()).save(searchCaptor.capture());
assertEquals(790, allResults.size()); assertEquals(790, allResults.size());
assertEquals(10, allResults.get(0).longValue()); assertEquals(10, allResults.get(0).getIdAsLong().longValue());
assertEquals(799, allResults.get(789).longValue()); assertEquals(799, allResults.get(789).getIdAsLong().longValue());
myExpectedNumberOfSearchBuildersCreated = 4; myExpectedNumberOfSearchBuildersCreated = 4;
} }
@ -274,7 +275,7 @@ public class SearchCoordinatorSvcImplTest {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
SlowIterator iter = new SlowIterator(pids.iterator(), 2); SlowIterator iter = new SlowIterator(pids.iterator(), 2);
when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter); when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter);
@ -298,7 +299,7 @@ public class SearchCoordinatorSvcImplTest {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
SlowIterator iter = new SlowIterator(pids.iterator(), 500); SlowIterator iter = new SlowIterator(pids.iterator(), 500);
when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter); when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter);
@ -342,7 +343,7 @@ public class SearchCoordinatorSvcImplTest {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
IResultIterator iter = new SlowIterator(pids.iterator(), 2); IResultIterator iter = new SlowIterator(pids.iterator(), 2);
when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter); when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter);
when(mySearchCacheSvc.save(any())).thenAnswer(t -> t.getArguments()[0]); when(mySearchCacheSvc.save(any())).thenAnswer(t -> t.getArguments()[0]);
@ -387,7 +388,7 @@ public class SearchCoordinatorSvcImplTest {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(100); List<ResourcePersistentId> pids = createPidSequence(100);
SlowIterator iter = new SlowIterator(pids.iterator(), 2); SlowIterator iter = new SlowIterator(pids.iterator(), 2);
when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter); when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(iter);
@ -435,9 +436,10 @@ public class SearchCoordinatorSvcImplTest {
} }
when(mySearchResultCacheSvc.fetchResultPids(any(Search.class), anyInt(), anyInt())).thenAnswer(theInvocation -> { when(mySearchResultCacheSvc.fetchResultPids(any(Search.class), anyInt(), anyInt())).thenAnswer(theInvocation -> {
ArrayList<Long> results = new ArrayList<>(); ArrayList<ResourcePersistentId> results = new ArrayList<>();
for (long i = theInvocation.getArgument(1, Integer.class); i < theInvocation.getArgument(2, Integer.class); i++) { for (long i = theInvocation.getArgument(1, Integer.class); i < theInvocation.getArgument(2, Integer.class); i++) {
results.add(i + 10L); Long nextPid = i + 10L;
results.add(new ResourcePersistentId(nextPid));
} }
return results; return results;
@ -470,7 +472,7 @@ public class SearchCoordinatorSvcImplTest {
params.setLoadSynchronous(true); params.setLoadSynchronous(true);
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(new ResultIterator(pids.iterator())); when(mySearchBuilder.createQuery(same(params), any(), any())).thenReturn(new ResultIterator(pids.iterator()));
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any()); doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
@ -491,7 +493,7 @@ public class SearchCoordinatorSvcImplTest {
params.setLoadSynchronousUpTo(100); params.setLoadSynchronousUpTo(100);
params.add("name", new StringParam("ANAME")); params.add("name", new StringParam("ANAME"));
List<Long> pids = createPidSequence(800); List<ResourcePersistentId> pids = createPidSequence(800);
when(mySearchBuilder.createQuery(same(params), any(), nullable(RequestDetails.class))).thenReturn(new ResultIterator(pids.iterator())); when(mySearchBuilder.createQuery(same(params), any(), nullable(RequestDetails.class))).thenReturn(new ResultIterator(pids.iterator()));
pids = createPidSequence(110); pids = createPidSequence(110);
@ -563,7 +565,7 @@ public class SearchCoordinatorSvcImplTest {
} }
public static class FailAfterNIterator extends BaseIterator<Long> implements IResultIterator { public static class FailAfterNIterator extends BaseIterator<ResourcePersistentId> implements IResultIterator {
private int myCount; private int myCount;
private IResultIterator myWrap; private IResultIterator myWrap;
@ -579,7 +581,7 @@ public class SearchCoordinatorSvcImplTest {
} }
@Override @Override
public Long next() { public ResourcePersistentId next() {
myCount--; myCount--;
if (myCount == 0) { if (myCount == 0) {
throw new NullPointerException("FAILED"); throw new NullPointerException("FAILED");
@ -598,11 +600,11 @@ public class SearchCoordinatorSvcImplTest {
} }
} }
public static class ResultIterator extends BaseIterator<Long> implements IResultIterator { public static class ResultIterator extends BaseIterator<ResourcePersistentId> implements IResultIterator {
private final Iterator<Long> myWrap; private final Iterator<ResourcePersistentId> myWrap;
ResultIterator(Iterator<Long> theWrap) { ResultIterator(Iterator<ResourcePersistentId> theWrap) {
myWrap = theWrap; myWrap = theWrap;
} }
@ -612,7 +614,7 @@ public class SearchCoordinatorSvcImplTest {
} }
@Override @Override
public Long next() { public ResourcePersistentId next() {
return myWrap.next(); return myWrap.next();
} }
@ -633,22 +635,22 @@ public class SearchCoordinatorSvcImplTest {
* <p> * <p>
* Don't use it in real code! * Don't use it in real code!
*/ */
public static class SlowIterator extends BaseIterator<Long> implements IResultIterator { public static class SlowIterator extends BaseIterator<ResourcePersistentId> implements IResultIterator {
private static final Logger ourLog = LoggerFactory.getLogger(SlowIterator.class); private static final Logger ourLog = LoggerFactory.getLogger(SlowIterator.class);
private final IResultIterator myResultIteratorWrap; private final IResultIterator myResultIteratorWrap;
private int myDelay; private int myDelay;
private Iterator<Long> myWrap; private Iterator<ResourcePersistentId> myWrap;
private List<Long> myReturnedValues = new ArrayList<>(); private List<ResourcePersistentId> myReturnedValues = new ArrayList<>();
private AtomicInteger myCountReturned = new AtomicInteger(0); private AtomicInteger myCountReturned = new AtomicInteger(0);
SlowIterator(Iterator<Long> theWrap, int theDelay) { SlowIterator(Iterator<ResourcePersistentId> theWrap, int theDelay) {
myWrap = theWrap; myWrap = theWrap;
myDelay = theDelay; myDelay = theDelay;
myResultIteratorWrap = null; myResultIteratorWrap = null;
} }
List<Long> getReturnedValues() { List<ResourcePersistentId> getReturnedValues() {
return myReturnedValues; return myReturnedValues;
} }
@ -666,13 +668,13 @@ public class SearchCoordinatorSvcImplTest {
} }
@Override @Override
public Long next() { public ResourcePersistentId next() {
try { try {
Thread.sleep(myDelay); Thread.sleep(myDelay);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// ignore // ignore
} }
Long retVal = myWrap.next(); ResourcePersistentId retVal = myWrap.next();
myReturnedValues.add(retVal); myReturnedValues.add(retVal);
myCountReturned.incrementAndGet(); myCountReturned.incrementAndGet();
return retVal; return retVal;

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeSystem;
@ -90,7 +91,7 @@ public abstract class BaseTermR4Test extends BaseJpaR4Test {
TermConcept parentB = new TermConcept(cs, "ParentB"); TermConcept parentB = new TermConcept(cs, "ParentB");
cs.getConcepts().add(parentB); cs.getConcepts().add(parentB);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return id; return id;
} }

View File

@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
@ -97,7 +98,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
TermConcept parentB = new TermConcept(cs, "ParentB"); TermConcept parentB = new TermConcept(cs, "ParentB");
cs.getConcepts().add(parentB); cs.getConcepts().add(parentB);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
return id; return id;
} }
@ -116,7 +117,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
TermConcept parentA = new TermConcept(cs, "CS2"); TermConcept parentA = new TermConcept(cs, "CS2");
cs.getConcepts().add(parentA); cs.getConcepts().add(parentA);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), CS_URL_2, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), CS_URL_2, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
} }
@ -185,7 +186,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
code2.getDisplay()); code2.getDisplay());
cs.getConcepts().add(code4); cs.getConcepts().add(code4);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), LOINC_URI, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), LOINC_URI, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
}); });
} }
@ -201,7 +202,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
TermCodeSystemVersion cs = new TermCodeSystemVersion(); TermCodeSystemVersion cs = new TermCodeSystemVersion();
cs.setResource(table); cs.setResource(table);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
// Update // Update
cs = new TermCodeSystemVersion(); cs = new TermCodeSystemVersion();
@ -210,7 +211,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
id = myCodeSystemDao.update(codeSystem, null, true, true, mySrd).getId().toUnqualified(); id = myCodeSystemDao.update(codeSystem, null, true, true, mySrd).getId().toUnqualified();
table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalArgumentException::new); table = myResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalArgumentException::new);
cs.setResource(table); cs.setResource(table);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getPersistentId(), CS_URL, "SYSTEM NAME", "SYSTEM VERSION", cs, table);
// Try to update to a different resource // Try to update to a different resource
codeSystem = new CodeSystem(); codeSystem = new CodeSystem();
@ -1780,7 +1781,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
child.addChild(parent, RelationshipTypeEnum.ISA); child.addChild(parent, RelationshipTypeEnum.ISA);
try { try {
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getId(), "http://foo", "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(table.getPersistentId(), "http://foo", "SYSTEM NAME", "SYSTEM VERSION", cs, table);
fail(); fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("CodeSystem contains circular reference around code parent", e.getMessage()); assertEquals("CodeSystem contains circular reference around code parent", e.getMessage());
@ -1905,7 +1906,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
runInTransaction(() -> { runInTransaction(() -> {
ResourceTable resTable = myEntityManager.find(ResourceTable.class, csId.getIdPartAsLong()); ResourceTable resTable = myEntityManager.find(ResourceTable.class, csId.getIdPartAsLong());
version.setResource(resTable); version.setResource(resTable);
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(csId.getIdPartAsLong(), cs.getUrl(), "My System", "SYSTEM VERSION", version, resTable); myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(csId.getIdPartAsLong()), cs.getUrl(), "My System", "SYSTEM VERSION", version, resTable);
}); });
org.hl7.fhir.dstu3.model.ValueSet vs = new org.hl7.fhir.dstu3.model.ValueSet(); org.hl7.fhir.dstu3.model.ValueSet vs = new org.hl7.fhir.dstu3.model.ValueSet();

View File

@ -0,0 +1,40 @@
package ca.uhn.fhir.jpa.model.cross;
/*-
* #%L
* HAPI FHIR Model
* %%
* Copyright (C) 2014 - 2019 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 org.hl7.fhir.instance.model.api.IIdType;
import java.util.Date;
public interface IBasePersistedResource {
IIdType getIdDt();
boolean isDeleted();
/**
* If the resource is deleted, returns the date/time that the resource was deleted at. Otherwie, returns <code>null</code>
*/
Date getDeleted();
ResourcePersistentId getPersistentId();
}

View File

@ -0,0 +1,88 @@
package ca.uhn.fhir.jpa.model.cross;
/*-
* #%L
* HAPI FHIR Model
* %%
* Copyright (C) 2014 - 2019 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.util.ObjectUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* This class is an abstraction for however primary keys are stored in the underlying storage engine. This might be
* a Long, a String, or something else.
*/
public class ResourcePersistentId {
private Object myId;
public ResourcePersistentId(Object theId) {
myId = theId;
}
@Override
public boolean equals(Object theO) {
if (!(theO instanceof ResourcePersistentId)) {
return false;
}
ResourcePersistentId that = (ResourcePersistentId) theO;
return ObjectUtil.equals(myId, that.myId);
}
@Override
public int hashCode() {
return myId.hashCode();
}
public Object getId() {
return myId;
}
public void setId(Object theId) {
myId = theId;
}
public Long getIdAsLong() {
return (Long) myId;
}
@Override
public String toString() {
return myId.toString();
}
public static List<Long> toLongList(Collection<ResourcePersistentId> thePids) {
List<Long> retVal = new ArrayList<>(thePids.size());
for (ResourcePersistentId next : thePids) {
retVal.add(next.getIdAsLong());
}
return retVal;
}
public static List<ResourcePersistentId> fromLongList(List<Long> theResultList) {
List<ResourcePersistentId> retVal = new ArrayList<>(theResultList.size());
for (Long next : theResultList) {
retVal.add(new ResourcePersistentId(next));
}
return retVal;
}
}

View File

@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.model.entity;
*/ */
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
@ -31,7 +33,7 @@ import java.util.Collection;
import java.util.Date; import java.util.Date;
@MappedSuperclass @MappedSuperclass
public abstract class BaseHasResource implements IBaseResourceEntity { public abstract class BaseHasResource implements IBaseResourceEntity, IBasePersistedResource {
@Column(name = "RES_DELETED_AT", nullable = true) @Column(name = "RES_DELETED_AT", nullable = true)
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
@ -85,10 +87,6 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
return cloneDate(myDeleted); return cloneDate(myDeleted);
} }
public void setDeleted(Date theDate) {
myDeleted = theDate;
}
@Override @Override
public FhirVersionEnum getFhirVersion() { public FhirVersionEnum getFhirVersion() {
return myFhirVersion; return myFhirVersion;
@ -121,6 +119,15 @@ public abstract class BaseHasResource implements IBaseResourceEntity {
} }
} }
@Override
public boolean isDeleted() {
return myDeleted != null;
}
public void setDeleted(Date theDate) {
myDeleted = theDate;
}
@Override @Override
public InstantDt getPublished() { public InstantDt getPublished() {
if (myPublished != null) { if (myPublished != null) {

View File

@ -61,6 +61,13 @@ public class ModelConfig {
private boolean mySubscriptionMatchingEnabled = true; private boolean mySubscriptionMatchingEnabled = true;
private String myWebsocketContextPath = DEFAULT_WEBSOCKET_CONTEXT_PATH; private String myWebsocketContextPath = DEFAULT_WEBSOCKET_CONTEXT_PATH;
/**
* Constructor
*/
public ModelConfig() {
super();
}
/** /**
* If set to {@code true} the default search params (i.e. the search parameters that are * 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 * defined by the FHIR specification itself) may be overridden by uploading search

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