partial solution implementation.

This commit is contained in:
peartree 2023-02-27 12:56:50 -05:00
parent 1b549d8a25
commit 4840a73cf6
8 changed files with 190 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.api.svc.IResourceSearchUrlSvc;
import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor;
import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider;
import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportJobSchedulingHelper;
@ -124,6 +125,7 @@ import ca.uhn.fhir.jpa.searchparam.nickname.NicknameInterceptor;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.sp.SearchParamPresenceSvcImpl;
import ca.uhn.fhir.jpa.search.ResourceSearchUrlSvcImpl;
import ca.uhn.fhir.jpa.term.TermCodeSystemStorageSvcImpl;
import ca.uhn.fhir.jpa.term.TermConceptMappingSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcImpl;
@ -792,4 +794,9 @@ public class JpaConfig {
@Bean
IMdmLinkImplFactory<MdmLink> mdmLinkImplFactory() {return new JpaMdmLinkImplFactory();}
@Bean
public IResourceSearchUrlSvc resourceSearchUrlSvc(){
return new ResourceSearchUrlSvcImpl();
}
}

View File

@ -405,6 +405,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
// Pre-cache the match URL
if (theMatchUrl != null) {
myMatchResourceUrlService.storeMatchUrlForResource(getResourceName(), theMatchUrl, jpaPid);
myMatchResourceUrlService.matchUrlResolved(theTransactionDetails, getResourceName(), theMatchUrl, jpaPid);
}

View File

@ -0,0 +1,8 @@
package ca.uhn.fhir.jpa.dao.data;
import ca.uhn.fhir.jpa.model.entity.ResourceSearchUrlEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface IResourceSearchUrlDao extends JpaRepository<ResourceSearchUrlEntity, Long>, IHapiFhirJpaRepository{
}

View File

@ -88,6 +88,27 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
init620();
init630();
init640();
init642();
}
protected void init642() {
Builder version = forVersion(VersionEnum.V6_4_2);
Builder.BuilderWithTableName resSearchUrlTable = version.onTable("HFJ_RES_SEARCH_URL");
resSearchUrlTable.addColumn("20230227.1","PID").nonNullable().type(ColumnTypeEnum.LONG);
resSearchUrlTable.addColumn("20230227.2", "RES_ID").nonNullable().type(ColumnTypeEnum.LONG);
resSearchUrlTable.addColumn("20230227.3", "RES_SEARC_URL").nonNullable().type(ColumnTypeEnum.STRING);
resSearchUrlTable.addColumn("20230227.4", "RES_HASH").nonNullable().type(ColumnTypeEnum.STRING, 128);
resSearchUrlTable.addColumn("20230227.5", "RES_SEARCH_URL").nonNullable().type(ColumnTypeEnum.STRING);
resSearchUrlTable.addColumn("20230227.6", "CREATED_TIME").nonNullable().type(ColumnTypeEnum.DATE_TIMESTAMP);
resSearchUrlTable.addForeignKey("20230227.7", "FK_RESSEARCHURL_RESID").toColumn("RES_ID").references("HFJ_RESOURCE", "RES_ID");
resSearchUrlTable.addIndex("20230227.8", "IDX_RES_HASH").unique(true).withColumns("RES_HASH");
version.addIdGenerator("20230227.9", "SEQ_RESSEARCHURL_ID");
}
protected void init640() {

View File

@ -0,0 +1,22 @@
package ca.uhn.fhir.jpa.search;
import ca.uhn.fhir.jpa.api.svc.IResourceSearchUrlSvc;
import ca.uhn.fhir.jpa.dao.data.IResourceSearchUrlDao;
import ca.uhn.fhir.jpa.model.entity.ResourceSearchUrlEntity;
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ResourceSearchUrlSvcImpl implements IResourceSearchUrlSvc {
@Autowired
private IResourceSearchUrlDao myResourceSearchUrlDao;
@Override
public void saveResourceSearchUrl(String theCanonicalizedUrlForStorage, IResourcePersistentId theResourcePersistentId) {
ResourceSearchUrlEntity searchUrlEntity = ResourceSearchUrlEntity.from(theCanonicalizedUrlForStorage, (Long)theResourcePersistentId.getId());
myResourceSearchUrlDao.save(searchUrlEntity);
}
}

View File

@ -0,0 +1,108 @@
package ca.uhn.fhir.jpa.model.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import java.util.Date;
@Entity
@Table(name = "HFJ_RES_SEARCH_URL", uniqueConstraints = {@UniqueConstraint(name = "IDX_RES_HASH", columnNames = "RES_HASH")
})
public class ResourceSearchUrlEntity {
@Id
@SequenceGenerator(name = "SEQ_RESSEARCHURL_ID", sequenceName = "SEQ_RESSEARCHURL_ID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_RESSEARCHURL_ID")
@Column(name = "PID")
private Long myId;
@OneToOne()
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_RESSEARCHURL_RESID"))
private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false, nullable = false)
private Long myResourcePid;
@Column(name = "RES_HASH", length = 128, nullable = false)
private String myHash;
@Column(name = "RES_SEARCH_URL", nullable = false)
private String mySearchUrl;
@Column(name = "CREATED_TIME", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date myCreatedTime;
public static ResourceSearchUrlEntity from(String theUrl, Long theId) {
return new ResourceSearchUrlEntity()
.setResourcePid(theId)
.setSearchUrl(theUrl)
.setCreatedTime(new Date());
}
public Long getId() {
return myId;
}
public ResourceSearchUrlEntity setId(Long theId) {
myId = theId;
return this;
}
public ResourceTable getResource() {
return myResource;
}
public ResourceSearchUrlEntity setResource(ResourceTable theResource) {
myResource = theResource;
return this;
}
public Long getResourcePid() {
return myResourcePid;
}
public ResourceSearchUrlEntity setResourcePid(Long theResourcePid) {
myResourcePid = theResourcePid;
return this;
}
public Date getCreatedTime() {
return myCreatedTime;
}
public ResourceSearchUrlEntity setCreatedTime(Date theCreatedTime) {
myCreatedTime = theCreatedTime;
return this;
}
public String getHash() {
return myHash;
}
public ResourceSearchUrlEntity setHash(String theHash) {
myHash = theHash;
return this;
}
public String getSearchUrl() {
return mySearchUrl;
}
public ResourceSearchUrlEntity setSearchUrl(String theSearchUrl) {
mySearchUrl = theSearchUrl;
return this;
}
}

View File

@ -0,0 +1,7 @@
package ca.uhn.fhir.jpa.api.svc;
import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId;
public interface IResourceSearchUrlSvc {
void saveResourceSearchUrl(String theCanonicalizedUrlForStorage, IResourcePersistentId theResourcePersistentId);
}

View File

@ -58,6 +58,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import ca.uhn.fhir.jpa.api.svc.IResourceSearchUrlSvc;
@Service
public class MatchResourceUrlService<T extends IResourcePersistentId> {
@ -76,6 +77,8 @@ public class MatchResourceUrlService<T extends IResourcePersistentId> {
private IInterceptorBroadcaster myInterceptorBroadcaster;
@Autowired
private MemoryCacheService myMemoryCacheService;
@Autowired
private IResourceSearchUrlSvc myResourceSearchUrlSvc;
/**
* Note that this will only return a maximum of 2 results!!
@ -109,8 +112,7 @@ public class MatchResourceUrlService<T extends IResourcePersistentId> {
}
if (retVal == null) {
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceType);
SearchParameterMap paramMap = myMatchUrlService.translateMatchUrl(matchUrl, resourceDef);
SearchParameterMap paramMap = deriveSearchParameterMap(matchUrl, myContext.getResourceType(theResourceType));
if (paramMap.isEmpty() && paramMap.getLastUpdated() == null) {
throw new InvalidRequestException(Msg.code(518) + "Invalid match URL[" + matchUrl + "] - URL has no search parameters");
}
@ -162,6 +164,11 @@ public class MatchResourceUrlService<T extends IResourcePersistentId> {
return retVal;
}
private SearchParameterMap deriveSearchParameterMap(String theMatchUrl, String theResourceType) {
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceType);
return myMatchUrlService.translateMatchUrl(theMatchUrl, resourceDef);
}
private <R extends IBaseResource> IFhirResourceDao<R> getResourceDao(Class<R> theResourceType) {
IFhirResourceDao<R> dao = myDaoRegistry.getResourceDao(theResourceType);
if (dao == null) {
@ -223,4 +230,11 @@ public class MatchResourceUrlService<T extends IResourcePersistentId> {
}
}
public void storeMatchUrlForResource(String theResourceName, String theMatchUrl, T theResourcePersistentId) {
SearchParameterMap matchUrlSearchParameterMap = deriveSearchParameterMap(theMatchUrl, theResourceName);
String canonicalizedMatchUrl = matchUrlSearchParameterMap.toNormalizedQueryString(myContext);
String canonicalizedUrlForStorage = massageForStorage(theResourceName, canonicalizedMatchUrl);
myResourceSearchUrlSvc.saveResourceSearchUrl(canonicalizedUrlForStorage, theResourcePersistentId);
}
}