Use ForcedId to get current ValueSet version

This commit is contained in:
juan.marchionatto 2021-08-31 13:33:39 -04:00
parent f63f12e976
commit 710343a599
16 changed files with 110 additions and 178 deletions

View File

@ -25,15 +25,18 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
@ -69,15 +72,15 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
private static final Logger ourLog = LoggerFactory.getLogger(JpaPersistedResourceValidationSupport.class);
public static final String LOINC_GENERIC_VALUESET_URL = "http://loinc.org/vs";
public static final String LOINC_GENERIC_VALUESET_URL_PLUS_SLASH = LOINC_GENERIC_VALUESET_URL + "/";
private final FhirContext myFhirContext;
private final IBaseResource myNoMatch;
@Autowired
private DaoRegistry myDaoRegistry;
@Autowired
private ITermReadSvc myITermReadSvc;
private Class<? extends IBaseResource> myCodeSystemType;
private Class<? extends IBaseResource> myStructureDefinitionType;
private Class<? extends IBaseResource> myValueSetType;
@ -104,20 +107,34 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
@Override
public IBaseResource fetchValueSet(String theSystem) {
// if no version is present, we need to append the current version,
// if one exists, in case it is not the last loaded
theSystem = appendCurrentVersion(theSystem);
boolean isNotLoincCodeSystem = ! StringUtils.containsIgnoreCase(theSystem, "loinc");
boolean hasVersion = theSystem.contains("|");
boolean isForGenericValueSet = theSystem.equals(LOINC_GENERIC_VALUESET_URL);
if (isNotLoincCodeSystem || hasVersion || isForGenericValueSet) {
return fetchResource(myValueSetType, theSystem);
}
// if no version is present, we need to fetch the resource for the current version if one exists,
// in case it is not the last loaded
Optional<IBaseResource> currentVSOpt = getValueSetCurrentVersion(new UriType(theSystem));
return currentVSOpt.orElseThrow(() -> new ResourceNotFoundException(
"Couldn't find current version ValueSet for url: " + theSystem));
}
private String appendCurrentVersion(String theSystem) {
// if version is included there is nothing to add here
if (theSystem.contains("|")) return theSystem;
/**
* Obtains the current version of a ValueSet using the fact that the current
* version is always pointed by the ForcedId for the no-versioned VS
*/
public Optional<IBaseResource> getValueSetCurrentVersion(UriType theUrl) {
if (! theUrl.getValueAsString().startsWith(LOINC_GENERIC_VALUESET_URL)) return Optional.empty();
Optional<String> currentVersionOpt = myITermReadSvc.getValueSetCurrentVersion(new UriType(theSystem));
if (!theUrl.getValue().startsWith(LOINC_GENERIC_VALUESET_URL_PLUS_SLASH)) {
throw new InternalErrorException("Don't know how to extract ForcedId from url: " + theUrl.getValueAsString());
}
return currentVersionOpt.map(ver -> theSystem + "|" + ver).orElse(theSystem);
String forcedId = theUrl.getValue().substring(LOINC_GENERIC_VALUESET_URL_PLUS_SLASH.length());
IBaseResource valueSet = myDaoRegistry.getResourceDao(myValueSetType).read(new IdDt("ValueSet", forcedId));
return Optional.ofNullable(valueSet);
}
@ -195,9 +212,6 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
params.add(ValueSet.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(ValueSet.SP_URL, new UriParam(theUri.substring(0, versionSeparator)));
} else {
// last loaded ValueSet not necessarily is the current version anymore, so code should be executing
// this path only when there is no current version pointed for the ValueSet
ourLog.warn("Fetching ValueSet current version as last loaded");
params.add(ValueSet.SP_URL, new UriParam(theUri));
}
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.dao.data;
import ca.uhn.fhir.jpa.entity.TermValueSet;
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
@ -31,6 +32,8 @@ import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Optional;
import static ca.uhn.fhir.jpa.dao.JpaPersistedResourceValidationSupport.LOINC_GENERIC_VALUESET_URL;
public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> {
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid")
@ -44,28 +47,32 @@ public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> {
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myExpansionStatus = :expansion_status")
Slice<TermValueSet> findByExpansionStatus(Pageable pageable, @Param("expansion_status") TermValueSetPreExpansionStatusEnum theExpansionStatus);
@Query(value="SELECT vs FROM TermValueSet vs INNER JOIN ResourceTable r ON r.myId = vs.myResourcePid WHERE vs.myUrl = :url ORDER BY r.myUpdated DESC")
List<TermValueSet> findTermValueSetByUrl(Pageable thePage, @Param("url") String theUrl);
/**
* The current TermValueSet is not necessarily the last uploaded anymore, but we know which is the last VS resource
* because it is pointed by a specific ForcedId, so we locate current ValueSet as the one pointing to the current resource
*/
@Query(value="SELECT vs FROM ForcedId f, TermValueSet vs where f.myForcedId = :forcedId and vs.myResource = f.myResource")
Optional<TermValueSet> findTermValueSetByForcedId(@Param("forcedId") String theForcedId);
default Optional<TermValueSet> findTermValueSetByUrl(@Param("url") String theUrl) {
if (theUrl.startsWith(LOINC_GENERIC_VALUESET_URL)) {
String forcedId = theUrl.substring(LOINC_GENERIC_VALUESET_URL.length());
if (StringUtils.isBlank(forcedId)) return Optional.empty();
return findTermValueSetByForcedId(forcedId);
}
List<TermValueSet> tvsList = findTermValueSetByUrl(Pageable.ofSize(1), theUrl);
return Optional.ofNullable(tvsList.size() == 1 ? tvsList.get(0) : null);
}
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myUrl = :url AND vs.myVersion IS NULL")
Optional<TermValueSet> findTermValueSetByUrlAndNullVersion(@Param("url") String theUrl);
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myUrl = :url AND vs.myVersion = :version")
Optional<TermValueSet> findTermValueSetByUrlAndVersion(@Param("url") String theUrl, @Param("version") String theVersion);
/**
* Obtain the only ValueSet for the url which myIsCurrentVersion is true if one exists
* or the last loaded ValueSet for the url which version is null otherwise
*/
@Query("select vs FROM TermValueSet vs JOIN FETCH vs.myResource r WHERE vs.myUrl = :url AND (vs.myIsCurrentVersion is true or " +
"(vs.myIsCurrentVersion is false AND vs.myVersion is null AND not exists(" +
"FROM TermValueSet WHERE myUrl = :url AND myIsCurrentVersion is true )) ) order by r.myUpdated DESC")
List<TermValueSet> listTermValueSetsByUrlAndCurrentVersion(@Param("url") String theUrl, Pageable pageable);
/**
* This method uses the previous one to get a possible list of ValueSets and return the first if any
* because the query will obtain no more than one if one with the myCurrentVersion flag exists but
* could obtain more if one with that flag doesn't exist. For that reason the query is Pageable and ordered
*/
default Optional<TermValueSet> findTermValueSetByUrlAndCurrentVersion(@Param("url") String theUrl) {
List<TermValueSet> termValueSets = listTermValueSetsByUrlAndCurrentVersion(theUrl, Pageable.ofSize(1));
return termValueSets.isEmpty()? Optional.empty() : Optional.of(termValueSets.get(0));
}
}

View File

@ -26,10 +26,24 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.OptimisticLock;
import javax.annotation.Nonnull;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@ -86,10 +100,6 @@ public class TermValueSet implements Serializable {
@Column(name = "EXPANSION_STATUS", nullable = false, length = MAX_EXPANSION_STATUS_LENGTH)
private TermValueSetPreExpansionStatusEnum myExpansionStatus;
@OptimisticLock(excluded = true)
@Column(name = "CURRENT_VERSION")
private Boolean myIsCurrentVersion = false;
@Transient
private transient Integer myHashCode;
@ -203,14 +213,6 @@ public class TermValueSet implements Serializable {
return this;
}
public Boolean getCurrentVersion() {
return myIsCurrentVersion;
}
public void setCurrentVersion(Boolean theCurrentVersion) {
myIsCurrentVersion = theCurrentVersion;
}
@Override
public boolean equals(Object theO) {
if (this == theO) return true;

View File

@ -26,7 +26,6 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
@ -43,20 +42,14 @@ import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.ValueSet;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<ValueSet> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaResourceProviderValueSetR4.class);
@Autowired
private ITermReadSvc myITermReadSvc;
@Operation(name = JpaConstants.OPERATION_EXPAND, idempotent = true)
public ValueSet expand(
HttpServletRequest theServletRequest,
@ -83,16 +76,6 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
throw new InvalidRequestException("$expand must EITHER be invoked at the instance level, or have a url specified, or have a ValueSet specified. Can not combine these options.");
}
// todo JM remove this code. This function is at lower level now
// because current version is not necessarily the last uploaded anymore, we add a version parameter for the current version
if (haveIdentifier && ! haveValueSetVersion) {
Optional<String> currentVersionOpt = myITermReadSvc.getValueSetCurrentVersion(theUrl);
if (currentVersionOpt.isPresent()) {
theValueSetVersion = new StringType(currentVersionOpt.get());
haveValueSetVersion = true;
}
}
ValueSetExpansionOptions options = createValueSetExpansionOptions(myDaoConfig, theOffset, theCount, theIncludeHierarchy, theFilter);
startRequest(theServletRequest);
@ -115,7 +98,6 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
}
}
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = {
@OperationParam(name = "result", type = BooleanType.class, min = 1),
@OperationParam(name = "message", type = StringType.class),

View File

@ -117,7 +117,6 @@ import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.IntegerType;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
import org.quartz.JobExecutionContext;
@ -197,7 +196,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
@Autowired
protected ITermConceptDesignationDao myConceptDesignationDao;
@Autowired
protected ITermValueSetDao myValueSetDao;
protected ITermValueSetDao myTermValueSetDao;
@Autowired
protected ITermValueSetConceptDao myValueSetConceptDao;
@Autowired
@ -232,9 +231,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
@Autowired
private ITermConceptMappingSvc myTermConceptMappingSvc;
@Autowired
private ITermValueSetDao myTermValueSetDao;
private volatile IValidationSupport myJpaValidationSupport;
private volatile IValidationSupport myValidationSupport;
@ -343,7 +339,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
public void deleteValueSetForResource(ResourceTable theResourceTable) {
// Get existing entity so it can be deleted.
Optional<TermValueSet> optionalExistingTermValueSetById = myValueSetDao.findByResourcePid(theResourceTable.getId());
Optional<TermValueSet> optionalExistingTermValueSetById = myTermValueSetDao.findByResourcePid(theResourceTable.getId());
if (optionalExistingTermValueSetById.isPresent()) {
TermValueSet existingTermValueSet = optionalExistingTermValueSetById.get();
@ -351,7 +347,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
ourLog.info("Deleting existing TermValueSet[{}] and its children...", existingTermValueSet.getId());
myValueSetConceptDesignationDao.deleteByTermValueSetId(existingTermValueSet.getId());
myValueSetConceptDao.deleteByTermValueSetId(existingTermValueSet.getId());
myValueSetDao.deleteById(existingTermValueSet.getId());
myTermValueSetDao.deleteById(existingTermValueSet.getId());
ourLog.info("Done deleting existing TermValueSet[{}] and its children.", existingTermValueSet.getId());
}
}
@ -447,9 +443,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
Optional<TermValueSet> optionalTermValueSet;
if (theValueSetToExpand.hasUrl()) {
if (theValueSetToExpand.hasVersion()) {
optionalTermValueSet = myValueSetDao.findTermValueSetByUrlAndVersion(theValueSetToExpand.getUrl(), theValueSetToExpand.getVersion());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(theValueSetToExpand.getUrl(), theValueSetToExpand.getVersion());
} else {
optionalTermValueSet = myValueSetDao.findTermValueSetByUrlAndCurrentVersion(theValueSetToExpand.getUrl());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrl(theValueSetToExpand.getUrl());
}
} else {
optionalTermValueSet = Optional.empty();
@ -1454,7 +1450,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
@Override
public boolean isValueSetPreExpandedForCodeValidation(ValueSet theValueSet) {
ResourcePersistentId valueSetResourcePid = myConceptStorageSvc.getValueSetResourcePid(theValueSet.getIdElement());
Optional<TermValueSet> optionalTermValueSet = myValueSetDao.findByResourcePid(valueSetResourcePid.getIdAsLong());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findByResourcePid(valueSetResourcePid.getIdAsLong());
if (!optionalTermValueSet.isPresent()) {
ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory code validation. {}", getValueSetInfo(theValueSet));
@ -1759,7 +1755,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
TermValueSet termValueSet = optionalTermValueSet.get();
termValueSet.setExpansionStatus(TermValueSetPreExpansionStatusEnum.EXPANSION_IN_PROGRESS);
return myValueSetDao.saveAndFlush(termValueSet);
return myTermValueSetDao.saveAndFlush(termValueSet);
});
if (valueSetToExpand == null) {
return;
@ -1768,18 +1764,18 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
// We have a ValueSet to pre-expand.
try {
ValueSet valueSet = txTemplate.execute(t -> {
TermValueSet refreshedValueSetToExpand = myValueSetDao.findById(valueSetToExpand.getId()).orElseThrow(() -> new IllegalStateException("Unknown VS ID: " + valueSetToExpand.getId()));
TermValueSet refreshedValueSetToExpand = myTermValueSetDao.findById(valueSetToExpand.getId()).orElseThrow(() -> new IllegalStateException("Unknown VS ID: " + valueSetToExpand.getId()));
return getValueSetFromResourceTable(refreshedValueSetToExpand.getResource());
});
assert valueSet != null;
ValueSetConceptAccumulator accumulator = new ValueSetConceptAccumulator(valueSetToExpand, myValueSetDao, myValueSetConceptDao, myValueSetConceptDesignationDao);
ValueSetConceptAccumulator accumulator = new ValueSetConceptAccumulator(valueSetToExpand, myTermValueSetDao, myValueSetConceptDao, myValueSetConceptDesignationDao);
expandValueSet(null, valueSet, accumulator);
// We are done with this ValueSet.
txTemplate.execute(t -> {
valueSetToExpand.setExpansionStatus(TermValueSetPreExpansionStatusEnum.EXPANDED);
myValueSetDao.saveAndFlush(valueSetToExpand);
myTermValueSetDao.saveAndFlush(valueSetToExpand);
return null;
});
@ -1789,7 +1785,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
ourLog.error("Failed to pre-expand ValueSet: " + e.getMessage(), e);
txTemplate.execute(t -> {
valueSetToExpand.setExpansionStatus(TermValueSetPreExpansionStatusEnum.FAILED_TO_EXPAND);
myValueSetDao.saveAndFlush(valueSetToExpand);
myTermValueSetDao.saveAndFlush(valueSetToExpand);
return null;
});
}
@ -1872,7 +1868,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
private Optional<TermValueSet> getNextTermValueSetNotExpanded() {
Optional<TermValueSet> retVal = Optional.empty();
Slice<TermValueSet> page = myValueSetDao.findByExpansionStatus(PageRequest.of(0, 1), TermValueSetPreExpansionStatusEnum.NOT_EXPANDED);
Slice<TermValueSet> page = myTermValueSetDao.findByExpansionStatus(PageRequest.of(0, 1), TermValueSetPreExpansionStatusEnum.NOT_EXPANDED);
if (!page.getContent().isEmpty()) {
retVal = Optional.of(page.getContent().get(0));
@ -1883,7 +1879,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
@Override
@Transactional
public void storeTermValueSet(ResourceTable theResourceTable, ValueSet theValueSet , boolean theMakeItCurrent) {
public void storeTermValueSet(ResourceTable theResourceTable, ValueSet theValueSet) {
ValidateUtil.isTrueOrThrowInvalidRequest(theResourceTable != null, "No resource supplied");
if (isPlaceholder(theValueSet)) {
@ -1902,13 +1898,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
termValueSet.setUrl(theValueSet.getUrl());
termValueSet.setVersion(theValueSet.getVersion());
termValueSet.setName(theValueSet.hasName() ? theValueSet.getName() : null);
termValueSet.setCurrentVersion(false);
// value sets must be marked as current only when version is present and flag indicates that
if (theValueSet.getVersion() != null && theMakeItCurrent) {
resetCurrentValueSetVersion(theValueSet);
termValueSet.setCurrentVersion(true);
}
// Delete version being replaced
deleteValueSetForResource(theResourceTable);
@ -1920,13 +1909,13 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
String version = termValueSet.getVersion();
Optional<TermValueSet> optionalExistingTermValueSetByUrl;
if (version != null) {
optionalExistingTermValueSetByUrl = myValueSetDao.findTermValueSetByUrlAndVersion(url, version);
optionalExistingTermValueSetByUrl = myTermValueSetDao.findTermValueSetByUrlAndVersion(url, version);
} else {
optionalExistingTermValueSetByUrl = myValueSetDao.findTermValueSetByUrlAndNullVersion(url);
optionalExistingTermValueSetByUrl = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(url);
}
if (!optionalExistingTermValueSetByUrl.isPresent()) {
myValueSetDao.save(termValueSet);
myTermValueSetDao.save(termValueSet);
} else {
TermValueSet existingTermValueSet = optionalExistingTermValueSetByUrl.get();
@ -1946,17 +1935,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
}
}
private void resetCurrentValueSetVersion(ValueSet theValueSet) {
Optional<TermValueSet> termValueSetOpt = myTermValueSetDao.findTermValueSetByUrlAndCurrentVersion(theValueSet.getUrl());
if (! termValueSetOpt.isPresent()) return;
TermValueSet termValueSet = termValueSetOpt.get();
termValueSet.setCurrentVersion(false);
myTermValueSetDao.save(termValueSet);
}
@Override
@Transactional
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB,
@ -2509,18 +2487,4 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
return theReqLang.equalsIgnoreCase(theStoredLang);
}
@Override
@Transactional
public Optional<String> getValueSetCurrentVersion(UriType theUrl) {
Optional<TermValueSet> termValueSetOpt =
myTermValueSetDao.findTermValueSetByUrlAndCurrentVersion(theUrl.getValueAsString());
if (! termValueSetOpt.isPresent() || StringUtils.isBlank(termValueSetOpt.get().getVersion())) {
return Optional.empty();
}
return termValueSetOpt.map(TermValueSet::getVersion);
}
}

View File

@ -399,9 +399,7 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
theCodeSystemResource.getVersion(), theCodeSystemVersion, resource, theRequest);
myDeferredStorageSvc.addConceptMapsToStorageQueue(theConceptMaps);
boolean isMakeVersionCurrent = ITermCodeSystemStorageSvc.isMakeVersionCurrent(theRequest);
myDeferredStorageSvc.addValueSetsToStorageQueue(theValueSets, isMakeVersionCurrent);
myDeferredStorageSvc.addValueSetsToStorageQueue(theValueSets);
return csId;
}

View File

@ -49,7 +49,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.util.Pair;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@ -66,7 +65,6 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
@ -74,7 +72,7 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
final private List<TermCodeSystem> myDeferredCodeSystemsDeletions = Collections.synchronizedList(new ArrayList<>());
final private Queue<TermCodeSystemVersion> myDeferredCodeSystemVersionsDeletions = new ConcurrentLinkedQueue<>();
final private List<TermConcept> myDeferredConcepts = Collections.synchronizedList(new ArrayList<>());
final private List<Pair<ValueSet, Boolean>> myDeferredValueSets = Collections.synchronizedList(new ArrayList<>());
final private List<ValueSet> myDeferredValueSets = Collections.synchronizedList(new ArrayList<>());
final private List<ConceptMap> myDeferredConceptMaps = Collections.synchronizedList(new ArrayList<>());
final private List<TermConceptParentChildLink> myConceptLinksToSaveLater = Collections.synchronizedList(new ArrayList<>());
@Autowired
@ -118,9 +116,9 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
}
@Override
public void addValueSetsToStorageQueue(List<ValueSet> theValueSets, boolean theMakeThemCurrent) {
public void addValueSetsToStorageQueue(List<ValueSet> theValueSets) {
Validate.notNull(theValueSets);
myDeferredValueSets.addAll(theValueSets.stream().map(vs -> Pair.of(vs, theMakeThemCurrent)).collect(Collectors.toList()));
myDeferredValueSets.addAll(theValueSets);
}
@Override
@ -216,15 +214,12 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
}
}
private void processDeferredValueSets() {
int count = Math.min(myDeferredValueSets.size(), 200);
for (Pair<ValueSet, Boolean> nextPair : new ArrayList<>(myDeferredValueSets.subList(0, count))) {
ValueSet valueSet = nextPair.getFirst();
boolean makeItCurrent = nextPair.getSecond();
ourLog.info("Creating ValueSet: {} , {}making it current version", valueSet.getId(), (makeItCurrent ? "" : "not "));
myTerminologyVersionAdapterSvc.createOrUpdateValueSet(valueSet, makeItCurrent);
myDeferredValueSets.remove(nextPair);
for (ValueSet nextValueSet : new ArrayList<>(myDeferredValueSets.subList(0, count))) {
ourLog.info("Creating ValueSet: {}", nextValueSet.getId());
myTerminologyVersionAdapterSvc.createOrUpdateValueSet(nextValueSet);
myDeferredValueSets.remove(nextValueSet);
}
ourLog.info("Saved {} deferred ValueSet resources, have {} remaining", count, myDeferredValueSets.size());
}

View File

@ -40,7 +40,7 @@ public class TermVersionAdapterSvcDstu2 implements ITermVersionAdapterSvc {
}
@Override
public void createOrUpdateValueSet(ValueSet theValueSet, boolean theMakeItCurrent) {
public void createOrUpdateValueSet(ValueSet theValueSet) {
throw new UnsupportedOperationException();
}

View File

@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.term;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40;
@ -38,7 +37,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import static ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc.MAKE_LOADING_VERSION_CURRENT;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl implements ITermVersionAdapterSvc {
@ -105,7 +103,7 @@ public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl im
}
@Override
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet, boolean theMakeItCurrent) {
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet) {
ValueSet valueSetDstu3;
try {
valueSetDstu3 = (ValueSet) VersionConvertorFactory_30_40.convertResource(theValueSet, new BaseAdvisor_30_40(false));
@ -113,14 +111,11 @@ public class TermVersionAdapterSvcDstu3 extends BaseTermVersionAdapterSvcImpl im
throw new InternalErrorException(e);
}
TransactionDetails txDetails = new TransactionDetails();
txDetails.putUserData(MAKE_LOADING_VERSION_CURRENT, theMakeItCurrent);
if (isBlank(valueSetDstu3.getIdElement().getIdPart())) {
String matchUrl = "ValueSet?url=" + UrlUtil.escapeUrlParam(theValueSet.getUrl());
myValueSetResourceDao.update(valueSetDstu3, matchUrl, true, false, null, txDetails);
myValueSetResourceDao.update(valueSetDstu3, matchUrl);
} else {
myValueSetResourceDao.update(valueSetDstu3, null, true, false, null, txDetails);
myValueSetResourceDao.update(valueSetDstu3);
}
}

View File

@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.term;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CodeSystem;
@ -34,7 +33,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import static ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc.MAKE_LOADING_VERSION_CURRENT;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class TermVersionAdapterSvcR4 extends BaseTermVersionAdapterSvcImpl implements ITermVersionAdapterSvc {
@ -83,15 +81,12 @@ public class TermVersionAdapterSvcR4 extends BaseTermVersionAdapterSvcImpl imple
}
@Override
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet, boolean theMakeItCurrent) {
TransactionDetails txDetails = new TransactionDetails();
txDetails.putUserData(MAKE_LOADING_VERSION_CURRENT, theMakeItCurrent);
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet) {
if (isBlank(theValueSet.getIdElement().getIdPart())) {
String matchUrl = "ValueSet?url=" + UrlUtil.escapeUrlParam(theValueSet.getUrl());
myValueSetResourceDao.update(theValueSet, matchUrl, true, false, null, txDetails);
myValueSetResourceDao.update(theValueSet, matchUrl);
} else {
myValueSetResourceDao.update(theValueSet, null, true, false, null, txDetails);
myValueSetResourceDao.update(theValueSet);
}
}

View File

@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.term;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
@ -36,7 +35,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import static ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc.MAKE_LOADING_VERSION_CURRENT;
import static org.apache.commons.lang3.StringUtils.isBlank;
public class TermVersionAdapterSvcR5 extends BaseTermVersionAdapterSvcImpl implements ITermVersionAdapterSvc {
@ -90,18 +88,15 @@ public class TermVersionAdapterSvcR5 extends BaseTermVersionAdapterSvcImpl imple
}
@Override
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet, boolean theMakeItCurrent) {
public void createOrUpdateValueSet(org.hl7.fhir.r4.model.ValueSet theValueSet) {
ValueSet valueSetR4 = (ValueSet) VersionConvertorFactory_40_50.convertResource(theValueSet, new BaseAdvisor_40_50(false));
TransactionDetails txDetails = new TransactionDetails();
txDetails.putUserData(MAKE_LOADING_VERSION_CURRENT, theMakeItCurrent);
if (isBlank(theValueSet.getIdElement().getIdPart())) {
String matchUrl = "ValueSet?url=" + UrlUtil.escapeUrlParam(theValueSet.getUrl());
myValueSetResourceDao.update(valueSetR4, matchUrl, true, false, null, txDetails);
myValueSetResourceDao.update(valueSetR4, matchUrl);
} else {
myValueSetResourceDao.update(valueSetR4, null, true, false, null, txDetails);
myValueSetResourceDao.update(valueSetR4);
}
}

View File

@ -52,7 +52,7 @@ public interface ITermDeferredStorageSvc {
void addConceptMapsToStorageQueue(List<ConceptMap> theConceptMaps);
void addValueSetsToStorageQueue(List<ValueSet> theValueSets, boolean theMakeThemCurrent);
void addValueSetsToStorageQueue(List<ValueSet> theValueSets);
void deleteCodeSystem(TermCodeSystem theCodeSystem);

View File

@ -14,7 +14,6 @@ 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.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.ValueSet;
import javax.annotation.Nonnull;
@ -88,13 +87,7 @@ public interface ITermReadSvc extends IValidationSupport {
void deleteValueSetAndChildren(ResourceTable theResourceTable);
void storeTermValueSet(ResourceTable theResourceTable, ValueSet theValueSet, boolean theMakeItCurrent);
default void storeTermValueSet(ResourceTable theResourceTable, ValueSet theValueSet) {
storeTermValueSet(theResourceTable, theValueSet, true);
}
void storeTermValueSet(ResourceTable theResourceTable, ValueSet theValueSet);
IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB);
@ -122,5 +115,4 @@ public interface ITermReadSvc extends IValidationSupport {
*/
CodeValidationResult codeSystemValidateCode(IIdType theCodeSystemId, String theValueSetUrl, String theVersion, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
Optional<String> getValueSetCurrentVersion(UriType theUrl);
}

View File

@ -41,6 +41,6 @@ public interface ITermVersionAdapterSvc {
void createOrUpdateConceptMap(ConceptMap theNextConceptMap);
void createOrUpdateValueSet(ValueSet theValueSet, boolean makeItCurrent);
void createOrUpdateValueSet(ValueSet theValueSet);
}

View File

@ -571,7 +571,7 @@ public abstract class BaseJpaR5Test extends BaseJpaTest implements ITestDataBuil
public List<String> getExpandedConceptsByValueSetUrl(String theValuesetUrl) {
return runInTransaction(() -> {
Optional<TermValueSet> valueSetOpt = myTermValueSetDao.findTermValueSetByUrlAndCurrentVersion(theValuesetUrl);
Optional<TermValueSet> valueSetOpt = myTermValueSetDao.findTermValueSetByUrl(theValuesetUrl);
assertTrue(valueSetOpt.isPresent());
TermValueSet valueSet = valueSetOpt.get();
List<TermValueSetConcept> concepts = valueSet.getConcepts();

View File

@ -122,15 +122,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
cmbTokNuTable.addColumn("20210722.1", "PARTITION_ID").nullable().type(ColumnTypeEnum.INT);
cmbTokNuTable.addColumn("20210722.2", "PARTITION_DATE").nullable().type(ColumnTypeEnum.DATE_ONLY);
cmbTokNuTable.modifyColumn("20210722.3", "RES_ID").nullable().withType(ColumnTypeEnum.LONG);
version.onTable("TRM_VALUESET")
.addColumn("20210820.1", "CURRENT_VERSION").nullable().type(ColumnTypeEnum.BOOLEAN);
//todo JM Add new column initialization and validate boolean in Oracle
}
private void init540() {
Builder version = forVersion(VersionEnum.V5_4_0);