Merge pull request #2081 from jamesagnew/feature_2020_09_02_term_multi_version_support

Feature 2020 09 02 term multi version support
This commit is contained in:
IanMMarshall 2020-10-01 12:24:40 -04:00 committed by GitHub
commit f1710fd0be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
114 changed files with 12526 additions and 625 deletions

View File

@ -20,14 +20,14 @@ package ca.uhn.fhir.util;
* #L% * #L%
*/ */
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.CompareToBuilder; import org.apache.commons.lang3.builder.CompareToBuilder;
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;
public class VersionIndependentConcept implements Comparable<VersionIndependentConcept> { public class FhirVersionIndependentConcept implements Comparable<FhirVersionIndependentConcept> {
private final String mySystem; private final String mySystem;
private final String mySystemVersion;
private final String myCode; private final String myCode;
private final String myDisplay; private final String myDisplay;
private int myHashCode; private int myHashCode;
@ -35,12 +35,17 @@ public class VersionIndependentConcept implements Comparable<VersionIndependentC
/** /**
* Constructor * Constructor
*/ */
public VersionIndependentConcept(String theSystem, String theCode) { public FhirVersionIndependentConcept(String theSystem, String theCode) {
this(theSystem, theCode, null); this(theSystem, theCode, null);
} }
public VersionIndependentConcept(String theSystem, String theCode, String theDisplay) { public FhirVersionIndependentConcept(String theSystem, String theCode, String theDisplay) {
this(theSystem, theCode, theDisplay, null);
}
public FhirVersionIndependentConcept(String theSystem, String theCode, String theDisplay, String theSystemVersion) {
mySystem = theSystem; mySystem = theSystem;
mySystemVersion = theSystemVersion;
myCode = theCode; myCode = theCode;
myDisplay = theDisplay; myDisplay = theDisplay;
myHashCode = new HashCodeBuilder(17, 37) myHashCode = new HashCodeBuilder(17, 37)
@ -57,6 +62,9 @@ public class VersionIndependentConcept implements Comparable<VersionIndependentC
return mySystem; return mySystem;
} }
public String getSystemVersion() {
return mySystemVersion;
}
public String getCode() { public String getCode() {
return myCode; return myCode;
@ -72,7 +80,7 @@ public class VersionIndependentConcept implements Comparable<VersionIndependentC
return false; return false;
} }
VersionIndependentConcept that = (VersionIndependentConcept) theO; FhirVersionIndependentConcept that = (FhirVersionIndependentConcept) theO;
return new EqualsBuilder() return new EqualsBuilder()
.append(mySystem, that.mySystem) .append(mySystem, that.mySystem)
@ -86,7 +94,7 @@ public class VersionIndependentConcept implements Comparable<VersionIndependentC
} }
@Override @Override
public int compareTo(VersionIndependentConcept theOther) { public int compareTo(FhirVersionIndependentConcept theOther) {
CompareToBuilder b = new CompareToBuilder(); CompareToBuilder b = new CompareToBuilder();
b.append(mySystem, theOther.getSystem()); b.append(mySystem, theOther.getSystem());
b.append(myCode, theOther.getCode()); b.append(myCode, theOther.getCode());

View File

@ -125,6 +125,8 @@ ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.matchesFound=Matches fo
ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.noMatchesFound=No matches found! ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.noMatchesFound=No matches found!
ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoConceptMapR4.matchesFound=Matches found! ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoConceptMapR4.matchesFound=Matches found!
ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoConceptMapR4.noMatchesFound=No matches found! ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoConceptMapR4.noMatchesFound=No matches found!
ca.uhn.fhir.jpa.dao.r5.FhirResourceDaoConceptMapR5.matchesFound=Matches found!
ca.uhn.fhir.jpa.dao.r5.FhirResourceDaoConceptMapR5.noMatchesFound=No matches found!
ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4.invalidSearchParamExpression=The expression "{0}" can not be evaluated and may be invalid: {1} ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4.invalidSearchParamExpression=The expression "{0}" can not be evaluated and may be invalid: {1}
ca.uhn.fhir.jpa.dao.predicate.PredicateBuilderToken.textModifierDisabledForSearchParam=The :text modifier is disabled for this search parameter ca.uhn.fhir.jpa.dao.predicate.PredicateBuilderToken.textModifierDisabledForSearchParam=The :text modifier is disabled for this search parameter
@ -141,9 +143,13 @@ ca.uhn.fhir.jpa.binstore.BinaryAccessProvider.unknownType=Content in resource of
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateCodeSystemUrl=Can not create multiple CodeSystem resources with CodeSystem.url "{0}", already have one with resource ID: {1} ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateCodeSystemUrl=Can not create multiple CodeSystem resources with CodeSystem.url "{0}", already have one with resource ID: {1}
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateCodeSystemUrlAndVersion=Can not create multiple CodeSystem resources with CodeSystem.url "{0}" and CodeSystem.version "{1}", already have one with resource ID: {2}
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateConceptMapUrl=Can not create multiple ConceptMap resources with ConceptMap.url "{0}", already have one with resource ID: {1} ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateConceptMapUrl=Can not create multiple ConceptMap resources with ConceptMap.url "{0}", already have one with resource ID: {1}
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateConceptMapUrlAndVersion=Can not create multiple ConceptMap resources with ConceptMap.url "{0}" and ConceptMap.version "{1}", already have one with resource ID: {2}
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateValueSetUrl=Can not create multiple ValueSet resources with ValueSet.url "{0}", already have one with resource ID: {1} ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateValueSetUrl=Can not create multiple ValueSet resources with ValueSet.url "{0}", already have one with resource ID: {1}
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.expansionTooLarge=Expansion of ValueSet produced too many codes (maximum {0}) - Operation aborted! ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.expansionTooLarge=Expansion of ValueSet produced too many codes (maximum {0}) - Operation aborted!
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotCreateDuplicateValueSetUrlAndVersion=Can not create multiple ValueSet resources with ValueSet.url "{0}" and ValueSet.version "{1}", already have one with resource ID: {2}
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.cannotUpdateUrlOrVersionForValueSetResource=Cannot update URL or version for ValueSet resource. Existing ValueSet resource with resource ID {0} found with ValueSet.url "{1}" and ValueSet.version "{2}"
ca.uhn.fhir.jpa.patch.JsonPatchUtils.failedToApplyPatch=Failed to apply JSON patch to {0}: {1} ca.uhn.fhir.jpa.patch.JsonPatchUtils.failedToApplyPatch=Failed to apply JSON patch to {0}: {1}

View File

@ -0,0 +1,4 @@
---
type: add
issue: 2081
title: "An implementation of CodeSystem validate-code operation has been added for R4 and R5."

View File

@ -0,0 +1,4 @@
---
type: add
issue: 2081
title: "Terminology loader for LOINC will now support specifying version and loading multiple versions of LOINC."

View File

@ -0,0 +1,4 @@
---
type: add
issue: 2081
title: "Operations for CodeSystem, ValueSet and ConcepMap will now support multiple CodeSystem versions."

View File

@ -42,6 +42,8 @@ public interface IFhirResourceDaoCodeSystem<T extends IBaseResource, CD, CC> ext
SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, CD theCodingA, CD theCodingB, RequestDetails theRequestDetails); SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, CD theCodingA, CD theCodingB, RequestDetails theRequestDetails);
IValidationSupport.CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl, IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay, CD theCoding, CC theCodeableConcept, RequestDetails theRequestDetails);
class SubsumesResult { class SubsumesResult {
private final ConceptSubsumptionOutcome myOutcome; private final ConceptSubsumptionOutcome myOutcome;

View File

@ -23,11 +23,14 @@ package ca.uhn.fhir.jpa.api.model;
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.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.model.UriType;
public class TranslationQuery { public class TranslationQuery {
private Coding myCoding; private Coding myCoding;
private Long myResourceId; private Long myResourceId;
private UriType myUrl;
private StringType myConceptMapVersion;
private UriType mySource; private UriType mySource;
private UriType myTarget; private UriType myTarget;
private UriType myTargetSystem; private UriType myTargetSystem;
@ -58,6 +61,30 @@ public class TranslationQuery {
myResourceId = theResourceId; myResourceId = theResourceId;
} }
public boolean hasUrl() {
return myUrl != null && myUrl.hasValue();
}
public UriType getUrl() {
return myUrl;
}
public void setUrl(UriType theUrl) {
myUrl = theUrl;
}
public boolean hasConceptMapVersion() {
return myConceptMapVersion != null && myConceptMapVersion.hasValue();
}
public StringType getConceptMapVersion() {
return myConceptMapVersion;
}
public void setConceptMapVersion(StringType theConceptMapVersion) {
myConceptMapVersion = theConceptMapVersion;
}
public boolean hasSource() { public boolean hasSource() {
return mySource != null && mySource.hasValue(); return mySource != null && mySource.hasValue();
} }
@ -107,6 +134,8 @@ public class TranslationQuery {
.append(getCoding().getSystem(), that.getCoding().getSystem()) .append(getCoding().getSystem(), that.getCoding().getSystem())
.append(getCoding().getVersion(), that.getCoding().getVersion()) .append(getCoding().getVersion(), that.getCoding().getVersion())
.append(getResourceId(), that.getResourceId()) .append(getResourceId(), that.getResourceId())
.append(getUrl(), that.getUrl())
.append(getConceptMapVersion(), that.getConceptMapVersion())
.append(getSource(), that.getSource()) .append(getSource(), that.getSource())
.append(getTarget(), that.getTarget()) .append(getTarget(), that.getTarget())
.append(getTargetSystem(), that.getTargetSystem()) .append(getTargetSystem(), that.getTargetSystem())
@ -120,6 +149,8 @@ public class TranslationQuery {
.append(getCoding().getSystem()) .append(getCoding().getSystem())
.append(getCoding().getVersion()) .append(getCoding().getVersion())
.append(getResourceId()) .append(getResourceId())
.append(getUrl())
.append(getConceptMapVersion())
.append(getSource()) .append(getSource())
.append(getTarget()) .append(getTarget())
.append(getTargetSystem()) .append(getTargetSystem())

View File

@ -1,5 +1,8 @@
package ca.uhn.fhir.jpa.api.model; package ca.uhn.fhir.jpa.api.model;
import java.util.ArrayList;
import java.util.List;
/* /*
* #%L * #%L
* HAPI FHIR JPA API * HAPI FHIR JPA API
@ -24,15 +27,15 @@ import org.apache.commons.lang3.Validate;
import org.hl7.fhir.r4.model.BooleanType; import org.hl7.fhir.r4.model.BooleanType;
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.StringType;
import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.model.UriType;
import java.util.ArrayList;
import java.util.List;
public class TranslationRequest { public class TranslationRequest {
private CodeableConcept myCodeableConcept; private CodeableConcept myCodeableConcept;
private Long myResourceId; private Long myResourceId;
private BooleanType myReverse; private BooleanType myReverse;
private UriType myUrl;
private StringType myConceptMapVersion;
private UriType mySource; private UriType mySource;
private UriType myTarget; private UriType myTarget;
private UriType myTargetSystem; private UriType myTargetSystem;
@ -90,6 +93,24 @@ public class TranslationRequest {
return false; return false;
} }
public UriType getUrl() {
return myUrl;
}
public TranslationRequest setUrl(UriType theUrl) {
myUrl = theUrl;
return this;
}
public StringType getConceptMapVersion() {
return myConceptMapVersion;
}
public TranslationRequest setConceptMapVersion(StringType theConceptMapVersion) {
myConceptMapVersion = theConceptMapVersion;
return this;
}
public UriType getSource() { public UriType getSource() {
return mySource; return mySource;
} }
@ -130,6 +151,14 @@ public class TranslationRequest {
translationQuery.setResourceId(this.getResourceId()); translationQuery.setResourceId(this.getResourceId());
} }
if (this.hasUrl()) {
translationQuery.setUrl(this.getUrl());
}
if (this.hasConceptMapVersion()) {
translationQuery.setConceptMapVersion(this.getConceptMapVersion());
}
if (this.hasSource()) { if (this.hasSource()) {
translationQuery.setSource(this.getSource()); translationQuery.setSource(this.getSource());
} }
@ -156,6 +185,14 @@ public class TranslationRequest {
return myReverse != null; return myReverse != null;
} }
public boolean hasUrl() {
return myUrl != null && myUrl.hasValue();
}
public boolean hasConceptMapVersion() {
return myConceptMapVersion != null && myConceptMapVersion.hasValue();
}
public boolean hasSource() { public boolean hasSource() {
return mySource != null && mySource.hasValue(); return mySource != null && mySource.hasValue();
} }

View File

@ -23,6 +23,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.DefaultProfileValidationSupport; import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
@ -43,7 +44,6 @@ import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriParam; import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.apache.commons.codec.binary.StringUtils;
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain; import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
@ -57,6 +57,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions; import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
import static ca.uhn.fhir.jpa.util.LogicUtil.multiXor; import static ca.uhn.fhir.jpa.util.LogicUtil.multiXor;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
@ -303,4 +304,10 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueS
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept); return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
} }
@Override
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl, IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode,
IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequestDetails) {
throw new UnsupportedOperationException();
}
} }

View File

@ -25,8 +25,11 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
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.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam; 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.param.UriParam;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
@ -121,18 +124,25 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1); params.setLoadSynchronousUpTo(1);
params.add(IAnyResource.SP_RES_ID, new StringParam(theUri)); params.add(IAnyResource.SP_RES_ID, new StringParam(theUri));
search = myDaoRegistry.getResourceDao("ValueSet").search(params); search = myDaoRegistry.getResourceDao(resourceName).search(params);
if (search.size() == 0) { if (search.size() == 0) {
params = new SearchParameterMap(); params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1); params.setLoadSynchronousUpTo(1);
params.add(ValueSet.SP_URL, new UriParam(theUri)); params.add(ValueSet.SP_URL, new UriParam(theUri));
search = myDaoRegistry.getResourceDao("ValueSet").search(params); search = myDaoRegistry.getResourceDao(resourceName).search(params);
} }
} else { } else {
int versionSeparator = theUri.lastIndexOf('|');
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1); params.setLoadSynchronousUpTo(1);
params.add(ValueSet.SP_URL, new UriParam(theUri)); if (versionSeparator != -1) {
search = myDaoRegistry.getResourceDao("ValueSet").search(params); params.add(ValueSet.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(ValueSet.SP_URL, new UriParam(theUri.substring(0,versionSeparator)));
} else {
params.add(ValueSet.SP_URL, new UriParam(theUri));
}
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
search = myDaoRegistry.getResourceDao(resourceName).search(params);
} }
} else if ("StructureDefinition".equals(resourceName)) { } else if ("StructureDefinition".equals(resourceName)) {
// Don't allow the core FHIR definitions to be overwritten // Don't allow the core FHIR definitions to be overwritten
@ -156,9 +166,16 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
} }
search = myDaoRegistry.getResourceDao("Questionnaire").search(params); search = myDaoRegistry.getResourceDao("Questionnaire").search(params);
} else if ("CodeSystem".equals(resourceName)) { } else if ("CodeSystem".equals(resourceName)) {
int versionSeparator = theUri.lastIndexOf('|');
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronousUpTo(1); params.setLoadSynchronousUpTo(1);
params.add(CodeSystem.SP_URL, new UriParam(theUri)); if (versionSeparator != -1) {
params.add(CodeSystem.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
params.add(CodeSystem.SP_URL, new UriParam(theUri.substring(0,versionSeparator)));
} else {
params.add(CodeSystem.SP_URL, new UriParam(theUri));
}
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
search = myDaoRegistry.getResourceDao(resourceName).search(params); search = myDaoRegistry.getResourceDao(resourceName).search(params);
} else if ("ImplementationGuide".equals(resourceName)) { } else if ("ImplementationGuide".equals(resourceName)) {
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();

View File

@ -35,9 +35,19 @@ public interface ITermCodeSystemVersionDao extends JpaRepository<TermCodeSystemV
@Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myCodeSystem = :cs") @Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myCodeSystem = :cs")
void deleteForCodeSystem(@Param("cs") TermCodeSystem theCodeSystem); void deleteForCodeSystem(@Param("cs") TermCodeSystem theCodeSystem);
@Modifying
@Query("DELETE FROM TermCodeSystemVersion csv WHERE csv.myId = :pid")
void delete(@Param("pid") Long codesystemversion_pid);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemPid = :codesystem_pid") @Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemPid = :codesystem_pid")
List<TermCodeSystemVersion> findByCodeSystemPid(@Param("codesystem_pid") Long theCodeSystemPid); List<TermCodeSystemVersion> findByCodeSystemPid(@Param("codesystem_pid") Long theCodeSystemPid);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemPid = :codesystem_pid AND cs.myCodeSystemVersionId = :codesystem_version_id")
TermCodeSystemVersion findByCodeSystemPidAndVersion(@Param("codesystem_pid") Long theCodeSystemPid, @Param("codesystem_version_id") String theCodeSystemVersionId);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myCodeSystemPid = :codesystem_pid AND cs.myCodeSystemVersionId IS NULL")
TermCodeSystemVersion findByCodeSystemPidVersionIsNull(@Param("codesystem_pid") Long theCodeSystemPid);
@Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myResourcePid = :resource_id") @Query("SELECT cs FROM TermCodeSystemVersion cs WHERE cs.myResourcePid = :resource_id")
List<TermCodeSystemVersion> findByCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid); List<TermCodeSystemVersion> findByCodeSystemResourcePid(@Param("resource_id") Long theCodeSystemResourcePid);

View File

@ -1,12 +1,15 @@
package ca.uhn.fhir.jpa.dao.data; package ca.uhn.fhir.jpa.dao.data;
import ca.uhn.fhir.jpa.entity.TermConceptMap; import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying; 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;
import java.util.Optional; import ca.uhn.fhir.jpa.entity.TermConceptMap;
/* /*
* #%L * #%L
@ -36,6 +39,18 @@ public interface ITermConceptMapDao extends JpaRepository<TermConceptMap, Long>
@Query("SELECT cm FROM TermConceptMap cm WHERE cm.myResourcePid = :resource_pid") @Query("SELECT cm FROM TermConceptMap cm WHERE cm.myResourcePid = :resource_pid")
Optional<TermConceptMap> findTermConceptMapByResourcePid(@Param("resource_pid") Long theResourcePid); Optional<TermConceptMap> findTermConceptMapByResourcePid(@Param("resource_pid") Long theResourcePid);
@Query("SELECT cm FROM TermConceptMap cm WHERE cm.myUrl = :url") // Keep backwards compatibility, recommend to use findTermConceptMapByUrlAndNullVersion instead
@Deprecated
@Query("SELECT cm FROM TermConceptMap cm WHERE cm.myUrl = :url and cm.myVersion is null")
Optional<TermConceptMap> findTermConceptMapByUrl(@Param("url") String theUrl); Optional<TermConceptMap> findTermConceptMapByUrl(@Param("url") String theUrl);
@Query("SELECT cm FROM TermConceptMap cm WHERE cm.myUrl = :url and cm.myVersion is null")
Optional<TermConceptMap> findTermConceptMapByUrlAndNullVersion(@Param("url") String theUrl);
// Note that last updated version is considered current version.
@Query(value="SELECT cm FROM TermConceptMap cm INNER JOIN ResourceTable r ON r.myId = cm.myResourcePid WHERE cm.myUrl = :url ORDER BY r.myUpdated DESC")
List<TermConceptMap> getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(Pageable thePage, @Param("url") String theUrl);
@Query("SELECT cm FROM TermConceptMap cm WHERE cm.myUrl = :url AND cm.myVersion = :version")
Optional<TermConceptMap> findTermConceptMapByUrlAndVersion(@Param("url") String theUrl, @Param("version") String theVersion);
} }

View File

@ -28,6 +28,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
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;
import java.util.List;
import java.util.Optional; import java.util.Optional;
public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> { public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> {
@ -35,10 +36,22 @@ public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> {
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid") @Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid")
Optional<TermValueSet> findByResourcePid(@Param("resource_pid") Long theResourcePid); Optional<TermValueSet> findByResourcePid(@Param("resource_pid") Long theResourcePid);
// Keeping for backwards compatibility but recommend using findTermValueSetByUrlAndNullVersion instead.
@Deprecated
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myUrl = :url") @Query("SELECT vs FROM TermValueSet vs WHERE vs.myUrl = :url")
Optional<TermValueSet> findByUrl(@Param("url") String theUrl); Optional<TermValueSet> findByUrl(@Param("url") String theUrl);
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myExpansionStatus = :expansion_status") @Query("SELECT vs FROM TermValueSet vs WHERE vs.myExpansionStatus = :expansion_status")
Slice<TermValueSet> findByExpansionStatus(Pageable pageable, @Param("expansion_status") TermValueSetPreExpansionStatusEnum theExpansionStatus); 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);
@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);
} }

View File

@ -22,11 +22,10 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
@ -65,8 +64,6 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
@Autowired @Autowired
protected ITermDeferredStorageSvc myTermDeferredStorageSvc; protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
@Autowired @Autowired
private ITermCodeSystemDao myCsDao;
@Autowired
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@Autowired @Autowired
private FhirContext myFhirContext; private FhirContext myFhirContext;
@ -104,7 +101,11 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
String system; String system;
if (haveCoding) { if (haveCoding) {
code = theCoding.getCode(); code = theCoding.getCode();
system = theCoding.getSystem(); if (theCoding.hasVersion()) {
system = theCoding.getSystem() + "|" + theCoding.getVersion();
} else {
system = theCoding.getSystem();
}
} else { } else {
code = theCode.getValue(); code = theCode.getValue();
system = theSystem.getValue(); system = theSystem.getValue();
@ -133,13 +134,8 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) { protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
super.preDelete(theResourceToDelete, theEntityToDelete); super.preDelete(theResourceToDelete, theEntityToDelete);
String codeSystemUrl = theResourceToDelete.getUrl(); myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
if (isNotBlank(codeSystemUrl)) {
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
if (persCs != null) {
myTermDeferredStorageSvc.deleteCodeSystem(persCs);
}
}
} }
@Override @Override
@ -160,4 +156,10 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
return retVal; return retVal;
} }
@Override
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl, IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode,
IPrimitiveType<String> theDisplay, Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
throw new UnsupportedOperationException();
}
} }

View File

@ -21,22 +21,18 @@ package ca.uhn.fhir.jpa.dao.dstu3;
*/ */
import ca.uhn.fhir.context.support.ConceptValidationOptions; import ca.uhn.fhir.context.support.ConceptValidationOptions;
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; 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.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
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.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
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.IntegerType; import org.hl7.fhir.dstu3.model.IntegerType;
@ -49,9 +45,6 @@ import org.hl7.fhir.exceptions.FHIRException;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -63,19 +56,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet; import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet;
public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> { public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
@Autowired
private ITermReadSvc myHapiTerminologySvc;
@Autowired
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@Autowired
private IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
@Override @Override
public void start() { public void start() {
super.start(); super.start();
@ -143,8 +126,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
filter.setValue(theFilter); filter.setValue(theFilter);
} }
ValueSet retVal = doExpand(source); return doExpand(source);
return retVal;
// if (defaultValueSet != null) { // if (defaultValueSet != null) {
// source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet)); // source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet));
@ -178,8 +160,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
filter.setValue(theFilter); filter.setValue(theFilter);
} }
ValueSet retVal = doExpand(source, theOffset, theCount); return doExpand(source, theOffset, theCount);
return retVal;
} }
@Override @Override
@ -217,6 +198,9 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
ValueSet toExpand = new ValueSet(); ValueSet toExpand = new ValueSet();
toExpand.setId(theSource.getId()); toExpand.setId(theSource.getId());
toExpand.setUrl(theSource.getUrl()); toExpand.setUrl(theSource.getUrl());
if (theSource.getVersion() != null) {
toExpand.setVersion(theSource.getVersion());
}
for (ConceptSetComponent next : theSource.getCompose().getInclude()) { for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
toExpand.getCompose().addInclude(next); toExpand.getCompose().addInclude(next);
@ -283,12 +267,12 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
try { try {
ValueSet valueSet = (ValueSet) theResource; ValueSet valueSet = (ValueSet) theResource;
org.hl7.fhir.r4.model.ValueSet converted = convertValueSet(valueSet); org.hl7.fhir.r4.model.ValueSet converted = convertValueSet(valueSet);
myHapiTerminologySvc.storeTermValueSet(retVal, converted); myTerminologySvc.storeTermValueSet(retVal, converted);
} catch (FHIRException fe) { } catch (FHIRException fe) {
throw new InternalErrorException(fe); throw new InternalErrorException(fe);
} }
} else { } else {
myHapiTerminologySvc.deleteValueSetAndChildren(retVal); myTerminologySvc.deleteValueSetAndChildren(retVal);
} }
} }

View File

@ -39,7 +39,7 @@ import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier; import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.util.VersionIndependentConcept; import ca.uhn.fhir.util.FhirVersionIndependentConcept;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.hibernate.query.criteria.internal.CriteriaBuilderImpl; import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.predicate.BooleanStaticAssertionPredicate; import org.hibernate.query.criteria.internal.predicate.BooleanStaticAssertionPredicate;
@ -160,7 +160,7 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
From<?, ResourceIndexedSearchParamToken> theFrom, From<?, ResourceIndexedSearchParamToken> theFrom,
SearchFilterParser.CompareOperation operation, SearchFilterParser.CompareOperation operation,
RequestPartitionId theRequestPartitionId) { RequestPartitionId theRequestPartitionId) {
final List<VersionIndependentConcept> codes = new ArrayList<>(); final List<FhirVersionIndependentConcept> codes = new ArrayList<>();
String paramName = theSearchParam.getName(); String paramName = theSearchParam.getName();
TokenParamModifier modifier = null; TokenParamModifier modifier = null;
@ -214,12 +214,12 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
validateHaveSystemAndCodeForToken(paramName, code, system); validateHaveSystemAndCodeForToken(paramName, code, system);
codes.addAll(myTerminologySvc.findCodesBelow(system, code)); codes.addAll(myTerminologySvc.findCodesBelow(system, code));
} else { } else {
codes.add(new VersionIndependentConcept(system, code)); codes.add(new FhirVersionIndependentConcept(system, code));
} }
} }
List<VersionIndependentConcept> sortedCodesList = codes List<FhirVersionIndependentConcept> sortedCodesList = codes
.stream() .stream()
.filter(t -> t.getCode() != null || t.getSystem() != null) .filter(t -> t.getCode() != null || t.getSystem() != null)
.sorted() .sorted()
@ -234,19 +234,19 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
List<Predicate> retVal = new ArrayList<>(); List<Predicate> retVal = new ArrayList<>();
// System only // System only
List<VersionIndependentConcept> systemOnlyCodes = sortedCodesList.stream().filter(t -> isBlank(t.getCode())).collect(Collectors.toList()); List<FhirVersionIndependentConcept> systemOnlyCodes = sortedCodesList.stream().filter(t -> isBlank(t.getCode())).collect(Collectors.toList());
if (!systemOnlyCodes.isEmpty()) { if (!systemOnlyCodes.isEmpty()) {
retVal.add(addPredicate(theResourceName, paramName, theBuilder, theFrom, systemOnlyCodes, modifier, SearchBuilderTokenModeEnum.SYSTEM_ONLY, theRequestPartitionId)); retVal.add(addPredicate(theResourceName, paramName, theBuilder, theFrom, systemOnlyCodes, modifier, SearchBuilderTokenModeEnum.SYSTEM_ONLY, theRequestPartitionId));
} }
// Code only // Code only
List<VersionIndependentConcept> codeOnlyCodes = sortedCodesList.stream().filter(t -> t.getSystem() == null).collect(Collectors.toList()); List<FhirVersionIndependentConcept> codeOnlyCodes = sortedCodesList.stream().filter(t -> t.getSystem() == null).collect(Collectors.toList());
if (!codeOnlyCodes.isEmpty()) { if (!codeOnlyCodes.isEmpty()) {
retVal.add(addPredicate(theResourceName, paramName, theBuilder, theFrom, codeOnlyCodes, modifier, SearchBuilderTokenModeEnum.VALUE_ONLY, theRequestPartitionId)); retVal.add(addPredicate(theResourceName, paramName, theBuilder, theFrom, codeOnlyCodes, modifier, SearchBuilderTokenModeEnum.VALUE_ONLY, theRequestPartitionId));
} }
// System and code // System and code
List<VersionIndependentConcept> systemAndCodeCodes = sortedCodesList.stream().filter(t -> isNotBlank(t.getCode()) && t.getSystem() != null).collect(Collectors.toList()); List<FhirVersionIndependentConcept> systemAndCodeCodes = sortedCodesList.stream().filter(t -> isNotBlank(t.getCode()) && t.getSystem() != null).collect(Collectors.toList());
if (!systemAndCodeCodes.isEmpty()) { if (!systemAndCodeCodes.isEmpty()) {
retVal.add(addPredicate(theResourceName, paramName, theBuilder, theFrom, systemAndCodeCodes, modifier, SearchBuilderTokenModeEnum.SYSTEM_AND_VALUE, theRequestPartitionId)); retVal.add(addPredicate(theResourceName, paramName, theBuilder, theFrom, systemAndCodeCodes, modifier, SearchBuilderTokenModeEnum.SYSTEM_AND_VALUE, theRequestPartitionId));
} }
@ -272,8 +272,8 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
String valueSet = valueSetUris.iterator().next(); String valueSet = valueSetUris.iterator().next();
ValueSetExpansionOptions options = new ValueSetExpansionOptions() ValueSetExpansionOptions options = new ValueSetExpansionOptions()
.setFailOnMissingCodeSystem(false); .setFailOnMissingCodeSystem(false);
List<VersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSet(options, valueSet); List<FhirVersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSet(options, valueSet);
for (VersionIndependentConcept nextCandidate : candidateCodes) { for (FhirVersionIndependentConcept nextCandidate : candidateCodes) {
if (nextCandidate.getCode().equals(code)) { if (nextCandidate.getCode().equals(code)) {
retVal = nextCandidate.getSystem(); retVal = nextCandidate.getSystem();
break; break;
@ -298,7 +298,7 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
} }
} }
private Predicate addPredicate(String theResourceName, String theParamName, CriteriaBuilder theBuilder, From<?, ResourceIndexedSearchParamToken> theFrom, List<VersionIndependentConcept> theTokens, TokenParamModifier theModifier, SearchBuilderTokenModeEnum theTokenMode, RequestPartitionId theRequestPartitionId) { private Predicate addPredicate(String theResourceName, String theParamName, CriteriaBuilder theBuilder, From<?, ResourceIndexedSearchParamToken> theFrom, List<FhirVersionIndependentConcept> theTokens, TokenParamModifier theModifier, SearchBuilderTokenModeEnum theTokenMode, RequestPartitionId theRequestPartitionId) {
if (myDontUseHashesForSearch) { if (myDontUseHashesForSearch) {
final Path<String> systemExpression = theFrom.get("mySystem"); final Path<String> systemExpression = theFrom.get("mySystem");
final Path<String> valueExpression = theFrom.get("myValue"); final Path<String> valueExpression = theFrom.get("myValue");
@ -317,7 +317,7 @@ class PredicateBuilderToken extends BasePredicateBuilder implements IPredicateBu
orPredicates.add(orPredicate); orPredicates.add(orPredicate);
break; break;
case SYSTEM_AND_VALUE: case SYSTEM_AND_VALUE:
for (VersionIndependentConcept next : theTokens) { for (FhirVersionIndependentConcept next : theTokens) {
orPredicates.add(theBuilder.and( orPredicates.add(theBuilder.and(
toEqualOrIsNullPredicate(systemExpression, next.getSystem()), toEqualOrIsNullPredicate(systemExpression, next.getSystem()),
toEqualOrIsNullPredicate(valueExpression, next.getCode()) toEqualOrIsNullPredicate(valueExpression, next.getCode())

View File

@ -22,11 +22,10 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
@ -52,14 +51,14 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> { public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4.class);
@Autowired
private ITermCodeSystemDao myCsDao;
@Autowired @Autowired
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@Autowired @Autowired
@ -99,7 +98,11 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
String system; String system;
if (haveCoding) { if (haveCoding) {
code = theCoding.getCode(); code = theCoding.getCode();
system = theCoding.getSystem(); if (theCoding.hasVersion()) {
system = theCoding.getSystem() + "|" + theCoding.getVersion();
} else {
system = theCoding.getSystem();
}
} else { } else {
code = theCode.getValue(); code = theCode.getValue();
system = theSystem.getValue(); system = theSystem.getValue();
@ -131,13 +134,8 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) { protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
super.preDelete(theResourceToDelete, theEntityToDelete); super.preDelete(theResourceToDelete, theEntityToDelete);
String codeSystemUrl = theResourceToDelete.getUrl(); myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
if (isNotBlank(codeSystemUrl)) {
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
if (persCs != null) {
myTermDeferredStorageSvc.deleteCodeSystem(persCs);
}
}
} }
@Override @Override
@ -155,5 +153,13 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
return retVal; return retVal;
} }
@Override
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl,
IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay,
Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
return myTerminologySvc.codeSystemValidateCode(theCodeSystemId, toStringOrNull(theCodeSystemUrl), toStringOrNull(theVersion), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
}
} }

View File

@ -32,6 +32,8 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.BooleanType; import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.CodeType;
@ -39,6 +41,7 @@ import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date; import java.util.Date;
@ -152,7 +155,11 @@ public class FhirResourceDaoConceptMapR4 extends BaseHapiFhirResourceDao<Concept
translationMatch.setSource(new UriType(element.getConceptMapUrl())); translationMatch.setSource(new UriType(element.getConceptMapUrl()));
if (element.getConceptMapGroupElementTargets().size() == 1) { if (element.getConceptMapGroupElementTargets().size() == 1) {
translationMatch.setEquivalence(new CodeType(element.getConceptMapGroupElementTargets().get(0).getEquivalence().toCode()));
ConceptMapEquivalence eq = element.getConceptMapGroupElementTargets().get(0).getEquivalence();
if (eq != null) {
translationMatch.setEquivalence(new CodeType(eq.toCode()));
}
} }
retVal.addMatch(translationMatch); retVal.addMatch(translationMatch);

View File

@ -20,26 +20,21 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; 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.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
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.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import org.apache.commons.codec.binary.StringUtils;
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;
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.IntegerType; import org.hl7.fhir.r4.model.IntegerType;
@ -48,7 +43,6 @@ import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r4.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r4.model.ValueSet.ConceptSetFilterComponent;
import org.hl7.fhir.r4.model.ValueSet.FilterOperator; import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -60,15 +54,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> { public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;
@Autowired
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@Autowired
private IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
@Override @Override
public void start() { public void start() {
@ -123,8 +109,7 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
filter.setValue(theFilter); filter.setValue(theFilter);
} }
ValueSet retVal = doExpand(source); return doExpand(source);
return retVal;
// if (defaultValueSet != null) { // if (defaultValueSet != null) {
// source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet)); // source = getContext().newJsonParser().parseResource(ValueSet.class, getContext().newJsonParser().encodeResourceToString(defaultValueSet));
@ -158,8 +143,7 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
filter.setValue(theFilter); filter.setValue(theFilter);
} }
ValueSet retVal = doExpand(source, theOffset, theCount); return doExpand(source, theOffset, theCount);
return retVal;
} }
@Override @Override
@ -197,6 +181,9 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
ValueSet toExpand = new ValueSet(); ValueSet toExpand = new ValueSet();
toExpand.setId(theSource.getId()); toExpand.setId(theSource.getId());
toExpand.setUrl(theSource.getUrl()); toExpand.setUrl(theSource.getUrl());
if (theSource.getVersion() != null) {
toExpand.setVersion(theSource.getVersion());
}
for (ConceptSetComponent next : theSource.getCompose().getInclude()) { for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
toExpand.getCompose().addInclude(next); toExpand.getCompose().addInclude(next);
@ -262,9 +249,9 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) { if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
if (retVal.getDeleted() == null) { if (retVal.getDeleted() == null) {
ValueSet valueSet = (ValueSet) theResource; ValueSet valueSet = (ValueSet) theResource;
myHapiTerminologySvc.storeTermValueSet(retVal, valueSet); myTerminologySvc.storeTermValueSet(retVal, valueSet);
} else { } else {
myHapiTerminologySvc.deleteValueSetAndChildren(retVal); myTerminologySvc.deleteValueSetAndChildren(retVal);
} }
} }

View File

@ -23,11 +23,10 @@ package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
@ -53,6 +52,8 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> { public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
@ -63,8 +64,6 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
@Autowired @Autowired
protected IdHelperService myIdHelperService; protected IdHelperService myIdHelperService;
@Autowired @Autowired
private ITermCodeSystemDao myCsDao;
@Autowired
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@Autowired @Autowired
private FhirContext myFhirContext; private FhirContext myFhirContext;
@ -101,7 +100,11 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
String system; String system;
if (haveCoding) { if (haveCoding) {
code = theCoding.getCode(); code = theCoding.getCode();
system = theCoding.getSystem(); if (theCoding.hasVersion()) {
system = theCoding.getSystem() + "|" + theCoding.getVersion();
} else {
system = theCoding.getSystem();
}
} else { } else {
code = theCode.getValue(); code = theCode.getValue();
system = theSystem.getValue(); system = theSystem.getValue();
@ -133,13 +136,8 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) { protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
super.preDelete(theResourceToDelete, theEntityToDelete); super.preDelete(theResourceToDelete, theEntityToDelete);
String codeSystemUrl = theResourceToDelete.getUrl(); myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
if (isNotBlank(codeSystemUrl)) {
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
if (persCs != null) {
myTermDeferredStorageSvc.deleteCodeSystem(persCs);
}
}
} }
@Override @Override
@ -157,5 +155,11 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
return retVal; return retVal;
} }
@Override
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl,
IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay,
Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
return myTerminologySvc.codeSystemValidateCode(theCodeSystemId, toStringOrNull(theCodeSystemUrl), toStringOrNull(theVersion), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
}
} }

View File

@ -1,5 +1,21 @@
package ca.uhn.fhir.jpa.dao.r5; package ca.uhn.fhir.jpa.dao.r5;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.UriType;
import org.springframework.beans.factory.annotation.Autowired;
/* /*
* #%L * #%L
* HAPI FHIR JPA Server * HAPI FHIR JPA Server
@ -29,23 +45,9 @@ 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.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.storage.TransactionDetails;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.convertors.VersionConvertor_40_50; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.UriType;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FhirResourceDaoConceptMapR5 extends BaseHapiFhirResourceDao<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> { public class FhirResourceDaoConceptMapR5 extends BaseHapiFhirResourceDao<ConceptMap> implements IFhirResourceDaoConceptMap<ConceptMap> {
@Autowired @Autowired
@ -153,7 +155,11 @@ public class FhirResourceDaoConceptMapR5 extends BaseHapiFhirResourceDao<Concept
translationMatch.setSource(VersionConvertor_40_50.convertUri(new UriType(element.getConceptMapUrl()))); translationMatch.setSource(VersionConvertor_40_50.convertUri(new UriType(element.getConceptMapUrl())));
if (element.getConceptMapGroupElementTargets().size() == 1) { if (element.getConceptMapGroupElementTargets().size() == 1) {
translationMatch.setEquivalence(VersionConvertor_40_50.convertCode(new CodeType(element.getConceptMapGroupElementTargets().get(0).getEquivalence().toCode())));
ConceptMapEquivalence eq = element.getConceptMapGroupElementTargets().get(0).getEquivalence();
if (eq != null) {
translationMatch.setEquivalence(VersionConvertor_40_50.convertCode(new CodeType(eq.toCode())));
}
} }
retVal.addMatch(translationMatch); retVal.addMatch(translationMatch);

View File

@ -20,26 +20,20 @@ package ca.uhn.fhir.jpa.dao.r5;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.support.ConceptValidationOptions;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; 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.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.util.LogicUtil;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import org.apache.commons.codec.binary.StringUtils;
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;
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.Enumerations; import org.hl7.fhir.r5.model.Enumerations;
@ -48,11 +42,7 @@ import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -64,18 +54,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> { public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
@Autowired
private ITermReadSvc myHapiTerminologySvc;
@Autowired
@Qualifier("myDefaultProfileValidationSupport")
private IValidationSupport myDefaultProfileValidationSupport;
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@Autowired
private IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
@Override @Override
public void start() { public void start() {
super.start(); super.start();
@ -164,8 +144,7 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
filter.setValue(theFilter); filter.setValue(theFilter);
} }
ValueSet retVal = doExpand(source, theOffset, theCount); return doExpand(source, theOffset, theCount);
return retVal;
} }
@Override @Override
@ -203,6 +182,9 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
ValueSet toExpand = new ValueSet(); ValueSet toExpand = new ValueSet();
toExpand.setId(theSource.getId()); toExpand.setId(theSource.getId());
toExpand.setUrl(theSource.getUrl()); toExpand.setUrl(theSource.getUrl());
if (theSource.getVersion() != null) {
toExpand.setVersion(theSource.getVersion());
}
for (ConceptSetComponent next : theSource.getCompose().getInclude()) { for (ConceptSetComponent next : theSource.getCompose().getInclude()) {
toExpand.getCompose().addInclude(next); toExpand.getCompose().addInclude(next);
@ -267,9 +249,9 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) { if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
if (retVal.getDeleted() == null) { if (retVal.getDeleted() == null) {
ValueSet valueSet = (ValueSet) theResource; ValueSet valueSet = (ValueSet) theResource;
myHapiTerminologySvc.storeTermValueSet(retVal, org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSet)); myTerminologySvc.storeTermValueSet(retVal, org.hl7.fhir.convertors.conv40_50.ValueSet40_50.convertValueSet(valueSet));
} else { } else {
myHapiTerminologySvc.deleteValueSetAndChildren(retVal); myTerminologySvc.deleteValueSetAndChildren(retVal);
} }
} }

View File

@ -58,7 +58,7 @@ public class TermCodeSystem implements Serializable {
@Column(name = "PID") @Column(name = "PID")
private Long myPid; private Long myPid;
@OneToOne(fetch = FetchType.LAZY) @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_RES")) @JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = true, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_RES"))
private ResourceTable myResource; private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false) @Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid; private Long myResourcePid;

View File

@ -40,17 +40,21 @@ import javax.persistence.OneToMany;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator; import javax.persistence.SequenceGenerator;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import static org.apache.commons.lang3.StringUtils.length; import static org.apache.commons.lang3.StringUtils.length;
@Table(name = "TRM_CODESYSTEM_VER" @Table(name = "TRM_CODESYSTEM_VER",
// Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this) // Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this)
) uniqueConstraints = {
@UniqueConstraint(name = TermCodeSystemVersion.IDX_CODESYSTEM_AND_VER, columnNames = {"CODESYSTEM_PID", "CS_VERSION_ID"})
})
@Entity() @Entity()
public class TermCodeSystemVersion implements Serializable { public class TermCodeSystemVersion implements Serializable {
public static final String IDX_CODESYSTEM_AND_VER = "IDX_CODESYSTEM_AND_VER";
public static final int MAX_VERSION_LENGTH = 200; public static final int MAX_VERSION_LENGTH = 200;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem") @OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem")

View File

@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.entity;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor; import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
import ca.uhn.fhir.util.VersionIndependentConcept;
import ca.uhn.fhir.util.ValidateUtil; import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;

View File

@ -35,12 +35,13 @@ import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_MAP", uniqueConstraints = { @Table(name = "TRM_CONCEPT_MAP", uniqueConstraints = {
@UniqueConstraint(name = "IDX_CONCEPT_MAP_URL", columnNames = {"URL"}) @UniqueConstraint(name = "IDX_CONCEPT_MAP_URL", columnNames = {"URL", "VER"})
}) })
public class TermConceptMap implements Serializable { public class TermConceptMap implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
static final int MAX_URL_LENGTH = 200; static final int MAX_URL_LENGTH = 200;
public static final int MAX_VER_LENGTH = 200;
@Id() @Id()
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID") @SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID")
@ -64,6 +65,9 @@ public class TermConceptMap implements Serializable {
@Column(name = "URL", nullable = false, length = MAX_URL_LENGTH) @Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
private String myUrl; private String myUrl;
@Column(name = "VER", nullable = true, length = MAX_VER_LENGTH)
private String myVersion;
@OneToMany(mappedBy = "myConceptMap") @OneToMany(mappedBy = "myConceptMap")
private List<TermConceptMapGroup> myConceptMapGroups; private List<TermConceptMapGroup> myConceptMapGroups;
@ -131,6 +135,17 @@ public class TermConceptMap implements Serializable {
return this; return this;
} }
public String getVersion() {
return myVersion;
}
public TermConceptMap setVersion(String theVersion) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theVersion, MAX_VER_LENGTH,
"Version exceeds maximum length (" + MAX_VER_LENGTH + "): " + length(theVersion));
myVersion = theVersion;
return this;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
@ -140,6 +155,7 @@ public class TermConceptMap implements Serializable {
.append("mySource", mySource) .append("mySource", mySource)
.append("myTarget", myTarget) .append("myTarget", myTarget)
.append("myUrl", myUrl) .append("myUrl", myUrl)
.append("myVersion", myVersion)
.append(myConceptMapGroups != null ? ("myConceptMapGroups - size=" + myConceptMapGroups.size()) : ("myConceptMapGroups=(null)")) .append(myConceptMapGroups != null ? ("myConceptMapGroups - size=" + myConceptMapGroups.size()) : ("myConceptMapGroups=(null)"))
.toString(); .toString();
} }

View File

@ -37,7 +37,7 @@ import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length; import static org.apache.commons.lang3.StringUtils.length;
@Table(name = "TRM_VALUESET", uniqueConstraints = { @Table(name = "TRM_VALUESET", uniqueConstraints = {
@UniqueConstraint(name = "IDX_VALUESET_URL", columnNames = {"URL"}) @UniqueConstraint(name = "IDX_VALUESET_URL", columnNames = {"URL", "VER"})
}) })
@Entity() @Entity()
public class TermValueSet implements Serializable { public class TermValueSet implements Serializable {
@ -46,6 +46,7 @@ public class TermValueSet implements Serializable {
public static final int MAX_EXPANSION_STATUS_LENGTH = 50; public static final int MAX_EXPANSION_STATUS_LENGTH = 50;
public static final int MAX_NAME_LENGTH = 200; public static final int MAX_NAME_LENGTH = 200;
public static final int MAX_URL_LENGTH = 200; public static final int MAX_URL_LENGTH = 200;
public static final int MAX_VER_LENGTH = 200;
@Id() @Id()
@SequenceGenerator(name = "SEQ_VALUESET_PID", sequenceName = "SEQ_VALUESET_PID") @SequenceGenerator(name = "SEQ_VALUESET_PID", sequenceName = "SEQ_VALUESET_PID")
@ -56,6 +57,9 @@ public class TermValueSet implements Serializable {
@Column(name = "URL", nullable = false, length = MAX_URL_LENGTH) @Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
private String myUrl; private String myUrl;
@Column(name = "VER", nullable = true, length = MAX_VER_LENGTH)
private String myVersion;
@OneToOne() @OneToOne()
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMVALUESET_RES")) @JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMVALUESET_RES"))
private ResourceTable myResource; private ResourceTable myResource;
@ -183,6 +187,17 @@ public class TermValueSet implements Serializable {
myExpansionStatus = theExpansionStatus; myExpansionStatus = theExpansionStatus;
} }
public String getVersion() {
return myVersion;
}
public TermValueSet setVersion(String theVersion) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theVersion, MAX_VER_LENGTH,
"Version exceeds maximum length (" + MAX_VER_LENGTH + "): " + length(theVersion));
myVersion = theVersion;
return this;
}
@Override @Override
public boolean equals(Object theO) { public boolean equals(Object theO) {
if (this == theO) return true; if (this == theO) return true;

View File

@ -53,6 +53,7 @@ public class BaseJpaResourceProviderCodeSystemDstu3 extends JpaResourceProviderD
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding, @OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
@OperationParam(name="version", min=0, max=1) StringType theVersion,
@OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties, @OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
@ -60,7 +61,12 @@ public class BaseJpaResourceProviderCodeSystemDstu3 extends JpaResourceProviderD
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao(); IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails); IValidationSupport.LookupCodeResult result;
if (theVersion != null) {
result = dao.lookupCode(theCode, new UriType(theSystem.getValue() + "|" + theVersion), theCoding, theRequestDetails);
} else {
result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
}
result.throwNotFoundIfAppropriate(); result.throwNotFoundIfAppropriate();
return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties); return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties);
} catch (FHIRException e) { } catch (FHIRException e) {
@ -84,13 +90,18 @@ public class BaseJpaResourceProviderCodeSystemDstu3 extends JpaResourceProviderD
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
@OperationParam(name = "codingA", min = 0, max = 1) Coding theCodingA, @OperationParam(name = "codingA", min = 0, max = 1) Coding theCodingA,
@OperationParam(name = "codingB", min = 0, max = 1) Coding theCodingB, @OperationParam(name = "codingB", min = 0, max = 1) Coding theCodingB,
@OperationParam(name = "version", min = 0, max = 1) StringType theVersion,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao(); IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IFhirResourceDaoCodeSystem.SubsumesResult result = dao.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theRequestDetails); IFhirResourceDaoCodeSystem.SubsumesResult result;
if (theVersion != null) {
theSystem = new UriType(theSystem.asStringValue() + "|" + theVersion.toString());
}
result = dao.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theRequestDetails);
return (Parameters) result.toParameters(theRequestDetails.getFhirContext()); return (Parameters) result.toParameters(theRequestDetails.getFhirContext());
} finally { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);

View File

@ -54,6 +54,8 @@ public class BaseJpaResourceProviderConceptMapDstu3 extends JpaResourceProviderD
public Parameters translate( public Parameters translate(
HttpServletRequest theServletRequest, HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
@OperationParam(name = "conceptMapVersion", min = 0, max = 1) StringType theConceptMapVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem,
@OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion, @OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion,
@ -65,6 +67,10 @@ public class BaseJpaResourceProviderConceptMapDstu3 extends JpaResourceProviderD
@OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse, @OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
boolean haveUrl = theUrl != null
&& theUrl.hasValue();
boolean haveConceptMapVersion = theConceptMapVersion != null
&& theConceptMapVersion.hasValue();
boolean haveSourceCode = theSourceCode != null boolean haveSourceCode = theSourceCode != null
&& theSourceCode.hasValue(); && theSourceCode.hasValue();
boolean haveSourceCodeSystem = theSourceCodeSystem != null boolean haveSourceCodeSystem = theSourceCodeSystem != null
@ -93,6 +99,15 @@ public class BaseJpaResourceProviderConceptMapDstu3 extends JpaResourceProviderD
TranslationRequest translationRequest = new TranslationRequest(); TranslationRequest translationRequest = new TranslationRequest();
try { try {
if (haveUrl) {
translationRequest.setUrl(VersionConvertor_30_40.convertUri(theUrl));
}
if (haveConceptMapVersion) {
translationRequest.setConceptMapVersion(VersionConvertor_30_40.convertString(theConceptMapVersion));
}
// Convert from DSTU3 to R4 // Convert from DSTU3 to R4
if (haveSourceCode) { if (haveSourceCode) {
translationRequest.getCodeableConcept().addCoding().setCodeElement(VersionConvertor_30_40.convertCode(theSourceCode)); translationRequest.getCodeableConcept().addCoding().setCodeElement(VersionConvertor_30_40.convertCode(theSourceCode));

View File

@ -46,6 +46,7 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
// Note: url is correct and identifier is not, but identifier was only added as // Note: url is correct and identifier is not, but identifier was only added as
// of 3.1.0 so we'll leave url for now. See: https://groups.google.com/d/msgid/hapi-fhir/CAN2Cfy8kW%2BAOkgC6VjPsU3gRCpExCNZBmJdi-k5R_TWeyWH4tA%40mail.gmail.com?utm_medium=email&utm_source=footer // of 3.1.0 so we'll leave url for now. See: https://groups.google.com/d/msgid/hapi-fhir/CAN2Cfy8kW%2BAOkgC6VjPsU3gRCpExCNZBmJdi-k5R_TWeyWH4tA%40mail.gmail.com?utm_medium=email&utm_source=footer
@OperationParam(name = "url", min = 0, max = 1) UriType theUrl, @OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
@OperationParam(name = "valueSetVersion", min = 0, max = 1) StringType theValueSetVersion,
@OperationParam(name = "identifier", min = 0, max = 1) UriType theIdentifier, @OperationParam(name = "identifier", min = 0, max = 1) UriType theIdentifier,
@OperationParam(name = "filter", min = 0, max = 1) StringType theFilter, @OperationParam(name = "filter", min = 0, max = 1) StringType theFilter,
@OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset, @OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset,
@ -60,6 +61,7 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
boolean haveIdentifier = url != null && isNotBlank(url.getValue()); boolean haveIdentifier = url != null && isNotBlank(url.getValue());
boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty(); boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty();
boolean haveValueSetVersion = theValueSetVersion != null && !theValueSetVersion.isEmpty();
if (!haveId && !haveIdentifier && !haveValueSet) { if (!haveId && !haveIdentifier && !haveValueSet) {
throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request."); throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request.");
@ -99,7 +101,11 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
if (haveId) { if (haveId) {
return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails); return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails);
} else if (haveIdentifier) { } else if (haveIdentifier) {
return dao.expandByIdentifier(url.getValue(), toFilterString(theFilter), offset, count); if (haveValueSetVersion) {
return dao.expandByIdentifier(url.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter), offset, count);
} else {
return dao.expandByIdentifier(url.getValue(), toFilterString(theFilter), offset, count);
}
} else { } else {
return dao.expand(theValueSet, toFilterString(theFilter), offset, count); return dao.expand(theValueSet, toFilterString(theFilter), offset, count);
} }
@ -107,7 +113,11 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
if (haveId) { if (haveId) {
return dao.expand(theId, toFilterString(theFilter), theRequestDetails); return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
} else if (haveIdentifier) { } else if (haveIdentifier) {
return dao.expandByIdentifier(url.getValue(), toFilterString(theFilter)); if (haveValueSetVersion) {
return dao.expandByIdentifier(url.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter));
} else {
return dao.expandByIdentifier(url.getValue(), toFilterString(theFilter));
}
} else { } else {
return dao.expand(theValueSet, toFilterString(theFilter)); return dao.expand(theValueSet, toFilterString(theFilter));
} }
@ -123,7 +133,6 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
} }
@SuppressWarnings("unchecked")
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = { @Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = {
@OperationParam(name = "result", type = BooleanType.class, min = 1), @OperationParam(name = "result", type = BooleanType.class, min = 1),
@OperationParam(name = "message", type = StringType.class), @OperationParam(name = "message", type = StringType.class),
@ -134,8 +143,10 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "identifier", min = 0, max = 1) UriType theValueSetIdentifier, @OperationParam(name = "identifier", min = 0, max = 1) UriType theValueSetIdentifier,
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl, @OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
@OperationParam(name = "valueSetVersion", min = 0, max = 1) StringType theValueSetVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
@OperationParam(name = "systemVersion", min = 0, max = 1) StringType theSystemVersion,
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay, @OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding, @OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept, @OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept,
@ -150,7 +161,19 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao(); IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
IValidationSupport.CodeValidationResult result = dao.validateCode(url, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails); UriType valueSetIdentifier;
if (theValueSetVersion != null) {
valueSetIdentifier = new UriType(url.getValue() + "|" + theValueSetVersion);
} else {
valueSetIdentifier = url;
}
UriType codeSystemIdentifier;
if (theSystemVersion != null) {
codeSystemIdentifier = new UriType(theSystem.getValue() + "|" + theSystemVersion);
} else {
codeSystemIdentifier = theSystem;
}
IValidationSupport.CodeValidationResult result = dao.validateCode(valueSetIdentifier, theId, theCode, codeSystemIdentifier, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result); return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
} finally { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);

View File

@ -1,5 +1,19 @@
package ca.uhn.fhir.jpa.provider.r4; package ca.uhn.fhir.jpa.provider.r4;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
/* /*
* #%L * #%L
* HAPI FHIR JPA Server * HAPI FHIR JPA Server
@ -23,20 +37,11 @@ package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
public class BaseJpaResourceProviderCodeSystemR4 extends JpaResourceProviderR4<CodeSystem> { public class BaseJpaResourceProviderCodeSystemR4 extends JpaResourceProviderR4<CodeSystem> {
@ -55,6 +60,7 @@ public class BaseJpaResourceProviderCodeSystemR4 extends JpaResourceProviderR4<C
@OperationParam(name="code", min=0, max=1) CodeType theCode, @OperationParam(name="code", min=0, max=1) CodeType theCode,
@OperationParam(name="system", min=0, max=1) UriType theSystem, @OperationParam(name="system", min=0, max=1) UriType theSystem,
@OperationParam(name="coding", min=0, max=1) Coding theCoding, @OperationParam(name="coding", min=0, max=1) Coding theCoding,
@OperationParam(name="version", min=0, max=1) StringType theVersion,
@OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties, @OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
@ -62,7 +68,12 @@ public class BaseJpaResourceProviderCodeSystemR4 extends JpaResourceProviderR4<C
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao(); IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails); IValidationSupport.LookupCodeResult result;
if (theVersion != null) {
result = dao.lookupCode(theCode, new UriType(theSystem.getValue() + "|" + theVersion), theCoding, theRequestDetails);
} else {
result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
}
result.throwNotFoundIfAppropriate(); result.throwNotFoundIfAppropriate();
return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties); return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties);
} finally { } finally {
@ -84,16 +95,53 @@ public class BaseJpaResourceProviderCodeSystemR4 extends JpaResourceProviderR4<C
@OperationParam(name="system", min=0, max=1) UriType theSystem, @OperationParam(name="system", min=0, max=1) UriType theSystem,
@OperationParam(name="codingA", min=0, max=1) Coding theCodingA, @OperationParam(name="codingA", min=0, max=1) Coding theCodingA,
@OperationParam(name="codingB", min=0, max=1) Coding theCodingB, @OperationParam(name="codingB", min=0, max=1) Coding theCodingB,
@OperationParam(name="version", min=0, max=1) StringType theVersion,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao(); IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IFhirResourceDaoCodeSystem.SubsumesResult result = dao.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theRequestDetails); IFhirResourceDaoCodeSystem.SubsumesResult result;
if (theVersion != null) {
theSystem = new UriType(theSystem.asStringValue() + "|" + theVersion.toString());
}
result = dao.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theRequestDetails);
return (Parameters) result.toParameters(theRequestDetails.getFhirContext()); return (Parameters) result.toParameters(theRequestDetails.getFhirContext());
} finally { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);
} }
} }
/**
* $validate-code operation
*/
@SuppressWarnings("unchecked")
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = {
@OperationParam(name = "result", type = BooleanType.class, min = 1),
@OperationParam(name = "message", type = StringType.class),
@OperationParam(name = "display", type = StringType.class)
})
public Parameters validateCode(
HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theCodeSystemUrl,
@OperationParam(name = "version", min = 0, max = 1) StringType theVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept,
RequestDetails theRequestDetails
) {
startRequest(theServletRequest);
try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IValidationSupport.CodeValidationResult result = dao.validateCode(theId, theCodeSystemUrl, theVersion, theCode, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
} finally {
endRequest(theServletRequest);
}
}
} }

View File

@ -49,6 +49,8 @@ public class BaseJpaResourceProviderConceptMapR4 extends JpaResourceProviderR4<C
public Parameters translate( public Parameters translate(
HttpServletRequest theServletRequest, HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
@OperationParam(name = "conceptMapVersion", min = 0, max = 1) StringType theConceptMapVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem,
@OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion, @OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion,
@ -60,6 +62,10 @@ public class BaseJpaResourceProviderConceptMapR4 extends JpaResourceProviderR4<C
@OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse, @OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
boolean haveUrl = theUrl != null
&& theUrl.hasValue();
boolean haveConceptMapVersion = theConceptMapVersion != null
&& theConceptMapVersion.hasValue();
boolean haveSourceCode = theSourceCode != null boolean haveSourceCode = theSourceCode != null
&& theSourceCode.hasCode(); && theSourceCode.hasCode();
boolean haveSourceCodeSystem = theSourceCodeSystem != null boolean haveSourceCodeSystem = theSourceCodeSystem != null
@ -88,6 +94,14 @@ public class BaseJpaResourceProviderConceptMapR4 extends JpaResourceProviderR4<C
TranslationRequest translationRequest = new TranslationRequest(); TranslationRequest translationRequest = new TranslationRequest();
if (haveUrl) {
translationRequest.setUrl(theUrl);
}
if (haveConceptMapVersion) {
translationRequest.setConceptMapVersion(theConceptMapVersion);
}
if (haveSourceCode) { if (haveSourceCode) {
translationRequest.getCodeableConcept().addCoding().setCodeElement(theSourceCode); translationRequest.getCodeableConcept().addCoding().setCodeElement(theSourceCode);

View File

@ -44,6 +44,7 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "valueSet", min = 0, max = 1) ValueSet theValueSet, @OperationParam(name = "valueSet", min = 0, max = 1) ValueSet theValueSet,
@OperationParam(name = "url", min = 0, max = 1) UriType theUrl, @OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
@OperationParam(name = "valueSetVersion", min = 0, max = 1) StringType theValueSetVersion,
@OperationParam(name = "filter", min = 0, max = 1) StringType theFilter, @OperationParam(name = "filter", min = 0, max = 1) StringType theFilter,
@OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset, @OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset,
@OperationParam(name = "count", min = 0, max = 1) IntegerType theCount, @OperationParam(name = "count", min = 0, max = 1) IntegerType theCount,
@ -52,6 +53,7 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
boolean haveId = theId != null && theId.hasIdPart(); boolean haveId = theId != null && theId.hasIdPart();
boolean haveIdentifier = theUrl != null && isNotBlank(theUrl.getValue()); boolean haveIdentifier = theUrl != null && isNotBlank(theUrl.getValue());
boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty(); boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty();
boolean haveValueSetVersion = theValueSetVersion != null && !theValueSetVersion.isEmpty();
if (!haveId && !haveIdentifier && !haveValueSet) { if (!haveId && !haveIdentifier && !haveValueSet) {
throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires a url or a valueSet as a part of the request."); throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires a url or a valueSet as a part of the request.");
@ -91,7 +93,11 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
if (haveId) { if (haveId) {
return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails); return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails);
} else if (haveIdentifier) { } else if (haveIdentifier) {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter), offset, count); if (haveValueSetVersion) {
return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter), offset, count);
} else {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter), offset, count);
}
} else { } else {
return dao.expand(theValueSet, toFilterString(theFilter), offset, count); return dao.expand(theValueSet, toFilterString(theFilter), offset, count);
} }
@ -99,7 +105,11 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
if (haveId) { if (haveId) {
return dao.expand(theId, toFilterString(theFilter), theRequestDetails); return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
} else if (haveIdentifier) { } else if (haveIdentifier) {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter)); if (haveValueSetVersion) {
return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter));
} else {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter));
}
} else { } else {
return dao.expand(theValueSet, toFilterString(theFilter)); return dao.expand(theValueSet, toFilterString(theFilter));
} }
@ -125,8 +135,10 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
HttpServletRequest theServletRequest, HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl, @OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
@OperationParam(name = "valueSetVersion", min = 0, max = 1) StringType theValueSetVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
@OperationParam(name = "systemVersion", min = 0, max = 1) StringType theSystemVersion,
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay, @OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding, @OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept, @OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept,
@ -136,7 +148,19 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4<Val
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao(); IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails); UriType valueSetIdentifier;
if (theValueSetVersion != null) {
valueSetIdentifier = new UriType(theValueSetUrl.getValue() + "|" + theValueSetVersion);
} else {
valueSetIdentifier = theValueSetUrl;
}
UriType codeSystemIdentifier;
if (theSystemVersion != null) {
codeSystemIdentifier = new UriType(theSystem.getValue() + "|" + theSystemVersion);
} else {
codeSystemIdentifier = theSystem;
}
IValidationSupport.CodeValidationResult result = dao.validateCode(valueSetIdentifier, theId, theCode, codeSystemIdentifier, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result); return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
} finally { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);

View File

@ -23,9 +23,13 @@ package ca.uhn.fhir.jpa.provider.r5;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.r5.model.IdType;
import org.hl7.fhir.r5.model.BooleanType; import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeType; import org.hl7.fhir.r5.model.CodeType;
@ -55,6 +59,7 @@ public class BaseJpaResourceProviderCodeSystemR5 extends JpaResourceProviderR5<C
@OperationParam(name="code", min=0, max=1) CodeType theCode, @OperationParam(name="code", min=0, max=1) CodeType theCode,
@OperationParam(name="system", min=0, max=1) UriType theSystem, @OperationParam(name="system", min=0, max=1) UriType theSystem,
@OperationParam(name="coding", min=0, max=1) Coding theCoding, @OperationParam(name="coding", min=0, max=1) Coding theCoding,
@OperationParam(name="version", min=0, max=1) StringType theVersion,
@OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties, @OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED) List<CodeType> theProperties,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
@ -62,7 +67,12 @@ public class BaseJpaResourceProviderCodeSystemR5 extends JpaResourceProviderR5<C
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao(); IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails); IValidationSupport.LookupCodeResult result;
if (theVersion != null) {
result = dao.lookupCode(theCode, new UriType(theSystem.getValue() + "|" + theVersion), theCoding, theRequestDetails);
} else {
result = dao.lookupCode(theCode, theSystem, theCoding, theRequestDetails);
}
result.throwNotFoundIfAppropriate(); result.throwNotFoundIfAppropriate();
return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties); return (Parameters) result.toParameters(theRequestDetails.getFhirContext(), theProperties);
} finally { } finally {
@ -84,16 +94,53 @@ public class BaseJpaResourceProviderCodeSystemR5 extends JpaResourceProviderR5<C
@OperationParam(name="system", min=0, max=1) UriType theSystem, @OperationParam(name="system", min=0, max=1) UriType theSystem,
@OperationParam(name="codingA", min=0, max=1) Coding theCodingA, @OperationParam(name="codingA", min=0, max=1) Coding theCodingA,
@OperationParam(name="codingB", min=0, max=1) Coding theCodingB, @OperationParam(name="codingB", min=0, max=1) Coding theCodingB,
@OperationParam(name="version", min=0, max=1) StringType theVersion,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao(); IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IFhirResourceDaoCodeSystem.SubsumesResult result = dao.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theRequestDetails); IFhirResourceDaoCodeSystem.SubsumesResult result;
if (theVersion != null) {
theSystem = new UriType(theSystem.asStringValue() + "|" + theVersion.toString());
}
result = dao.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB, theRequestDetails);
return (Parameters) result.toParameters(theRequestDetails.getFhirContext()); return (Parameters) result.toParameters(theRequestDetails.getFhirContext());
} finally { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);
} }
} }
/**
* $validate-code operation
*/
@SuppressWarnings("unchecked")
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = {
@OperationParam(name = "result", type = BooleanType.class, min = 1),
@OperationParam(name = "message", type = StringType.class),
@OperationParam(name = "display", type = StringType.class)
})
public Parameters validateCode(
HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theCodeSystemUrl,
@OperationParam(name = "version", min = 0, max = 1) StringType theVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept,
RequestDetails theRequestDetails
) {
startRequest(theServletRequest);
try {
IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> dao = (IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept>) getDao();
IValidationSupport.CodeValidationResult result = dao.validateCode(theId, theCodeSystemUrl, theVersion, theCode, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
} finally {
endRequest(theServletRequest);
}
}
} }

View File

@ -50,6 +50,8 @@ public class BaseJpaResourceProviderConceptMapR5 extends JpaResourceProviderR5<C
public Parameters translate( public Parameters translate(
HttpServletRequest theServletRequest, HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
@OperationParam(name = "conceptMapVersion", min = 0, max = 1) StringType theConceptMapVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem,
@OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion, @OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion,
@ -61,6 +63,10 @@ public class BaseJpaResourceProviderConceptMapR5 extends JpaResourceProviderR5<C
@OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse, @OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse,
RequestDetails theRequestDetails RequestDetails theRequestDetails
) { ) {
boolean haveUrl = theUrl != null
&& theUrl.hasValue();
boolean haveConceptMapVersion = theConceptMapVersion != null
&& theConceptMapVersion.hasValue();
boolean haveSourceCode = theSourceCode != null boolean haveSourceCode = theSourceCode != null
&& theSourceCode.hasCode(); && theSourceCode.hasCode();
boolean haveSourceCodeSystem = theSourceCodeSystem != null boolean haveSourceCodeSystem = theSourceCodeSystem != null
@ -89,6 +95,14 @@ public class BaseJpaResourceProviderConceptMapR5 extends JpaResourceProviderR5<C
TranslationRequest translationRequest = new TranslationRequest(); TranslationRequest translationRequest = new TranslationRequest();
if (haveUrl) {
translationRequest.setUrl(VersionConvertor_40_50.convertUri(theUrl));
}
if (haveConceptMapVersion) {
translationRequest.setConceptMapVersion(VersionConvertor_40_50.convertString(theConceptMapVersion));
}
if (haveSourceCode) { if (haveSourceCode) {
translationRequest.getCodeableConcept().addCoding().setCodeElement(VersionConvertor_40_50.convertCode(theSourceCode)); translationRequest.getCodeableConcept().addCoding().setCodeElement(VersionConvertor_40_50.convertCode(theSourceCode));

View File

@ -44,6 +44,7 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "valueSet", min = 0, max = 1) ValueSet theValueSet, @OperationParam(name = "valueSet", min = 0, max = 1) ValueSet theValueSet,
@OperationParam(name = "url", min = 0, max = 1) UriType theUrl, @OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
@OperationParam(name = "valueSetVersion", min = 0, max = 1) StringType theValueSetVersion,
@OperationParam(name = "filter", min = 0, max = 1) StringType theFilter, @OperationParam(name = "filter", min = 0, max = 1) StringType theFilter,
@OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset, @OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset,
@OperationParam(name = "count", min = 0, max = 1) IntegerType theCount, @OperationParam(name = "count", min = 0, max = 1) IntegerType theCount,
@ -52,6 +53,7 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
boolean haveId = theId != null && theId.hasIdPart(); boolean haveId = theId != null && theId.hasIdPart();
boolean haveIdentifier = theUrl != null && isNotBlank(theUrl.getValue()); boolean haveIdentifier = theUrl != null && isNotBlank(theUrl.getValue());
boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty(); boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty();
boolean haveValueSetVersion = theValueSetVersion != null && !theValueSetVersion.isEmpty();
if (!haveId && !haveIdentifier && !haveValueSet) { if (!haveId && !haveIdentifier && !haveValueSet) {
throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires a url or a valueSet as a part of the request."); throw new InvalidRequestException("$expand operation at the type level (no ID specified) requires a url or a valueSet as a part of the request.");
@ -91,7 +93,11 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
if (haveId) { if (haveId) {
return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails); return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails);
} else if (haveIdentifier) { } else if (haveIdentifier) {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter), offset, count); if (haveValueSetVersion) {
return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter), offset, count);
} else {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter), offset, count);
}
} else { } else {
return dao.expand(theValueSet, toFilterString(theFilter), offset, count); return dao.expand(theValueSet, toFilterString(theFilter), offset, count);
} }
@ -99,7 +105,11 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
if (haveId) { if (haveId) {
return dao.expand(theId, toFilterString(theFilter), theRequestDetails); return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
} else if (haveIdentifier) { } else if (haveIdentifier) {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter)); if (haveValueSetVersion) {
return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter));
} else {
return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter));
}
} else { } else {
return dao.expand(theValueSet, toFilterString(theFilter)); return dao.expand(theValueSet, toFilterString(theFilter));
} }
@ -125,8 +135,10 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
HttpServletRequest theServletRequest, HttpServletRequest theServletRequest,
@IdParam(optional = true) IdType theId, @IdParam(optional = true) IdType theId,
@OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl, @OperationParam(name = "url", min = 0, max = 1) UriType theValueSetUrl,
@OperationParam(name = "valueSetVersion", min = 0, max = 1) StringType theValueSetVersion,
@OperationParam(name = "code", min = 0, max = 1) CodeType theCode, @OperationParam(name = "code", min = 0, max = 1) CodeType theCode,
@OperationParam(name = "system", min = 0, max = 1) UriType theSystem, @OperationParam(name = "system", min = 0, max = 1) UriType theSystem,
@OperationParam(name = "systemVersion", min = 0, max = 1) StringType theSystemVersion,
@OperationParam(name = "display", min = 0, max = 1) StringType theDisplay, @OperationParam(name = "display", min = 0, max = 1) StringType theDisplay,
@OperationParam(name = "coding", min = 0, max = 1) Coding theCoding, @OperationParam(name = "coding", min = 0, max = 1) Coding theCoding,
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept, @OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theCodeableConcept,
@ -136,7 +148,19 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5<Val
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao(); IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> dao = (IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept>) getDao();
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetUrl, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails); UriType valueSetIdentifier;
if (theValueSetVersion != null) {
valueSetIdentifier = new UriType(theValueSetUrl.getValue() + "|" + theValueSetVersion);
} else {
valueSetIdentifier = theValueSetUrl;
}
UriType codeSystemIdentifier;
if (theSystemVersion != null) {
codeSystemIdentifier = new UriType(theSystem.getValue() + "|" + theSystemVersion);
} else {
codeSystemIdentifier = theSystem;
}
IValidationSupport.CodeValidationResult result = dao.validateCode(valueSetIdentifier, theId, theCode, codeSystemIdentifier, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result); return (Parameters) BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
} finally { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);

View File

@ -231,6 +231,15 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
}); });
} }
@Override
@Transactional(propagation = Propagation.NEVER)
public void deleteCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
// Delete TermCodeSystemVersion
ourLog.info(" * Deleting TermCodeSystemVersion {}", theCodeSystemVersion.getCodeSystemVersionId());
deleteCodeSystemVersion(theCodeSystemVersion.getPid());
}
/** /**
* Returns the number of saved concepts * Returns the number of saved concepts
*/ */
@ -284,16 +293,19 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
ResourcePersistentId 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 and codesystem version already exists, we don't want to
* already exists, since that will wipe out the existing concepts. We do create or update * overwrite the existing version since that will wipe out the existing concepts. We do create
* the TermCodeSystem table though, since that allows the DB to reject changes * or update the TermCodeSystem table though, since that allows the DB to reject changes that would
* that would result in duplicate CodeSysten.url values. * result in duplicate CodeSystem.url values.
*/ */
if (theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.NOTPRESENT) { if (theCodeSystem.getContent() == CodeSystem.CodeSystemContentMode.NOTPRESENT) {
TermCodeSystem codeSystem = myCodeSystemDao.findByCodeSystemUri(theCodeSystem.getUrl()); TermCodeSystem termCodeSystem = myCodeSystemDao.findByCodeSystemUri(theCodeSystem.getUrl());
if (codeSystem != null) { if (termCodeSystem != null) {
getOrCreateTermCodeSystem(codeSystemResourcePid, theCodeSystem.getUrl(), theCodeSystem.getUrl(), theResourceEntity); TermCodeSystemVersion codeSystemVersion = getExistingTermCodeSystemVersion(termCodeSystem.getPid(), theCodeSystem.getVersion());
return; if (codeSystemVersion != null) {
TermCodeSystem myCodeSystemEntity = getOrCreateDistinctTermCodeSystem(codeSystemResourcePid, theCodeSystem.getUrl(), theCodeSystem.getUrl(), theCodeSystem.getVersion(), theResourceEntity);
return;
}
} }
} }
@ -338,11 +350,11 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
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 version so we can delete it
List<TermCodeSystemVersion> existing = myCodeSystemVersionDao.findByCodeSystemResourcePid(theCodeSystemResourcePid.getIdAsLong()); 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. * Delete version being replaced.
*/ */
for (TermCodeSystemVersion next : existing) { for (TermCodeSystemVersion next : existing) {
@ -351,16 +363,11 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
deleteCodeSystemVersion(codeSystemVersionPid); deleteCodeSystemVersion(codeSystemVersionPid);
} }
ourLog.debug("Flushing...");
myConceptDao.flush();
ourLog.debug("Done flushing");
/* /*
* Do the upload * Do the upload
*/ */
TermCodeSystem codeSystem = getOrCreateTermCodeSystem(theCodeSystemResourcePid, theSystemUri, theSystemName, theCodeSystemResourceTable); TermCodeSystem codeSystem = getOrCreateDistinctTermCodeSystem(theCodeSystemResourcePid, theSystemUri, theSystemName, theSystemVersionId, theCodeSystemResourceTable);
theCodeSystemVersion.setCodeSystem(codeSystem); theCodeSystemVersion.setCodeSystem(codeSystem);
theCodeSystemVersion.setCodeSystemDisplayName(theSystemName); theCodeSystemVersion.setCodeSystemDisplayName(theSystemName);
@ -408,6 +415,17 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
} }
} }
private TermCodeSystemVersion getExistingTermCodeSystemVersion(Long theCodeSystemVersionPid, String theCodeSystemVersion) {
TermCodeSystemVersion existing;
if (theCodeSystemVersion == null) {
existing = myCodeSystemVersionDao.findByCodeSystemPidVersionIsNull(theCodeSystemVersionPid);
} else {
existing = myCodeSystemVersionDao.findByCodeSystemPidAndVersion(theCodeSystemVersionPid, theCodeSystemVersion);
}
return existing;
}
private void deleteCodeSystemVersion(final Long theCodeSystemVersionPid) { private void deleteCodeSystemVersion(final Long theCodeSystemVersionPid) {
ourLog.info(" * Deleting code system version {}", theCodeSystemVersionPid); ourLog.info(" * Deleting code system version {}", theCodeSystemVersionPid);
@ -455,10 +473,12 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
ourLog.info(" * Removing code system version {} as current version of code system {}", theCodeSystemVersionPid, codeSystem.getPid()); ourLog.info(" * Removing code system version {} as current version of code system {}", theCodeSystemVersionPid, codeSystem.getPid());
codeSystem.setCurrentVersion(null); codeSystem.setCurrentVersion(null);
myCodeSystemDao.save(codeSystem); myCodeSystemDao.save(codeSystem);
myCodeSystemDao.flush();
} }
ourLog.info(" * Deleting code system version"); ourLog.info(" * Deleting code system version");
myCodeSystemVersionDao.deleteById(theCodeSystemVersionPid); myCodeSystemVersionDao.delete(theCodeSystemVersionPid);
myCodeSystemVersionDao.flush();
}); });
} }
@ -651,28 +671,48 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
} }
@Nonnull @Nonnull
private TermCodeSystem getOrCreateTermCodeSystem(ResourcePersistentId theCodeSystemResourcePid, String theSystemUri, String theSystemName, ResourceTable theCodeSystemResourceTable) { private TermCodeSystem getOrCreateDistinctTermCodeSystem(ResourcePersistentId theCodeSystemResourcePid, String theSystemUri, String theSystemName, String theSystemVersionId, ResourceTable theCodeSystemResourceTable) {
TermCodeSystem codeSystem = myCodeSystemDao.findByCodeSystemUri(theSystemUri); TermCodeSystem codeSystem = myCodeSystemDao.findByCodeSystemUri(theSystemUri);
if (codeSystem == null) { if (codeSystem == null) {
codeSystem = myCodeSystemDao.findByResourcePid(theCodeSystemResourcePid.getIdAsLong()); codeSystem = myCodeSystemDao.findByResourcePid(theCodeSystemResourcePid.getIdAsLong());
if (codeSystem == null) { if (codeSystem == null) {
codeSystem = new TermCodeSystem(); codeSystem = new TermCodeSystem();
} }
codeSystem.setResource(theCodeSystemResourceTable);
} else { } else {
if (!ObjectUtil.equals(codeSystem.getResource().getId(), theCodeSystemResourceTable.getId())) { checkForCodeSystemVersionDuplicate(codeSystem, theSystemUri, theSystemVersionId, theCodeSystemResourceTable);
String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "cannotCreateDuplicateCodeSystemUrl", theSystemUri,
codeSystem.getResource().getIdDt().toUnqualifiedVersionless().getValue());
throw new UnprocessableEntityException(msg);
}
} }
codeSystem.setResource(theCodeSystemResourceTable);
codeSystem.setCodeSystemUri(theSystemUri); codeSystem.setCodeSystemUri(theSystemUri);
codeSystem.setName(theSystemName); codeSystem.setName(theSystemName);
codeSystem = myCodeSystemDao.save(codeSystem); codeSystem = myCodeSystemDao.save(codeSystem);
return codeSystem; return codeSystem;
} }
private void checkForCodeSystemVersionDuplicate(TermCodeSystem theCodeSystem, String theSystemUri, String theSystemVersionId, ResourceTable theCodeSystemResourceTable) {
TermCodeSystemVersion codeSystemVersionEntity;
String msg = null;
if (theSystemVersionId == null) {
// Check if a non-versioned TermCodeSystemVersion entity already exists for this TermCodeSystem.
codeSystemVersionEntity = myCodeSystemVersionDao.findByCodeSystemPidVersionIsNull(theCodeSystem.getPid());
if (codeSystemVersionEntity != null) {
msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "cannotCreateDuplicateCodeSystemUrl", theSystemUri, codeSystemVersionEntity.getResource().getIdDt().toUnqualifiedVersionless().getValue());
}
} else {
// Check if a TermCodeSystemVersion entity already exists for this TermCodeSystem and version.
codeSystemVersionEntity = myCodeSystemVersionDao.findByCodeSystemPidAndVersion(theCodeSystem.getPid(), theSystemVersionId);
if (codeSystemVersionEntity != null) {
msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "cannotCreateDuplicateCodeSystemUrlAndVersion", theSystemUri, theSystemVersionId, codeSystemVersionEntity.getResource().getIdDt().toUnqualifiedVersionless().getValue());
}
}
// Throw exception if the TermCodeSystemVersion is being duplicated.
if (codeSystemVersionEntity != null) {
if (!ObjectUtil.equals(codeSystemVersionEntity.getResource().getId(), theCodeSystemResourceTable.getId())) {
throw new UnprocessableEntityException(msg);
}
}
}
private void populateCodeSystemVersionProperties(TermCodeSystemVersion theCodeSystemVersion, CodeSystem theCodeSystemResource, ResourceTable theResourceTable) { private void populateCodeSystemVersionProperties(TermCodeSystemVersion theCodeSystemVersion, CodeSystem theCodeSystemResource, ResourceTable theResourceTable) {
theCodeSystemVersion.setResource(theResourceTable); theCodeSystemVersion.setResource(theResourceTable);
theCodeSystemVersion.setCodeSystemDisplayName(theCodeSystemResource.getName()); theCodeSystemVersion.setCodeSystemDisplayName(theCodeSystemResource.getName());

View File

@ -20,14 +20,15 @@ package ca.uhn.fhir.jpa.term;
* #L% * #L%
*/ */
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao; import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao; import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptDao; import ca.uhn.fhir.jpa.dao.data.ITermConceptDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptParentChildLinkDao; import ca.uhn.fhir.jpa.dao.data.ITermConceptParentChildLinkDao;
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.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.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.sched.HapiJob; import ca.uhn.fhir.jpa.model.sched.HapiJob;
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;
@ -67,13 +68,12 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
@Autowired @Autowired
protected PlatformTransactionManager myTransactionMgr; protected PlatformTransactionManager myTransactionMgr;
private boolean myProcessDeferred = true; private boolean myProcessDeferred = true;
private List<TermCodeSystem> myDefferedCodeSystemsDeletions = Collections.synchronizedList(new ArrayList<>()); final private List<TermCodeSystem> myDefferedCodeSystemsDeletions = Collections.synchronizedList(new ArrayList<>());
private List<TermConcept> myDeferredConcepts = Collections.synchronizedList(new ArrayList<>()); final private List<TermCodeSystemVersion> myDefferedCodeSystemVersionsDeletions = Collections.synchronizedList(new ArrayList<>());
private List<ValueSet> myDeferredValueSets = Collections.synchronizedList(new ArrayList<>()); final private List<TermConcept> myDeferredConcepts = Collections.synchronizedList(new ArrayList<>());
private List<ConceptMap> myDeferredConceptMaps = Collections.synchronizedList(new ArrayList<>()); final private List<ValueSet> myDeferredValueSets = Collections.synchronizedList(new ArrayList<>());
private List<TermConceptParentChildLink> myConceptLinksToSaveLater = Collections.synchronizedList(new ArrayList<>()); final private List<ConceptMap> myDeferredConceptMaps = Collections.synchronizedList(new ArrayList<>());
@Autowired final private List<TermConceptParentChildLink> myConceptLinksToSaveLater = Collections.synchronizedList(new ArrayList<>());
private DaoConfig myDaoConfig;
@Autowired @Autowired
private ITermConceptParentChildLinkDao myConceptParentChildLinkDao; private ITermConceptParentChildLinkDao myConceptParentChildLinkDao;
@Autowired @Autowired
@ -115,6 +115,21 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
myDefferedCodeSystemsDeletions.add(theCodeSystem); myDefferedCodeSystemsDeletions.add(theCodeSystem);
} }
@Override
@Transactional
public void deleteCodeSystemForResource(ResourceTable theCodeSystemToDelete) {
List<TermCodeSystemVersion> codeSystemVersionsToDelete = myCodeSystemVersionDao.findByCodeSystemResourcePid(theCodeSystemToDelete.getResourceId());
for (TermCodeSystemVersion codeSystemVersionToDelete : codeSystemVersionsToDelete){
if (codeSystemVersionToDelete != null) {
myDefferedCodeSystemVersionsDeletions.add(codeSystemVersionToDelete);
}
}
TermCodeSystem codeSystemToDelete = myCodeSystemDao.findByResourcePid(theCodeSystemToDelete.getResourceId());
if (codeSystemToDelete != null) {
deleteCodeSystem(codeSystemToDelete);
}
}
@Override @Override
public void saveAllDeferred() { public void saveAllDeferred() {
while (!isStorageQueueEmpty()) { while (!isStorageQueueEmpty()) {
@ -211,6 +226,7 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
myDeferredConceptMaps.clear(); myDeferredConceptMaps.clear();
myDeferredConcepts.clear(); myDeferredConcepts.clear();
myDefferedCodeSystemsDeletions.clear(); myDefferedCodeSystemsDeletions.clear();
myConceptLinksToSaveLater.clear();
} }
@Transactional(propagation = Propagation.NEVER) @Transactional(propagation = Propagation.NEVER)
@ -266,6 +282,12 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
} }
private void processDeferredCodeSystemDeletions() { private void processDeferredCodeSystemDeletions() {
for (TermCodeSystemVersion next : myDefferedCodeSystemVersionsDeletions) {
myCodeSystemStorageSvc.deleteCodeSystemVersion(next);
}
myDefferedCodeSystemVersionsDeletions.clear();
for (TermCodeSystem next : myDefferedCodeSystemsDeletions) { for (TermCodeSystem next : myDefferedCodeSystemsDeletions) {
myCodeSystemStorageSvc.deleteCodeSystem(next); myCodeSystemStorageSvc.deleteCodeSystem(next);
} }
@ -274,8 +296,7 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
@Override @Override
public boolean isStorageQueueEmpty() { public boolean isStorageQueueEmpty() {
boolean retVal = true; boolean retVal = !isProcessDeferredPaused();
retVal &= !isProcessDeferredPaused();
retVal &= !isDeferredConcepts(); retVal &= !isDeferredConcepts();
retVal &= !isConceptLinksToSaveLater(); retVal &= !isConceptLinksToSaveLater();
retVal &= !isDeferredValueSets(); retVal &= !isDeferredValueSets();
@ -300,7 +321,7 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
} }
private boolean isDeferredCodeSystemDeletions() { private boolean isDeferredCodeSystemDeletions() {
return !myDefferedCodeSystemsDeletions.isEmpty(); return !myDefferedCodeSystemsDeletions.isEmpty() || !myDefferedCodeSystemVersionsDeletions.isEmpty();
} }
private boolean isDeferredConcepts() { private boolean isDeferredConcepts() {
@ -345,11 +366,6 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
myTransactionMgr = theTxManager; myTransactionMgr = theTxManager;
} }
@VisibleForTesting
void setDaoConfigForUnitTest(DaoConfig theDaoConfig) {
myDaoConfig = theDaoConfig;
}
@VisibleForTesting @VisibleForTesting
void setCodeSystemStorageSvcForUnitTest(ITermCodeSystemStorageSvc theCodeSystemStorageSvc) { void setCodeSystemStorageSvcForUnitTest(ITermCodeSystemStorageSvc theCodeSystemStorageSvc) {
myCodeSystemStorageSvc = theCodeSystemStorageSvc; myCodeSystemStorageSvc = theCodeSystemStorageSvc;

View File

@ -378,6 +378,11 @@ public class TermLoaderSvcImpl implements ITermLoaderSvc {
try { try {
String loincCsString = IOUtils.toString(BaseTermReadSvcImpl.class.getResourceAsStream("/ca/uhn/fhir/jpa/term/loinc/loinc.xml"), Charsets.UTF_8); String loincCsString = IOUtils.toString(BaseTermReadSvcImpl.class.getResourceAsStream("/ca/uhn/fhir/jpa/term/loinc/loinc.xml"), Charsets.UTF_8);
loincCs = FhirContext.forR4().newXmlParser().parseResource(CodeSystem.class, loincCsString); loincCs = FhirContext.forR4().newXmlParser().parseResource(CodeSystem.class, loincCsString);
String codeSystemVersionId = theUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (codeSystemVersionId != null) {
loincCs.setVersion(codeSystemVersionId);
loincCs.setId(loincCs.getId() + "-" + codeSystemVersionId);
}
} catch (IOException e) { } catch (IOException e) {
throw new InternalErrorException("Failed to load loinc.xml", e); throw new InternalErrorException("Failed to load loinc.xml", e);
} }
@ -475,7 +480,7 @@ public class TermLoaderSvcImpl implements ITermLoaderSvc {
IOUtils.closeQuietly(theDescriptors); IOUtils.closeQuietly(theDescriptors);
valueSets.add(getValueSetLoincAll()); valueSets.add(getValueSetLoincAll(theUploadProperties));
for (Entry<String, TermConcept> next : code2concept.entrySet()) { for (Entry<String, TermConcept> next : code2concept.entrySet()) {
TermConcept nextConcept = next.getValue(); TermConcept nextConcept = next.getValue();
@ -494,12 +499,20 @@ public class TermLoaderSvcImpl implements ITermLoaderSvc {
return new UploadStatistics(conceptCount, target); return new UploadStatistics(conceptCount, target);
} }
private ValueSet getValueSetLoincAll() { private ValueSet getValueSetLoincAll(Properties theUploadProperties) {
ValueSet retVal = new ValueSet(); ValueSet retVal = new ValueSet();
retVal.setId("loinc-all"); String codeSystemVersionId = theUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
String valueSetId;
if (codeSystemVersionId != null) {
valueSetId = "loinc-all" + "-" + codeSystemVersionId;
} else {
valueSetId = "loinc-all";
codeSystemVersionId = "1.0.0";
}
retVal.setId(valueSetId);
retVal.setUrl("http://loinc.org/vs"); retVal.setUrl("http://loinc.org/vs");
retVal.setVersion("1.0.0"); retVal.setVersion(codeSystemVersionId);
retVal.setName("All LOINC codes"); retVal.setName("All LOINC codes");
retVal.setStatus(Enumerations.PublicationStatus.ACTIVE); retVal.setStatus(Enumerations.PublicationStatus.ACTIVE);
retVal.setDate(new Date()); retVal.setDate(new Date());

View File

@ -26,14 +26,14 @@ import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.util.VersionIndependentConcept; import ca.uhn.fhir.util.FhirVersionIndependentConcept;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
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.ValueSet; import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -47,23 +47,23 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
@Autowired @Autowired
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
private void addAllChildren(String theSystemString, org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent theCode, List<VersionIndependentConcept> theListToPopulate) { private void addAllChildren(String theSystemString, ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept theCode, List<FhirVersionIndependentConcept> theListToPopulate) {
if (isNotBlank(theCode.getCode())) { if (isNotBlank(theCode.getCode())) {
theListToPopulate.add(new VersionIndependentConcept(theSystemString, theCode.getCode())); theListToPopulate.add(new FhirVersionIndependentConcept(theSystemString, theCode.getCode()));
} }
for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent nextChild : theCode.getConcept()) { for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept nextChild : theCode.getConcept()) {
addAllChildren(theSystemString, nextChild, theListToPopulate); addAllChildren(theSystemString, nextChild, theListToPopulate);
} }
} }
private boolean addTreeIfItContainsCode(String theSystemString, org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent theNext, String theCode, List<VersionIndependentConcept> theListToPopulate) { private boolean addTreeIfItContainsCode(String theSystemString, ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept theNext, String theCode, List<FhirVersionIndependentConcept> theListToPopulate) {
boolean foundCodeInChild = false; boolean foundCodeInChild = false;
for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent nextChild : theNext.getConcept()) { for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept nextChild : theNext.getConcept()) {
foundCodeInChild |= addTreeIfItContainsCode(theSystemString, nextChild, theCode, theListToPopulate); foundCodeInChild |= addTreeIfItContainsCode(theSystemString, nextChild, theCode, theListToPopulate);
} }
if (theCode.equals(theNext.getCode()) || foundCodeInChild) { if (theCode.equals(theNext.getCode()) || foundCodeInChild) {
theListToPopulate.add(new VersionIndependentConcept(theSystemString, theNext.getCode())); theListToPopulate.add(new FhirVersionIndependentConcept(theSystemString, theNext.getCode()));
return true; return true;
} }
@ -95,30 +95,30 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
private void findCodesAbove(org.hl7.fhir.dstu2.model.ValueSet theSystem, String theSystemString, String theCode, List<VersionIndependentConcept> theListToPopulate) { private void findCodesAbove(ca.uhn.fhir.model.dstu2.resource.ValueSet theSystem, String theSystemString, String theCode, List<FhirVersionIndependentConcept> theListToPopulate) {
List<org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent> conceptList = theSystem.getCodeSystem().getConcept(); List<ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept> conceptList = theSystem.getCodeSystem().getConcept();
for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent next : conceptList) { for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept next : conceptList) {
addTreeIfItContainsCode(theSystemString, next, theCode, theListToPopulate); addTreeIfItContainsCode(theSystemString, next, theCode, theListToPopulate);
} }
} }
@Override @Override
public List<VersionIndependentConcept> findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) { public List<FhirVersionIndependentConcept> findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) {
ArrayList<VersionIndependentConcept> retVal = new ArrayList<>(); ArrayList<FhirVersionIndependentConcept> retVal = new ArrayList<>();
org.hl7.fhir.dstu2.model.ValueSet system = (org.hl7.fhir.dstu2.model.ValueSet) myValidationSupport.fetchCodeSystem(theSystem); ca.uhn.fhir.model.dstu2.resource.ValueSet system = (ca.uhn.fhir.model.dstu2.resource.ValueSet) myValidationSupport.fetchCodeSystem(theSystem);
if (system != null) { if (system != null) {
findCodesAbove(system, theSystem, theCode, retVal); findCodesAbove(system, theSystem, theCode, retVal);
} }
return retVal; return retVal;
} }
private void findCodesBelow(org.hl7.fhir.dstu2.model.ValueSet theSystem, String theSystemString, String theCode, List<VersionIndependentConcept> theListToPopulate) { private void findCodesBelow(ca.uhn.fhir.model.dstu2.resource.ValueSet theSystem, String theSystemString, String theCode, List<FhirVersionIndependentConcept> theListToPopulate) {
List<org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent> conceptList = theSystem.getCodeSystem().getConcept(); List<ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept> conceptList = theSystem.getCodeSystem().getConcept();
findCodesBelow(theSystemString, theCode, theListToPopulate, conceptList); findCodesBelow(theSystemString, theCode, theListToPopulate, conceptList);
} }
private void findCodesBelow(String theSystemString, String theCode, List<VersionIndependentConcept> theListToPopulate, List<org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent> conceptList) { private void findCodesBelow(String theSystemString, String theCode, List<FhirVersionIndependentConcept> theListToPopulate, List<ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept> conceptList) {
for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent next : conceptList) { for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept next : conceptList) {
if (theCode.equals(next.getCode())) { if (theCode.equals(next.getCode())) {
addAllChildren(theSystemString, next, theListToPopulate); addAllChildren(theSystemString, next, theListToPopulate);
} else { } else {
@ -128,9 +128,9 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
} }
@Override @Override
public List<VersionIndependentConcept> findCodesBelowUsingBuiltInSystems(String theSystem, String theCode) { public List<FhirVersionIndependentConcept> findCodesBelowUsingBuiltInSystems(String theSystem, String theCode) {
ArrayList<VersionIndependentConcept> retVal = new ArrayList<>(); ArrayList<FhirVersionIndependentConcept> retVal = new ArrayList<>();
org.hl7.fhir.dstu2.model.ValueSet system = (org.hl7.fhir.dstu2.model.ValueSet) myValidationSupport.fetchCodeSystem(theSystem); ca.uhn.fhir.model.dstu2.resource.ValueSet system = (ca.uhn.fhir.model.dstu2.resource.ValueSet) myValidationSupport.fetchCodeSystem(theSystem);
if (system != null) { if (system != null) {
findCodesBelow(system, theSystem, theCode, retVal); findCodesBelow(system, theSystem, theCode, retVal);
} }
@ -148,6 +148,17 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
return retVal; return retVal;
} }
@Nullable
@Override
protected Coding toCanonicalCoding(@Nullable IBaseCoding theCoding) {
Coding retVal = null;
if (theCoding != null) {
CodingDt coding = (CodingDt) theCoding;
retVal = new Coding(coding.getSystem(), coding.getCode(), coding.getDisplay());
}
return retVal;
}
@Nullable @Nullable
@Override @Override
protected CodeableConcept toCanonicalCodeableConcept(@Nullable IBaseDatatype theCodeableConcept) { protected CodeableConcept toCanonicalCodeableConcept(@Nullable IBaseDatatype theCodeableConcept) {
@ -157,7 +168,7 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl {
CodeableConceptDt cc = (CodeableConceptDt) theCodeableConcept; CodeableConceptDt cc = (CodeableConceptDt) theCodeableConcept;
outcome.setText(cc.getText()); outcome.setText(cc.getText());
for (CodingDt next : cc.getCoding()) { for (CodingDt next : cc.getCoding()) {
outcome.addCoding(toCanonicalCoding(next)); outcome.addCoding(toCanonicalCoding((IBaseDatatype)next));
} }
} }
return outcome; return outcome;

View File

@ -5,33 +5,25 @@ import ca.uhn.fhir.context.support.ConceptValidationOptions;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.context.support.ValidationSupportContext; import ca.uhn.fhir.context.support.ValidationSupportContext;
import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3; import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.ValidateUtil; import ca.uhn.fhir.util.ValidateUtil;
import ca.uhn.fhir.util.VersionIndependentConcept;
import org.hl7.fhir.convertors.VersionConvertor_30_40; import org.hl7.fhir.convertors.VersionConvertor_30_40;
import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.convertors.conv30_40.CodeSystem30_40; import org.hl7.fhir.convertors.conv30_40.CodeSystem30_40;
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.ValueSet; import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Optional;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet; import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet;
/* /*
@ -112,6 +104,12 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
return VersionConvertor_30_40.convertCoding((org.hl7.fhir.dstu3.model.Coding) theCoding); return VersionConvertor_30_40.convertCoding((org.hl7.fhir.dstu3.model.Coding) theCoding);
} }
@Override
@Nullable
protected org.hl7.fhir.r4.model.Coding toCanonicalCoding(IBaseCoding theCoding) {
return VersionConvertor_30_40.convertCoding((org.hl7.fhir.dstu3.model.Coding) theCoding);
}
@Override @Override
@Nullable @Nullable
protected org.hl7.fhir.r4.model.CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCoding) { protected org.hl7.fhir.r4.model.CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCoding) {

View File

@ -8,6 +8,7 @@ import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4; import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException; import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeSystem;
@ -107,6 +108,11 @@ public class TermReadSvcR4 extends BaseTermReadSvcImpl implements ITermReadSvcR4
return (Coding) theCoding; return (Coding) theCoding;
} }
@Override
protected Coding toCanonicalCoding(IBaseCoding theCoding) {
return (Coding) theCoding;
}
@Override @Override
protected CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCodeableConcept) { protected CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCodeableConcept) {
return (CodeableConcept) theCodeableConcept; return (CodeableConcept) theCodeableConcept;

View File

@ -12,6 +12,7 @@ import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
import ca.uhn.fhir.util.ValidateUtil; import ca.uhn.fhir.util.ValidateUtil;
import org.hl7.fhir.convertors.VersionConvertor_40_50; import org.hl7.fhir.convertors.VersionConvertor_40_50;
import org.hl7.fhir.convertors.conv40_50.CodeSystem40_50; import org.hl7.fhir.convertors.conv40_50.CodeSystem40_50;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
@ -111,6 +112,12 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
return VersionConvertor_40_50.convertCoding((Coding) theCoding); return VersionConvertor_40_50.convertCoding((Coding) theCoding);
} }
@Override
@Nullable
protected org.hl7.fhir.r4.model.Coding toCanonicalCoding(IBaseCoding theCoding) {
return VersionConvertor_40_50.convertCoding((Coding) theCoding);
}
@Override @Override
@Nullable @Nullable
protected org.hl7.fhir.r4.model.CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCoding) { protected org.hl7.fhir.r4.model.CodeableConcept toCanonicalCodeableConcept(IBaseDatatype theCoding) {
@ -135,4 +142,10 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
org.hl7.fhir.r4.model.ValueSet valueSetR4 = toCanonicalValueSet(valueSet); org.hl7.fhir.r4.model.ValueSet valueSetR4 = toCanonicalValueSet(valueSet);
return super.isValueSetPreExpandedForCodeValidation(valueSetR4); return super.isValueSetPreExpandedForCodeValidation(valueSetR4);
} }
@Override
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
return super.lookupCode(theSystem, theCode);
}
} }

View File

@ -42,13 +42,12 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValueSetConceptAccumulator.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValueSetConceptAccumulator.class);
private TermValueSet myTermValueSet; private TermValueSet myTermValueSet;
private ITermValueSetDao myValueSetDao; final private ITermValueSetDao myValueSetDao;
private ITermValueSetConceptDao myValueSetConceptDao; final private ITermValueSetConceptDao myValueSetConceptDao;
private ITermValueSetConceptDesignationDao myValueSetConceptDesignationDao; final private ITermValueSetConceptDesignationDao myValueSetConceptDesignationDao;
private int myConceptsSaved; private int myConceptsSaved;
private int myDesignationsSaved; private int myDesignationsSaved;
private int myConceptsExcluded; private int myConceptsExcluded;
private int myCount;
public ValueSetConceptAccumulator(@Nonnull TermValueSet theTermValueSet, @Nonnull ITermValueSetDao theValueSetDao, @Nonnull ITermValueSetConceptDao theValueSetConceptDao, @Nonnull ITermValueSetConceptDesignationDao theValueSetConceptDesignationDao) { public ValueSetConceptAccumulator(@Nonnull TermValueSet theTermValueSet, @Nonnull ITermValueSetDao theValueSetDao, @Nonnull ITermValueSetConceptDao theValueSetConceptDao, @Nonnull ITermValueSetConceptDesignationDao theValueSetConceptDesignationDao) {
myTermValueSet = theTermValueSet; myTermValueSet = theTermValueSet;

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
import ca.uhn.fhir.model.api.annotation.Block; import ca.uhn.fhir.model.api.annotation.Block;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.HapiExtensions;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.ValueSet; import org.hl7.fhir.r4.model.ValueSet;
@ -67,7 +68,7 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
public void includeConcept(String theSystem, String theCode, String theDisplay) { public void includeConcept(String theSystem, String theCode, String theDisplay) {
incrementConceptsCount(); incrementConceptsCount();
ValueSet.ValueSetExpansionContainsComponent contains = this.addContains(); ValueSet.ValueSetExpansionContainsComponent contains = this.addContains();
contains.setSystem(theSystem); setSystemAndVersion(theSystem, contains);
contains.setCode(theCode); contains.setCode(theCode);
contains.setDisplay(theDisplay); contains.setDisplay(theDisplay);
} }
@ -76,7 +77,7 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection<TermConceptDesignation> theDesignations) { public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection<TermConceptDesignation> theDesignations) {
incrementConceptsCount(); incrementConceptsCount();
ValueSet.ValueSetExpansionContainsComponent contains = this.addContains(); ValueSet.ValueSetExpansionContainsComponent contains = this.addContains();
contains.setSystem(theSystem); setSystemAndVersion(theSystem, contains);
contains.setCode(theCode); contains.setCode(theCode);
contains.setDisplay(theDisplay); contains.setDisplay(theDisplay);
if (theDesignations != null) { if (theDesignations != null) {
@ -95,11 +96,26 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
@Override @Override
public void excludeConcept(String theSystem, String theCode) { public void excludeConcept(String theSystem, String theCode) {
this String excludeSystem;
.getContains() String excludeSystemVersion;
.removeIf(t -> int versionSeparator = theSystem.indexOf("|");
theSystem.equals(t.getSystem()) && if(versionSeparator > -1) {
theCode.equals(t.getCode())); excludeSystemVersion = theSystem.substring(versionSeparator + 1);
excludeSystem = theSystem.substring(0, versionSeparator);
} else {
excludeSystem = theSystem;
excludeSystemVersion = null;
}
if (excludeSystemVersion != null) {
this.getContains().removeIf(t ->
excludeSystem.equals(t.getSystem()) &&
theCode.equals(t.getCode()) &&
excludeSystemVersion.equals(t.getVersion()));
} else {
this.getContains().removeIf(t ->
theSystem.equals(t.getSystem()) &&
theCode.equals(t.getCode()));
}
} }
private void incrementConceptsCount() { private void incrementConceptsCount() {
@ -108,4 +124,17 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
throw new ExpansionTooCostlyException(msg); throw new ExpansionTooCostlyException(msg);
} }
} }
private void setSystemAndVersion(String theSystemAndVersion, ValueSet.ValueSetExpansionContainsComponent myComponent) {
if (StringUtils.isNotEmpty((theSystemAndVersion))) {
int versionSeparator = theSystemAndVersion.lastIndexOf('|');
if (versionSeparator != -1) {
myComponent.setVersion(theSystemAndVersion.substring(versionSeparator + 1));
myComponent.setSystem(theSystemAndVersion.substring(0,versionSeparator));
} else {
myComponent.setSystem(theSystemAndVersion);
}
}
}
} }

View File

@ -41,6 +41,8 @@ public interface ITermCodeSystemStorageSvc {
void deleteCodeSystem(TermCodeSystem theCodeSystem); void deleteCodeSystem(TermCodeSystem theCodeSystem);
void deleteCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion);
void storeNewCodeSystemVersion(ResourcePersistentId 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);
/** /**

View File

@ -21,8 +21,10 @@ package ca.uhn.fhir.jpa.term.api;
*/ */
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.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.entity.ResourceTable;
import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.ValueSet; import org.hl7.fhir.r4.model.ValueSet;
@ -54,6 +56,8 @@ public interface ITermDeferredStorageSvc {
void deleteCodeSystem(TermCodeSystem theCodeSystem); void deleteCodeSystem(TermCodeSystem theCodeSystem);
void deleteCodeSystemForResource(ResourceTable theCodeSystemResourceToDelete);
/** /**
* This is mostly here for unit tests - Saves any and all deferred concepts and links * This is mostly here for unit tests - Saves any and all deferred concepts and links
*/ */

View File

@ -10,9 +10,7 @@ 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.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.IValueSetConceptAccumulator; import ca.uhn.fhir.jpa.term.IValueSetConceptAccumulator;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.util.FhirVersionIndependentConcept;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.util.VersionIndependentConcept;
import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -21,7 +19,6 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.ConceptMap; import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.ValueSet; import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
@ -71,21 +68,21 @@ public interface ITermReadSvc extends IValidationSupport {
void expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator); void expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator);
List<VersionIndependentConcept> expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet); List<FhirVersionIndependentConcept> expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet);
Optional<TermConcept> findCode(String theCodeSystem, String theCode); Optional<TermConcept> findCode(String theCodeSystem, String theCode);
Set<TermConcept> findCodesAbove(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode); Set<TermConcept> findCodesAbove(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode);
List<VersionIndependentConcept> findCodesAbove(String theSystem, String theCode); List<FhirVersionIndependentConcept> findCodesAbove(String theSystem, String theCode);
List<VersionIndependentConcept> findCodesAboveUsingBuiltInSystems(String theSystem, String theCode); List<FhirVersionIndependentConcept> findCodesAboveUsingBuiltInSystems(String theSystem, String theCode);
Set<TermConcept> findCodesBelow(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode); Set<TermConcept> findCodesBelow(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode);
List<VersionIndependentConcept> findCodesBelow(String theSystem, String theCode); List<FhirVersionIndependentConcept> findCodesBelow(String theSystem, String theCode);
List<VersionIndependentConcept> findCodesBelowUsingBuiltInSystems(String theSystem, String theCode); List<FhirVersionIndependentConcept> findCodesBelowUsingBuiltInSystems(String theSystem, String theCode);
CodeSystem fetchCanonicalCodeSystemFromCompleteContext(String theSystem); CodeSystem fetchCanonicalCodeSystemFromCompleteContext(String theSystem);
@ -122,4 +119,9 @@ public interface ITermReadSvc extends IValidationSupport {
*/ */
boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet); boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet);
/**
* Version independent
*/
CodeValidationResult codeSystemValidateCode(IIdType theCodeSystemId, String theValueSetUrl, String theVersion, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
} }

View File

@ -52,7 +52,7 @@ public abstract class BaseLoincHandler implements IRecordHandler {
private final List<ValueSet> myValueSets; private final List<ValueSet> myValueSets;
private final Map<String, ValueSet> myIdToValueSet = new HashMap<>(); private final Map<String, ValueSet> myIdToValueSet = new HashMap<>();
private final Map<String, TermConcept> myCode2Concept; private final Map<String, TermConcept> myCode2Concept;
private final Properties myUploadProperties; protected final Properties myUploadProperties;
BaseLoincHandler(Map<String, TermConcept> theCode2Concept, List<ValueSet> theValueSets, List<ConceptMap> theConceptMaps, Properties theUploadProperties) { BaseLoincHandler(Map<String, TermConcept> theCode2Concept, List<ValueSet> theValueSets, List<ConceptMap> theConceptMaps, Properties theUploadProperties) {
myValueSets = theValueSets; myValueSets = theValueSets;
@ -115,7 +115,7 @@ public abstract class BaseLoincHandler implements IRecordHandler {
conceptMap.setId(theMapping.getConceptMapId()); conceptMap.setId(theMapping.getConceptMapId());
conceptMap.setUrl(theMapping.getConceptMapUri()); conceptMap.setUrl(theMapping.getConceptMapUri());
conceptMap.setName(theMapping.getConceptMapName()); conceptMap.setName(theMapping.getConceptMapName());
conceptMap.setVersion(myUploadProperties.getProperty(LOINC_CONCEPTMAP_VERSION.getCode())); conceptMap.setVersion(theMapping.getConceptMapVersion());
conceptMap.setPublisher(REGENSTRIEF_INSTITUTE_INC); conceptMap.setPublisher(REGENSTRIEF_INSTITUTE_INC);
conceptMap.addContact() conceptMap.addContact()
.setName(REGENSTRIEF_INSTITUTE_INC) .setName(REGENSTRIEF_INSTITUTE_INC)
@ -191,6 +191,8 @@ public abstract class BaseLoincHandler implements IRecordHandler {
String version = null; String version = null;
if (isNotBlank(theVersionPropertyName)) { if (isNotBlank(theVersionPropertyName)) {
version = myUploadProperties.getProperty(theVersionPropertyName); version = myUploadProperties.getProperty(theVersionPropertyName);
} else {
version = myUploadProperties.getProperty(LOINC_CONCEPTMAP_VERSION.getCode());
} }
ValueSet vs; ValueSet vs;
@ -226,6 +228,7 @@ public abstract class BaseLoincHandler implements IRecordHandler {
private String myCopyright; private String myCopyright;
private String myConceptMapId; private String myConceptMapId;
private String myConceptMapUri; private String myConceptMapUri;
private String myConceptMapVersion;
private String myConceptMapName; private String myConceptMapName;
private String mySourceCodeSystem; private String mySourceCodeSystem;
private String mySourceCode; private String mySourceCode;
@ -263,6 +266,15 @@ public abstract class BaseLoincHandler implements IRecordHandler {
return this; return this;
} }
String getConceptMapVersion() {
return myConceptMapVersion;
}
ConceptMapping setConceptMapVersion(String theConceptMapVersion) {
myConceptMapVersion = theConceptMapVersion;
return this;
}
String getCopyright() { String getCopyright() {
return myCopyright; return myCopyright;
} }

View File

@ -31,6 +31,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class BaseLoincTop2000LabResultsHandler extends BaseLoincHandler implements IRecordHandler { public class BaseLoincTop2000LabResultsHandler extends BaseLoincHandler implements IRecordHandler {
@ -41,7 +42,12 @@ public class BaseLoincTop2000LabResultsHandler extends BaseLoincHandler implemen
public BaseLoincTop2000LabResultsHandler(Map<String, TermConcept> theCode2concept, List<ValueSet> theValueSets, String theValueSetId, String theValueSetUri, String theValueSetName, List<ConceptMap> theConceptMaps, Properties theUploadProperties) { public BaseLoincTop2000LabResultsHandler(Map<String, TermConcept> theCode2concept, List<ValueSet> theValueSets, String theValueSetId, String theValueSetUri, String theValueSetName, List<ConceptMap> theConceptMaps, Properties theUploadProperties) {
super(theCode2concept, theValueSets, theConceptMaps, theUploadProperties); super(theCode2concept, theValueSets, theConceptMaps, theUploadProperties);
myValueSetId = theValueSetId; String versionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (versionId != null) {
myValueSetId = theValueSetId + "-" + versionId;
} else {
myValueSetId = theValueSetId;
}
myValueSetUri = theValueSetUri; myValueSetUri = theValueSetUri;
myValueSetName = theValueSetName; myValueSetName = theValueSetName;
} }

View File

@ -74,7 +74,14 @@ public class LoincAnswerListHandler extends BaseLoincHandler {
} }
// Answer list ValueSet // Answer list ValueSet
ValueSet vs = getValueSet(answerListId, "http://loinc.org/vs/" + answerListId, answerListName, LOINC_ANSWERLIST_VERSION.getCode()); String valueSetId;
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (codeSystemVersionId != null) {
valueSetId = answerListId + "-" + codeSystemVersionId;
} else {
valueSetId = answerListId;
}
ValueSet vs = getValueSet(valueSetId, "http://loinc.org/vs/" + answerListId, answerListName, LOINC_ANSWERLIST_VERSION.getCode());
if (vs.getIdentifier().isEmpty()) { if (vs.getIdentifier().isEmpty()) {
vs.addIdentifier() vs.addIdentifier()
.setSystem("urn:ietf:rfc:3986") .setSystem("urn:ietf:rfc:3986")

View File

@ -33,6 +33,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincDocumentOntologyHandler extends BaseLoincHandler implements IRecordHandler { public class LoincDocumentOntologyHandler extends BaseLoincHandler implements IRecordHandler {
@ -57,7 +58,14 @@ public class LoincDocumentOntologyHandler extends BaseLoincHandler implements IR
String partName = trim(theRecord.get("PartName")); String partName = trim(theRecord.get("PartName"));
// RSNA Codes VS // RSNA Codes VS
ValueSet vs = getValueSet(DOCUMENT_ONTOLOGY_CODES_VS_ID, DOCUMENT_ONTOLOGY_CODES_VS_URI, DOCUMENT_ONTOLOGY_CODES_VS_NAME, null); String valueSetId;
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (codeSystemVersionId != null) {
valueSetId = DOCUMENT_ONTOLOGY_CODES_VS_ID + "-" + codeSystemVersionId;
} else {
valueSetId = DOCUMENT_ONTOLOGY_CODES_VS_ID;
}
ValueSet vs = getValueSet(valueSetId, DOCUMENT_ONTOLOGY_CODES_VS_URI, DOCUMENT_ONTOLOGY_CODES_VS_NAME, null);
addCodeAsIncludeToValueSet(vs, ITermLoaderSvc.LOINC_URI, loincNumber, null); addCodeAsIncludeToValueSet(vs, ITermLoaderSvc.LOINC_URI, loincNumber, null);
// Part Properties // Part Properties

View File

@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincGroupFileHandler extends BaseLoincHandler implements IRecordHandler { public class LoincGroupFileHandler extends BaseLoincHandler implements IRecordHandler {
@ -47,7 +48,18 @@ public class LoincGroupFileHandler extends BaseLoincHandler implements IRecordHa
String groupId = trim(theRecord.get("GroupId")); String groupId = trim(theRecord.get("GroupId"));
String groupName = trim(theRecord.get("Group")); String groupName = trim(theRecord.get("Group"));
ValueSet parentValueSet = getValueSet(parentGroupId, VS_URI_PREFIX + parentGroupId, null, null); String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
String parentGroupValueSetId;
String groupValueSetId;
if (codeSystemVersionId != null) {
parentGroupValueSetId = parentGroupId + "-" + codeSystemVersionId;
groupValueSetId = groupId + "-" + codeSystemVersionId;
} else {
parentGroupValueSetId = parentGroupId;
groupValueSetId = groupId;
}
ValueSet parentValueSet = getValueSet(parentGroupValueSetId, VS_URI_PREFIX + parentGroupId, null, null);
parentValueSet parentValueSet
.getCompose() .getCompose()
.getIncludeFirstRep() .getIncludeFirstRep()
@ -55,7 +67,7 @@ public class LoincGroupFileHandler extends BaseLoincHandler implements IRecordHa
// Create group to set its name (terms are added in a different // Create group to set its name (terms are added in a different
// handler) // handler)
getValueSet(groupId, VS_URI_PREFIX + groupId, groupName, null); getValueSet(groupValueSetId, VS_URI_PREFIX + groupId, groupName, null);
} }

View File

@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONCEPTMAP_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincGroupTermsFileHandler extends BaseLoincHandler implements IRecordHandler { public class LoincGroupTermsFileHandler extends BaseLoincHandler implements IRecordHandler {
@ -43,9 +45,16 @@ public class LoincGroupTermsFileHandler extends BaseLoincHandler implements IRec
public void accept(CSVRecord theRecord) { public void accept(CSVRecord theRecord) {
//"Category","GroupId","Archetype","LoincNumber","LongCommonName" //"Category","GroupId","Archetype","LoincNumber","LongCommonName"
String groupId = trim(theRecord.get("GroupId")); String groupId = trim(theRecord.get("GroupId"));
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
String valueSetId;
if (codeSystemVersionId != null) {
valueSetId = groupId + "-" + codeSystemVersionId;
} else {
valueSetId = groupId;
}
String loincNumber = trim(theRecord.get("LoincNumber")); String loincNumber = trim(theRecord.get("LoincNumber"));
ValueSet valueSet = getValueSet(groupId, LoincGroupFileHandler.VS_URI_PREFIX + groupId, null, null); ValueSet valueSet = getValueSet(valueSetId, LoincGroupFileHandler.VS_URI_PREFIX + groupId, null, null);
addCodeAsIncludeToValueSet(valueSet, ITermLoaderSvc.LOINC_URI, loincNumber, null); addCodeAsIncludeToValueSet(valueSet, ITermLoaderSvc.LOINC_URI, loincNumber, null);
} }

View File

@ -32,6 +32,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONCEPTMAP_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincIeeeMedicalDeviceCodeHandler extends BaseLoincHandler implements IRecordHandler { public class LoincIeeeMedicalDeviceCodeHandler extends BaseLoincHandler implements IRecordHandler {
@ -51,6 +53,7 @@ public class LoincIeeeMedicalDeviceCodeHandler extends BaseLoincHandler implemen
@Override @Override
public void accept(CSVRecord theRecord) { public void accept(CSVRecord theRecord) {
String loincIeeeCmVersion = myUploadProperties.getProperty(LOINC_CONCEPTMAP_VERSION.getCode());
String loincNumber = trim(theRecord.get("LOINC_NUM")); String loincNumber = trim(theRecord.get("LOINC_NUM"));
String longCommonName = trim(theRecord.get("LOINC_LONG_COMMON_NAME")); String longCommonName = trim(theRecord.get("LOINC_LONG_COMMON_NAME"));
String ieeeCode = trim(theRecord.get("IEEE_CF_CODE10")); String ieeeCode = trim(theRecord.get("IEEE_CF_CODE10"));
@ -59,10 +62,18 @@ public class LoincIeeeMedicalDeviceCodeHandler extends BaseLoincHandler implemen
// LOINC Part -> IEEE 11073:10101 Mappings // LOINC Part -> IEEE 11073:10101 Mappings
String sourceCodeSystemUri = ITermLoaderSvc.LOINC_URI; String sourceCodeSystemUri = ITermLoaderSvc.LOINC_URI;
String targetCodeSystemUri = ITermLoaderSvc.IEEE_11073_10101_URI; String targetCodeSystemUri = ITermLoaderSvc.IEEE_11073_10101_URI;
String conceptMapId;
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (codeSystemVersionId != null) {
conceptMapId = LOINC_IEEE_CM_ID + "-" + codeSystemVersionId;
} else {
conceptMapId = LOINC_IEEE_CM_ID;
}
addConceptMapEntry( addConceptMapEntry(
new ConceptMapping() new ConceptMapping()
.setConceptMapId(LOINC_IEEE_CM_ID) .setConceptMapId(conceptMapId)
.setConceptMapUri(LOINC_IEEE_CM_URI) .setConceptMapUri(LOINC_IEEE_CM_URI)
.setConceptMapVersion(loincIeeeCmVersion)
.setConceptMapName(LOINC_IEEE_CM_NAME) .setConceptMapName(LOINC_IEEE_CM_NAME)
.setSourceCodeSystem(sourceCodeSystemUri) .setSourceCodeSystem(sourceCodeSystemUri)
.setSourceCode(loincNumber) .setSourceCode(loincNumber)
@ -71,7 +82,7 @@ public class LoincIeeeMedicalDeviceCodeHandler extends BaseLoincHandler implemen
.setTargetCode(ieeeCode) .setTargetCode(ieeeCode)
.setTargetDisplay(ieeeDisplayName) .setTargetDisplay(ieeeDisplayName)
.setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL), .setEquivalence(Enumerations.ConceptMapEquivalence.EQUAL),
CM_COPYRIGHT); CM_COPYRIGHT);
} }

View File

@ -31,11 +31,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincImagingDocumentCodeHandler extends BaseLoincHandler implements IRecordHandler { public class LoincImagingDocumentCodeHandler extends BaseLoincHandler implements IRecordHandler {
public static final String VS_ID = "loinc-imaging-document-codes"; public static final String VS_ID_BASE = "loinc-imaging-document-codes";
public static final String VS_URI = "http://loinc.org/vs/loinc-imaging-document-codes"; public static final String VS_URI = "http://loinc.org/vs/loinc-imaging-document-codes";
public static final String VS_NAME = "LOINC Imaging Document Codes"; public static final String VS_NAME = "LOINC Imaging Document Codes";
@ -48,7 +49,15 @@ public class LoincImagingDocumentCodeHandler extends BaseLoincHandler implements
String loincNumber = trim(theRecord.get("LOINC_NUM")); String loincNumber = trim(theRecord.get("LOINC_NUM"));
String displayName = trim(theRecord.get("LONG_COMMON_NAME")); String displayName = trim(theRecord.get("LONG_COMMON_NAME"));
ValueSet valueSet = getValueSet(VS_ID, VS_URI, VS_NAME,null); String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
String valueSetId;
if (codeSystemVersionId != null) {
valueSetId = VS_ID_BASE + "-" + codeSystemVersionId;
} else {
valueSetId = VS_ID_BASE;
}
ValueSet valueSet = getValueSet(valueSetId, VS_URI, VS_NAME,null);
addCodeAsIncludeToValueSet(valueSet, ITermLoaderSvc.LOINC_URI, loincNumber, displayName); addCodeAsIncludeToValueSet(valueSet, ITermLoaderSvc.LOINC_URI, loincNumber, displayName);
} }

View File

@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincParentGroupFileHandler extends BaseLoincHandler implements IRecordHandler { public class LoincParentGroupFileHandler extends BaseLoincHandler implements IRecordHandler {
@ -42,9 +43,16 @@ public class LoincParentGroupFileHandler extends BaseLoincHandler implements IRe
public void accept(CSVRecord theRecord) { public void accept(CSVRecord theRecord) {
// "ParentGroupId","ParentGroup","Status" // "ParentGroupId","ParentGroup","Status"
String parentGroupId = trim(theRecord.get("ParentGroupId")); String parentGroupId = trim(theRecord.get("ParentGroupId"));
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
String valueSetId;
if (codeSystemVersionId != null) {
valueSetId = parentGroupId + "-" + codeSystemVersionId;
} else {
valueSetId = parentGroupId;
}
String parentGroupName = trim(theRecord.get("ParentGroup")); String parentGroupName = trim(theRecord.get("ParentGroup"));
getValueSet(parentGroupId, LoincGroupFileHandler.VS_URI_PREFIX + parentGroupId, parentGroupName, null); getValueSet(valueSetId, LoincGroupFileHandler.VS_URI_PREFIX + parentGroupId, parentGroupName, null);
} }

View File

@ -33,6 +33,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONCEPTMAP_VERSION;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
@ -75,6 +77,9 @@ public class LoincPartRelatedCodeMappingHandler extends BaseLoincHandler impleme
String extCodeSystemVersion = trim(theRecord.get("ExtCodeSystemVersion")); String extCodeSystemVersion = trim(theRecord.get("ExtCodeSystemVersion"));
String extCodeSystemCopyrightNotice = trim(theRecord.get("ExtCodeSystemCopyrightNotice")); String extCodeSystemCopyrightNotice = trim(theRecord.get("ExtCodeSystemCopyrightNotice"));
// ConceptMap version from properties files
String loincPartMapVersion = myUploadProperties.getProperty(LOINC_CONCEPTMAP_VERSION.getCode());
Enumerations.ConceptMapEquivalence equivalence; Enumerations.ConceptMapEquivalence equivalence;
switch (trim(defaultString(mapType))) { switch (trim(defaultString(mapType))) {
case "": case "":
@ -125,11 +130,19 @@ public class LoincPartRelatedCodeMappingHandler extends BaseLoincHandler impleme
loincPartMapName = "Unknown Mapping"; loincPartMapName = "Unknown Mapping";
break; break;
} }
String conceptMapId;
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (codeSystemVersionId != null) {
conceptMapId = loincPartMapId + "-" + codeSystemVersionId;
} else {
conceptMapId = loincPartMapId;
}
addConceptMapEntry( addConceptMapEntry(
new ConceptMapping() new ConceptMapping()
.setConceptMapId(loincPartMapId) .setConceptMapId(conceptMapId)
.setConceptMapUri(loincPartMapUri) .setConceptMapUri(loincPartMapUri)
.setConceptMapVersion(loincPartMapVersion)
.setConceptMapName(loincPartMapName) .setConceptMapName(loincPartMapName)
.setSourceCodeSystem(ITermLoaderSvc.LOINC_URI) .setSourceCodeSystem(ITermLoaderSvc.LOINC_URI)
.setSourceCode(partNumber) .setSourceCode(partNumber)

View File

@ -31,6 +31,8 @@ import org.hl7.fhir.r4.model.ValueSet;
import java.util.*; import java.util.*;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONCEPTMAP_VERSION;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
@ -80,6 +82,9 @@ public class LoincRsnaPlaybookHandler extends BaseLoincHandler implements IRecor
String rpid = trim(theRecord.get("RPID")); String rpid = trim(theRecord.get("RPID"));
String longName = trim(theRecord.get("LongName")); String longName = trim(theRecord.get("LongName"));
// ConceptMap version from properties files
String loincRsnaCmVersion = myUploadProperties.getProperty(LOINC_CONCEPTMAP_VERSION.getCode());
// RSNA Codes VS // RSNA Codes VS
ValueSet vs; ValueSet vs;
if (!myIdToValueSet.containsKey(RSNA_CODES_VS_ID)) { if (!myIdToValueSet.containsKey(RSNA_CODES_VS_ID)) {
@ -170,12 +175,24 @@ public class LoincRsnaPlaybookHandler extends BaseLoincHandler implements IRecor
code.addPropertyCoding(loincCodePropName, ITermLoaderSvc.LOINC_URI, partNumber, partName); code.addPropertyCoding(loincCodePropName, ITermLoaderSvc.LOINC_URI, partNumber, partName);
} }
String partConceptMapId;
String termConceptMapId;
String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
if (codeSystemVersionId != null) {
partConceptMapId = LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_ID + "-" + codeSystemVersionId;
termConceptMapId = LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_ID + "-" + codeSystemVersionId;
} else {
partConceptMapId = LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_ID;
termConceptMapId = LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_ID;
}
// LOINC Part -> Radlex RID code mappings // LOINC Part -> Radlex RID code mappings
if (isNotBlank(rid)) { if (isNotBlank(rid)) {
addConceptMapEntry( addConceptMapEntry(
new ConceptMapping() new ConceptMapping()
.setConceptMapId(LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_ID) .setConceptMapId(partConceptMapId)
.setConceptMapUri(LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_URI) .setConceptMapUri(LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_URI)
.setConceptMapVersion(loincRsnaCmVersion)
.setConceptMapName(LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_NAME) .setConceptMapName(LoincPartRelatedCodeMappingHandler.LOINC_PART_TO_RID_PART_MAP_NAME)
.setSourceCodeSystem(ITermLoaderSvc.LOINC_URI) .setSourceCodeSystem(ITermLoaderSvc.LOINC_URI)
.setSourceCode(partNumber) .setSourceCode(partNumber)
@ -191,8 +208,9 @@ public class LoincRsnaPlaybookHandler extends BaseLoincHandler implements IRecor
if (isNotBlank(rpid)) { if (isNotBlank(rpid)) {
addConceptMapEntry( addConceptMapEntry(
new ConceptMapping() new ConceptMapping()
.setConceptMapId(LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_ID) .setConceptMapId(termConceptMapId)
.setConceptMapUri(LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_URI) .setConceptMapUri(LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_URI)
.setConceptMapVersion(loincRsnaCmVersion)
.setConceptMapName(LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_NAME) .setConceptMapName(LoincPartRelatedCodeMappingHandler.LOINC_TERM_TO_RPID_PART_MAP_NAME)
.setSourceCodeSystem(ITermLoaderSvc.LOINC_URI) .setSourceCodeSystem(ITermLoaderSvc.LOINC_URI)
.setSourceCode(loincNumber) .setSourceCode(loincNumber)

View File

@ -29,11 +29,12 @@ import org.hl7.fhir.r4.model.ValueSet;
import java.util.*; import java.util.*;
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;
public class LoincUniversalOrderSetHandler extends BaseLoincHandler implements IRecordHandler { public class LoincUniversalOrderSetHandler extends BaseLoincHandler implements IRecordHandler {
public static final String VS_ID = "loinc-universal-order-set"; public static final String VS_ID_BASE = "loinc-universal-order-set";
public static final String VS_URI = "http://loinc.org/vs/loinc-universal-order-set"; public static final String VS_URI = "http://loinc.org/vs/loinc-universal-order-set";
public static final String VS_NAME = "LOINC Universal Order Set"; public static final String VS_NAME = "LOINC Universal Order Set";
@ -47,7 +48,15 @@ public class LoincUniversalOrderSetHandler extends BaseLoincHandler implements I
String displayName = trim(theRecord.get("LONG_COMMON_NAME")); String displayName = trim(theRecord.get("LONG_COMMON_NAME"));
String orderObs = trim(theRecord.get("ORDER_OBS")); String orderObs = trim(theRecord.get("ORDER_OBS"));
ValueSet valueSet = getValueSet(VS_ID, VS_URI, VS_NAME, null); String codeSystemVersionId = myUploadProperties.getProperty(LOINC_CODESYSTEM_VERSION.getCode());
String valueSetId;
if (codeSystemVersionId != null) {
valueSetId = VS_ID_BASE + "-" + codeSystemVersionId;
} else {
valueSetId = VS_ID_BASE;
}
ValueSet valueSet = getValueSet(valueSetId, VS_URI, VS_NAME, null);
addCodeAsIncludeToValueSet(valueSet, ITermLoaderSvc.LOINC_URI, loincNumber, displayName); addCodeAsIncludeToValueSet(valueSet, ITermLoaderSvc.LOINC_URI, loincNumber, displayName);
} }

View File

@ -96,6 +96,9 @@ public enum LoincUploadPropertiesEnum {
/* /*
* OPTIONAL * OPTIONAL
*/ */
// This is the version identifier for the LOINC code system
LOINC_CODESYSTEM_VERSION("loinc.codesystem.version"),
// This is the version identifier for the answer list file // This is the version identifier for the answer list file
LOINC_ANSWERLIST_VERSION("loinc.answerlist.version"), LOINC_ANSWERLIST_VERSION("loinc.answerlist.version"),

View File

@ -61,6 +61,10 @@ loinc.universal.lab.order.valueset.file=AccessoryFiles/LoincUniversalLabOrdersVa
### OPTIONAL ### ### OPTIONAL ###
################ ################
# This is the version identifier for the LOINC code system
## Key may be omitted if only a single version of LOINC is being kept.
#loinc.codesystem.version=2.68
# This is the version identifier for the answer list file # This is the version identifier for the answer list file
## Key may be omitted ## Key may be omitted
loinc.answerlist.version=Beta.1 loinc.answerlist.version=Beta.1

View File

@ -40,7 +40,7 @@ import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
import ca.uhn.fhir.util.BundleUtil; import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.VersionIndependentConcept; import ca.uhn.fhir.util.FhirVersionIndependentConcept;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Session; import org.hibernate.Session;
@ -507,9 +507,9 @@ public abstract class BaseJpaTest extends BaseTest {
return retVal; return retVal;
} }
protected static Set<String> toCodes(List<VersionIndependentConcept> theConcepts) { protected static Set<String> toCodes(List<FhirVersionIndependentConcept> theConcepts) {
HashSet<String> retVal = new HashSet<>(); HashSet<String> retVal = new HashSet<>();
for (VersionIndependentConcept next : theConcepts) { for (FhirVersionIndependentConcept next : theConcepts) {
retVal.add(next.getCode()); retVal.add(next.getCode());
} }
return retVal; return retVal;

View File

@ -1,6 +1,7 @@
package ca.uhn.fhir.jpa.dao.dstu2; package ca.uhn.fhir.jpa.dao.dstu2;
import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.model.dstu2.resource.ValueSet;
@ -21,7 +22,10 @@ import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder; import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test { public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
@ -228,5 +232,15 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test {
assertThat(resp, not(containsString("<code value=\"8450-9\"/>"))); assertThat(resp, not(containsString("<code value=\"8450-9\"/>")));
} }
@Test
public void testValidateCodeForCodeSystemOperationNotSupported() {
try {
((IFhirResourceDaoCodeSystem)myValueSetDao).validateCode(null, null, null, null, null, null, null, null);
fail();
} catch (UnsupportedOperationException theE) {
assertNotNull(theE);
}
}
} }

View File

@ -52,7 +52,6 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextEntityManager;

View File

@ -1,7 +1,6 @@
package ca.uhn.fhir.jpa.dao.dstu3; package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.model.CodeSystem; import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.Enumerations; import org.hl7.fhir.dstu3.model.Enumerations;
@ -13,6 +12,8 @@ import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
public class FhirResourceDaoDstu3CodeSystemTest extends BaseJpaDstu3Test { public class FhirResourceDaoDstu3CodeSystemTest extends BaseJpaDstu3Test {
@AfterAll @AfterAll
@ -77,5 +78,17 @@ public class FhirResourceDaoDstu3CodeSystemTest extends BaseJpaDstu3Test {
} }
@Test
public void testValidateCodeForCodeSystemOperationNotSupported() {
try {
myCodeSystemDao.validateCode(null, null, null, null, null, null, null, null);
fail();
} catch (UnsupportedOperationException theE) {
assertNotNull(theE);
}
}
} }

View File

@ -1,23 +1,32 @@
package ca.uhn.fhir.jpa.dao.dstu3; package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.api.model.TranslationMatch; import static org.junit.jupiter.api.Assertions.assertEquals;
import ca.uhn.fhir.jpa.api.model.TranslationRequest; import static org.junit.jupiter.api.Assertions.assertFalse;
import ca.uhn.fhir.jpa.api.model.TranslationResult; import static org.junit.jupiter.api.Assertions.assertNull;
import ca.uhn.fhir.util.TestUtil; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import java.util.Optional;
import org.hl7.fhir.dstu3.model.ConceptMap; import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.model.UriType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
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 static org.junit.jupiter.api.Assertions.*; import ca.uhn.fhir.jpa.api.model.TranslationMatch;
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
import ca.uhn.fhir.jpa.api.model.TranslationResult;
import ca.uhn.fhir.jpa.entity.TermConceptMap;
public class FhirResourceDaoDstu3ConceptMapTest extends BaseJpaDstu3Test { public class FhirResourceDaoDstu3ConceptMapTest extends BaseJpaDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3ConceptMapTest.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3ConceptMapTest.class);
@ -98,4 +107,74 @@ public class FhirResourceDaoDstu3ConceptMapTest extends BaseJpaDstu3Test {
}); });
} }
@Test
public void testConceptMapFindTermConceptMapByUrl() {
Pageable page = PageRequest.of(0, 1);
List<TermConceptMap> theExpConceptMapList = myTermConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page, CM_URL);
assertEquals(1, theExpConceptMapList.size());
assertEquals(CM_URL, theExpConceptMapList.get(0).getUrl());
}
@Test
public void testConceptMapTwoConceptMapWithSameUrlDifferentVersion() {
String theUrl = "http://loinc.org/property/analyte-suffix";
ConceptMap theConceptMap1 = new ConceptMap();
ConceptMap theConceptMap2 = new ConceptMap();
theConceptMap1.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name1").setVersion("v1");
theConceptMap2.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name2").setVersion("v2");
myConceptMapDao.create(theConceptMap1);
myConceptMapDao.create(theConceptMap2);
Optional<TermConceptMap> theExpConceptMapV1 = myTermConceptMapDao.findTermConceptMapByUrlAndVersion(theUrl, "v1");
Optional<TermConceptMap> theExpConceptMapV2 = myTermConceptMapDao.findTermConceptMapByUrlAndVersion(theUrl, "v2");
assertTrue(theExpConceptMapV1.isPresent());
assertEquals(theUrl, theExpConceptMapV1.get().getUrl());
assertEquals("v1", theExpConceptMapV1.get().getVersion());
assertTrue(theExpConceptMapV2.isPresent());
assertEquals(theUrl, theExpConceptMapV2.get().getUrl());
assertEquals("v2", theExpConceptMapV2.get().getVersion());
// should return the latest one which is v2
Pageable page = PageRequest.of(0, 1);
List<TermConceptMap> theExpSecondOne = myTermConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page, theUrl);
assertEquals(1, theExpSecondOne.size());
assertEquals(theUrl, theExpSecondOne.get(0).getUrl());
assertEquals("v2", theExpSecondOne.get(0).getVersion());
}
@Test
public void testConceptMapTwoConceptMapWithSameUrlOneWithoutVersion() {
String theUrl = "http://loinc.org/property/analyte-suffix";
ConceptMap theConceptMap1 = new ConceptMap();
ConceptMap theConceptMap2 = new ConceptMap();
theConceptMap1.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name1").setVersion("v1");
theConceptMap2.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name2");
myConceptMapDao.create(theConceptMap1);
myConceptMapDao.create(theConceptMap2);
Optional<TermConceptMap> theExpConceptMapV1 = myTermConceptMapDao.findTermConceptMapByUrlAndVersion(theUrl, "v1");
assertTrue(theExpConceptMapV1.isPresent());
assertEquals(theUrl, theExpConceptMapV1.get().getUrl());
assertEquals("v1", theExpConceptMapV1.get().getVersion());
// should return the latest one which in this case is not versioned
Pageable page = PageRequest.of(0, 1);
List<TermConceptMap> theExpSecondOne = myTermConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page, theUrl);
assertEquals(1, theExpSecondOne.size());
assertEquals(theUrl, theExpSecondOne.get(0).getUrl());
assertNull(theExpSecondOne.get(0).getVersion());
}
} }

View File

@ -80,6 +80,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
private CodeSystem createExternalCs() { private CodeSystem createExternalCs() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
codeSystem.setName("ACME Codes"); codeSystem.setName("ACME Codes");
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -124,6 +125,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
private void createExternalCsLarge() { private void createExternalCsLarge() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -165,6 +167,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
private CodeSystem createExternalCsDogs() { private CodeSystem createExternalCsDogs() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -698,6 +701,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
public void testLookupSnomed() { public void testLookupSnomed() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl("http://snomed.info/sct"); codeSystem.setUrl("http://snomed.info/sct");
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();

View File

@ -0,0 +1,222 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
import ca.uhn.fhir.jpa.entity.TermValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class FhirResourceDaoDstu3ValueSetMultiVersionTest extends BaseJpaDstu3Test {
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
private enum ValueSetVersions { NULL, V1, V2 }
@Autowired
protected ITermValueSetConceptDao myTermValueSetConceptDao;
private DaoMethodOutcome createLocalCsAndVs(String theVersion, Set<String> theCodeSystemCodes) {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion(theVersion);
codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
for (String codeSystemCode : theCodeSystemCodes) {
codeSystem.addConcept().setCode(codeSystemCode);
}
myCodeSystemDao.create(codeSystem, mySrd);
return createLocalVs(codeSystem, theVersion);
}
private DaoMethodOutcome createLocalVs(CodeSystem theCodeSystem, String theVersion) {
ValueSet valueSet = new ValueSet();
valueSet.setUrl(URL_MY_VALUE_SET);
valueSet.setVersion(theVersion);
if (theVersion == null) {
valueSet.setName("ValueSet_noVersion");
} else {
valueSet.setName("ValueSet_"+theVersion);
}
valueSet.getCompose().addInclude().setSystem(theCodeSystem.getUrl());
return myValueSetDao.create(valueSet, mySrd);
}
private Map<ValueSetVersions, DaoMethodOutcome> createVersionedValueSets() {
HashMap<ValueSetVersions, DaoMethodOutcome> valueSets = new HashMap<>();
Set<String> valueSetConcepts_noVersion = new HashSet<>();
valueSetConcepts_noVersion.add("hello");
valueSetConcepts_noVersion.add("goodbye");
valueSets.put(ValueSetVersions.NULL, createLocalCsAndVs(null, valueSetConcepts_noVersion));
Set<String> valueSetConcepts_v1 = new HashSet<>(valueSetConcepts_noVersion);
valueSetConcepts_v1.add("hi");
valueSets.put(ValueSetVersions.V1, createLocalCsAndVs("v1", valueSetConcepts_v1));
Set<String> valueSetConcepts_v2 = new HashSet<>(valueSetConcepts_v1);
valueSetConcepts_v2.add("so-long");
valueSets.put(ValueSetVersions.V2, createLocalCsAndVs("v2", valueSetConcepts_v2));
return valueSets;
}
@Test
public void testCreateVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
assertTrue(optionalTermValueSet.isPresent());
Long nullVersion_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.NULL).getEntity()).getId();
assertNotNull(nullVersion_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(nullVersion_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_noVersion", optionalTermValueSet.get().getName());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
assertTrue(optionalTermValueSet.isPresent());
Long v1Version_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.V1).getEntity()).getId();
assertNotNull(v1Version_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(v1Version_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_v1", optionalTermValueSet.get().getName());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2");
assertTrue(optionalTermValueSet.isPresent());
Long v2Version_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.V2).getEntity()).getId();
assertNotNull(v2Version_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(v2Version_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_v2", optionalTermValueSet.get().getName());
}
@Test
public void testUpdateVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
TermValueSet termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertEquals("ValueSet_noVersion", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertEquals("ValueSet_v1", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertEquals("ValueSet_v2", termValueSet.getName());
// Update ValueSets
ValueSet updated = (ValueSet)myValueSets.get(ValueSetVersions.NULL).getResource();
updated.setName("ValueSet_noVersion_updated");
DaoMethodOutcome nullVersion_update_outcome = myValueSetDao.update(updated);
Long nullVersion_resid = ((ResourceTable)nullVersion_update_outcome.getEntity()).getId();
updated = (ValueSet)myValueSets.get(ValueSetVersions.V1).getResource();
updated.setName("ValueSet_v1_updated");
DaoMethodOutcome v1Version_update_outcome = myValueSetDao.update(updated);
Long v1Version_resid = ((ResourceTable)v1Version_update_outcome.getEntity()).getId();
updated = (ValueSet)myValueSets.get(ValueSetVersions.V2).getResource();
updated.setName("ValueSet_v2_updated");
DaoMethodOutcome v2Version_update_outcome = myValueSetDao.update(updated);
Long v2Version_resid = ((ResourceTable)v2Version_update_outcome.getEntity()).getId();
// Verify that ValueSets were updated.
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertNotNull(nullVersion_resid);
assertNotNull(termValueSet.getResource());
assertEquals(nullVersion_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_noVersion_updated", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertNotNull(v1Version_resid);
assertNotNull(termValueSet.getResource());
assertEquals(v1Version_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_v1_updated", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertNotNull(v2Version_resid);
assertNotNull(termValueSet.getResource());
assertEquals(v2Version_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_v2_updated", termValueSet.getName());
}
@Test
public void testDeleteVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
TermValueSet termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertEquals("ValueSet_noVersion", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertEquals("ValueSet_v1", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertEquals("ValueSet_v2", termValueSet.getName());
// Delete ValueSets
myValueSetDao.delete(myValueSets.get(ValueSetVersions.NULL).getResource().getIdElement());
assertEquals(2, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
myValueSetDao.delete(myValueSets.get(ValueSetVersions.V1).getResource().getIdElement());
assertEquals(1, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
if (optionalTermValueSet.isPresent()) {
fail();
}
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
myValueSetDao.delete(myValueSets.get(ValueSetVersions.V2).getResource().getIdElement());
assertEquals(0, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2");
if (optionalTermValueSet.isPresent()) {
fail();
}
}
}

View File

@ -22,6 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.IOException; import java.io.IOException;
import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
@ -76,6 +77,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd); validationOutcome = myValueSetDao.validateCode(vsIdentifier, null, code, system, null, null, null, mySrd);
assertEquals(false, validationOutcome.isOk()); assertEquals(false, validationOutcome.isOk());
await().until(() -> clearDeferredStorageQueue());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
runInTransaction(() -> { runInTransaction(() -> {
@ -95,6 +97,16 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test {
} }
private boolean clearDeferredStorageQueue() {
if(!myTerminologyDeferredStorageSvc.isStorageQueueEmpty()) {
myTerminologyDeferredStorageSvc.saveAllDeferred();
return false;
} else {
return true;
}
}
@Test @Test
@Disabled @Disabled

View File

@ -64,7 +64,6 @@ 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.SearchParamRegistryImpl; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.subscription.match.registry.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;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
@ -81,7 +80,6 @@ import ca.uhn.fhir.rest.server.BasePagingProvider;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.test.utilities.ITestDataBuilder; import ca.uhn.fhir.test.utilities.ITestDataBuilder;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.ValidationResult;

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r4; package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
@ -8,6 +9,7 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals;
@ -35,15 +37,7 @@ public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test {
@Test @Test
public void testDeleteLargeCompleteCodeSystem() { public void testDeleteLargeCompleteCodeSystem() {
CodeSystem cs = new CodeSystem(); IIdType id = createLargeCodeSystem(null);
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setUrl("http://foo");
for (int i = 0; i < 222; i++) {
cs.addConcept().setCode("CODE" + i);
}
IIdType id = myCodeSystemDao.create(cs).getId().toUnqualifiedVersionless();
myTerminologyDeferredStorageSvc.saveDeferred();
myTerminologyDeferredStorageSvc.saveDeferred();
runInTransaction(() -> { runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count()); assertEquals(1, myTermCodeSystemDao.count());
@ -65,13 +59,129 @@ public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test {
// Now the background scheduler will do its thing // Now the background scheduler will do its thing
myTerminologyDeferredStorageSvc.saveDeferred(); myTerminologyDeferredStorageSvc.saveDeferred();
runInTransaction(() -> { runInTransaction(() -> {
assertEquals(0, myTermCodeSystemDao.count()); assertEquals(1, myTermCodeSystemDao.count());
assertEquals(0, myTermCodeSystemVersionDao.count()); assertEquals(0, myTermCodeSystemVersionDao.count());
assertEquals(0, myTermConceptDao.count()); assertEquals(0, myTermConceptDao.count());
}); });
} }
@Test
public void testDeleteCodeSystemVersion() {
// Create code system with two versions.
IIdType id_first = createLargeCodeSystem("1");
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(222, myTermConceptDao.count());
assertEquals(1, resourceList.size());
assertNull(resourceList.get(0).getDeleted());
});
IIdType id_second = createLargeCodeSystem("2");
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(2, myTermCodeSystemVersionDao.count());
assertEquals(444, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(2, active);
});
// Attempt to delete first version
myCodeSystemDao.delete(id_first, mySrd);
// Only the resource will be deleted initially
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(2, myTermCodeSystemVersionDao.count());
assertEquals(444, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(1, active);
});
// Now the background scheduler will do its thing
myTerminologyDeferredStorageSvc.saveDeferred();
// Entities for first resource should be gone now.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(1, active);
});
// Attempt to delete second version
myCodeSystemDao.delete(id_second, mySrd);
// Only the resource will be deleted initially, but the URL for the TermCodeSystem will be cleared and not searchable.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(0, active);
});
// Now the background scheduler will do its thing
myTerminologyDeferredStorageSvc.saveDeferred();
// The remaining versions and Code System entities should be gone now.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(0, myTermCodeSystemVersionDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(0, active);
});
}
private IIdType createLargeCodeSystem(String theVersion) {
CodeSystem cs = new CodeSystem();
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setUrl("http://foo");
if (theVersion != null) {
cs.setVersion(theVersion);
}
for (int i = 0; i < 222; i++) {
cs.addConcept().setCode("CODE" + i);
}
IIdType id = myCodeSystemDao.create(cs).getId().toUnqualifiedVersionless();
myTerminologyDeferredStorageSvc.saveDeferred();
myTerminologyDeferredStorageSvc.saveDeferred();
return id;
}
@AfterAll @AfterAll
public static void afterClassClearContext() { public static void afterClassClearContext() {
TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(false); TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(false);

View File

@ -1,31 +1,37 @@
package ca.uhn.fhir.jpa.dao.r4; package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.api.model.TranslationMatch; import static org.junit.jupiter.api.Assertions.assertEquals;
import ca.uhn.fhir.jpa.api.model.TranslationRequest; import static org.junit.jupiter.api.Assertions.assertFalse;
import ca.uhn.fhir.jpa.api.model.TranslationResult; import static org.junit.jupiter.api.Assertions.assertNull;
import ca.uhn.fhir.util.TestUtil; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CanonicalType; import org.hl7.fhir.r4.model.CanonicalType;
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.ConceptMap; import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence; import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r4.model.UriType; import org.hl7.fhir.r4.model.UriType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
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.io.IOException; import ca.uhn.fhir.jpa.api.model.TranslationMatch;
import ca.uhn.fhir.jpa.api.model.TranslationRequest;
import static org.junit.jupiter.api.Assertions.assertEquals; import ca.uhn.fhir.jpa.api.model.TranslationResult;
import static org.junit.jupiter.api.Assertions.assertFalse; import ca.uhn.fhir.jpa.entity.TermConceptMap;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class FhirResourceDaoR4ConceptMapTest extends BaseJpaR4Test { public class FhirResourceDaoR4ConceptMapTest extends BaseJpaR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4ConceptMapTest.class); private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoR4ConceptMapTest.class);
@ -1148,5 +1154,74 @@ public class FhirResourceDaoR4ConceptMapTest extends BaseJpaR4Test {
assertEquals("S52.209A", outcome.getMatches().get(0).getConcept().getCode()); assertEquals("S52.209A", outcome.getMatches().get(0).getConcept().getCode());
} }
@Test
public void testConceptMapFindTermConceptMapByUrl() {
Pageable page = PageRequest.of(0, 1);
List<TermConceptMap> theExpConceptMapList = myTermConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page, CM_URL);
assertEquals(1, theExpConceptMapList.size());
assertEquals(CM_URL, theExpConceptMapList.get(0).getUrl());
}
@Test
public void testConceptMapTwoConceptMapWithSameUrlDifferentVersion() {
String theUrl = "http://loinc.org/property/analyte-suffix";
ConceptMap theConceptMap1 = new ConceptMap();
ConceptMap theConceptMap2 = new ConceptMap();
theConceptMap1.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name1").setVersion("v1");
theConceptMap2.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name2").setVersion("v2");
myConceptMapDao.create(theConceptMap1);
myConceptMapDao.create(theConceptMap2);
Optional<TermConceptMap> theExpConceptMapV1 = myTermConceptMapDao.findTermConceptMapByUrlAndVersion(theUrl, "v1");
Optional<TermConceptMap> theExpConceptMapV2 = myTermConceptMapDao.findTermConceptMapByUrlAndVersion(theUrl, "v2");
assertTrue(theExpConceptMapV1.isPresent());
assertEquals(theUrl, theExpConceptMapV1.get().getUrl());
assertEquals("v1", theExpConceptMapV1.get().getVersion());
assertTrue(theExpConceptMapV2.isPresent());
assertEquals(theUrl, theExpConceptMapV2.get().getUrl());
assertEquals("v2", theExpConceptMapV2.get().getVersion());
// should return the latest one which is v2
Pageable page = PageRequest.of(0, 1);
List<TermConceptMap> theExpSecondOne = myTermConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page, theUrl);
assertEquals(1, theExpSecondOne.size());
assertEquals(theUrl, theExpSecondOne.get(0).getUrl());
assertEquals("v2", theExpSecondOne.get(0).getVersion());
}
@Test
public void testConceptMapTwoConceptMapWithSameUrlOneWithoutVersion() {
String theUrl = "http://loinc.org/property/analyte-suffix";
ConceptMap theConceptMap1 = new ConceptMap();
ConceptMap theConceptMap2 = new ConceptMap();
theConceptMap1.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name1").setVersion("v1");
theConceptMap2.setUrl(theUrl).setStatus(PublicationStatus.ACTIVE).setName("name2");
myConceptMapDao.create(theConceptMap1);
myConceptMapDao.create(theConceptMap2);
Optional<TermConceptMap> theExpConceptMapV1 = myTermConceptMapDao.findTermConceptMapByUrlAndVersion(theUrl, "v1");
assertTrue(theExpConceptMapV1.isPresent());
assertEquals(theUrl, theExpConceptMapV1.get().getUrl());
assertEquals("v1", theExpConceptMapV1.get().getVersion());
// should return the latest one which is v2
Pageable page = PageRequest.of(0, 1);
List<TermConceptMap> theExpSecondOne = myTermConceptMapDao.getTermConceptMapEntitiesByUrlOrderByMostRecentUpdate(page, theUrl);
assertEquals(1, theExpSecondOne.size());
assertEquals(theUrl, theExpSecondOne.get(0).getUrl());
assertNull(theExpSecondOne.get(0).getVersion());
}
} }

View File

@ -209,6 +209,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest {
private CodeSystem createExternalCs() { private CodeSystem createExternalCs() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();

View File

@ -337,6 +337,34 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
} }
@Test
public void testExpandValueSetContainingSystemIncludeAndExcludeWithNoCodes() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/r4/iar/CodeSystem-iar-citizenship-status.xml");
myCodeSystemDao.create(cs);
ValueSet vs = loadResourceFromClasspath(ValueSet.class, "/r4/iar/ValueSet-iar-citizenship-status.xml");
ValueSet.ConceptSetComponent excludeComponent = new ValueSet.ConceptSetComponent().setSystem("http://ccim.on.ca/fhir/iar/CodeSystem/iar-citizenship-status");
excludeComponent.addConcept().setCode("REF");
vs.getCompose().addExclude(excludeComponent);
myValueSetDao.create(vs);
CodeSystem cs2 = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
myCodeSystemDao.create(cs2);
ValueSet vs2 = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs-with-exclude.xml");
myValueSetDao.create(vs2);
ValueSet expansion = myValueSetDao.expandByIdentifier("http://ccim.on.ca/fhir/iar/ValueSet/iar-citizenship-status", null);
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion));
assertEquals(5, expansion.getExpansion().getContains().size());
ValueSet expansion2 = myValueSetDao.expandByIdentifier("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", null);
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion2));
assertEquals(22, expansion2.getExpansion().getContains().size());
}
} }

View File

@ -85,6 +85,7 @@ public class FhirResourceDaoR4TerminologyElasticsearchIT extends BaseJpaTest {
public void testExpandWithIncludeContainingDashesInInclude() { public void testExpandWithIncludeContainingDashesInInclude() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();

View File

@ -80,6 +80,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
private CodeSystem createExternalCs() { private CodeSystem createExternalCs() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -129,6 +130,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
private CodeSystem createExternalCsDogs() { private CodeSystem createExternalCsDogs() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -159,6 +161,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
private void createExternalCsLarge() { private void createExternalCsLarge() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -232,6 +235,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
@Test @Test
public void testCodeSystemCreateDuplicateFails() { public void testCodeSystemCreateDuplicateFails() {
// No version.
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setContent(CodeSystemContentMode.COMPLETE); codeSystem.setContent(CodeSystemContentMode.COMPLETE);
@ -246,6 +250,25 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
} catch (UnprocessableEntityException e) { } catch (UnprocessableEntityException e) {
assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage()); assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
} }
// With version.
codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("1");
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("1");
codeSystem.setContent(CodeSystemContentMode.COMPLETE);
try {
myCodeSystemDao.create(codeSystem, mySrd);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\" and CodeSystem.version \"1\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
}
} }
@Test @Test
@ -473,6 +496,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
public void testExpandWithIncludeContainingDashesInInclude() { public void testExpandWithIncludeContainingDashesInInclude() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -815,6 +839,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
public void testLookupSnomed() { public void testLookupSnomed() {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl("http://snomed.info/sct"); codeSystem.setUrl("http://snomed.info/sct");
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();

View File

@ -9,8 +9,6 @@ import ca.uhn.fhir.jpa.entity.TermValueSet;
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum; import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl; import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvcLoincTest;
import ca.uhn.fhir.jpa.term.ZipCollectionBuilder;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc; import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
@ -80,7 +78,6 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;

View File

@ -0,0 +1,246 @@
package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
import ca.uhn.fhir.jpa.entity.TermValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.ValueSet;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class FhirResourceDaoR4ValueSetMultiVersionTest extends BaseJpaR4Test {
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
private enum ValueSetVersions { NULL, V1, V2 }
@Autowired
protected ITermValueSetConceptDao myTermValueSetConceptDao;
private DaoMethodOutcome createLocalCsAndVs(String theVersion, Set<String> theCodeSystemCodes) {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion(theVersion);
codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
for (String codeSystemCode : theCodeSystemCodes) {
codeSystem.addConcept().setCode(codeSystemCode);
}
myCodeSystemDao.create(codeSystem, mySrd);
return createLocalVs(codeSystem, theVersion);
}
private DaoMethodOutcome createLocalVs(CodeSystem theCodeSystem, String theVersion) {
ValueSet valueSet = new ValueSet();
valueSet.setUrl(URL_MY_VALUE_SET);
valueSet.setVersion(theVersion);
if (theVersion == null) {
valueSet.setName("ValueSet_noVersion");
} else {
valueSet.setName("ValueSet_"+theVersion);
}
valueSet.getCompose().addInclude().setSystem(theCodeSystem.getUrl());
return myValueSetDao.create(valueSet, mySrd);
}
private Map<ValueSetVersions, DaoMethodOutcome> createVersionedValueSets() {
HashMap<ValueSetVersions, DaoMethodOutcome> valueSets = new HashMap<>();
Set<String> valueSetConcepts_noVersion = new HashSet<>();
valueSetConcepts_noVersion.add("hello");
valueSetConcepts_noVersion.add("goodbye");
valueSets.put(ValueSetVersions.NULL, createLocalCsAndVs(null, valueSetConcepts_noVersion));
Set<String> valueSetConcepts_v1 = new HashSet<>(valueSetConcepts_noVersion);
valueSetConcepts_v1.add("hi");
valueSets.put(ValueSetVersions.V1, createLocalCsAndVs("v1", valueSetConcepts_v1));
Set<String> valueSetConcepts_v2 = new HashSet<>(valueSetConcepts_v1);
valueSetConcepts_v2.add("so-long");
valueSets.put(ValueSetVersions.V2, createLocalCsAndVs("v2", valueSetConcepts_v2));
return valueSets;
}
@Test
public void testCreateVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
assertTrue(optionalTermValueSet.isPresent());
Long nullVersion_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.NULL).getEntity()).getId();
assertNotNull(nullVersion_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(nullVersion_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_noVersion", optionalTermValueSet.get().getName());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
assertTrue(optionalTermValueSet.isPresent());
Long v1Version_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.V1).getEntity()).getId();
assertNotNull(v1Version_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(v1Version_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_v1", optionalTermValueSet.get().getName());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2");
assertTrue(optionalTermValueSet.isPresent());
Long v2Version_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.V2).getEntity()).getId();
assertNotNull(v2Version_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(v2Version_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_v2", optionalTermValueSet.get().getName());
}
@Test
public void testUpdateVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
TermValueSet termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertEquals("ValueSet_noVersion", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertEquals("ValueSet_v1", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertEquals("ValueSet_v2", termValueSet.getName());
// Update ValueSets
ValueSet updated = (ValueSet)myValueSets.get(ValueSetVersions.NULL).getResource();
updated.setName("ValueSet_noVersion_updated");
DaoMethodOutcome nullVersion_update_outcome = myValueSetDao.update(updated);
Long nullVersion_resid = ((ResourceTable)nullVersion_update_outcome.getEntity()).getId();
updated = (ValueSet)myValueSets.get(ValueSetVersions.V1).getResource();
updated.setName("ValueSet_v1_updated");
DaoMethodOutcome v1Version_update_outcome = myValueSetDao.update(updated);
Long v1Version_resid = ((ResourceTable)v1Version_update_outcome.getEntity()).getId();
updated = (ValueSet)myValueSets.get(ValueSetVersions.V2).getResource();
updated.setName("ValueSet_v2_updated");
DaoMethodOutcome v2Version_update_outcome = myValueSetDao.update(updated);
Long v2Version_resid = ((ResourceTable)v2Version_update_outcome.getEntity()).getId();
// Verify that ValueSets were updated.
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertNotNull(nullVersion_resid);
assertNotNull(termValueSet.getResource());
assertEquals(nullVersion_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_noVersion_updated", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertNotNull(v1Version_resid);
assertNotNull(termValueSet.getResource());
assertEquals(v1Version_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_v1_updated", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertNotNull(v2Version_resid);
assertNotNull(termValueSet.getResource());
assertEquals(v2Version_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_v2_updated", termValueSet.getName());
}
@Test
public void testDeleteVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
TermValueSet termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertEquals("ValueSet_noVersion", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertEquals("ValueSet_v1", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertEquals("ValueSet_v2", termValueSet.getName());
// Delete ValueSets
myValueSetDao.delete(myValueSets.get(ValueSetVersions.NULL).getResource().getIdElement());
assertEquals(2, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
myValueSetDao.delete(myValueSets.get(ValueSetVersions.V1).getResource().getIdElement());
assertEquals(1, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
if (optionalTermValueSet.isPresent()) {
fail();
}
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
myValueSetDao.delete(myValueSets.get(ValueSetVersions.V2).getResource().getIdElement());
assertEquals(0, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2");
if (optionalTermValueSet.isPresent()) {
fail();
}
}
@Test
public void testExpandWithNoResultsInLocalValueSet() {
Set<String> valueSetConcepts = new HashSet<>();
valueSetConcepts.add("hello");
valueSetConcepts.add("goodbye");
createLocalCsAndVs("1", valueSetConcepts);
ValueSet vs = new ValueSet();
ValueSet.ConceptSetComponent include = vs.getCompose().addInclude();
include.setSystem(URL_MY_CODE_SYSTEM + "AA");
include.setVersion("1");
include.addConcept().setCode("A");
try {
myValueSetDao.expand(vs, null);
fail();
} catch (PreconditionFailedException e) {
assertEquals("Unknown CodeSystem URI \"http://example.com/my_code_systemAA\" referenced from ValueSet", e.getMessage());
}
}
}

View File

@ -69,7 +69,6 @@ import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.BasePagingProvider; import ca.uhn.fhir.rest.server.BasePagingProvider;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.ValidationResult;

View File

@ -0,0 +1,175 @@
package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
public class FhirResourceDaoR5CodeSystemTest extends BaseJpaR5Test {
@Test
public void testDeleteLargeCompleteCodeSystem() {
IIdType id = createLargeCodeSystem(null);
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
});
myCodeSystemDao.delete(id);
// Nothing is deleted initially but the URI is changed so it can't be found
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
});
// Now the background scheduler will do its thing
myTermDeferredStorageSvc.saveDeferred();
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertEquals(0, myTermCodeSystemVersionDao.count());
assertEquals(0, myTermConceptDao.count());
});
}
@Test
public void testDeleteCodeSystemVersion() {
// Create code system with two versions.
IIdType id_first = createLargeCodeSystem("1");
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(222, myTermConceptDao.count());
assertEquals(1, resourceList.size());
assertNull(resourceList.get(0).getDeleted());
});
IIdType id_second = createLargeCodeSystem("2");
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(2, myTermCodeSystemVersionDao.count());
assertEquals(444, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(2, active);
});
// Attempt to delete first version
myCodeSystemDao.delete(id_first, mySrd);
// Only the resource will be deleted initially
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(2, myTermCodeSystemVersionDao.count());
assertEquals(444, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(1, active);
});
// Now the background scheduler will do its thing
myTermDeferredStorageSvc.saveDeferred();
// Entities for first resource should be gone now.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNotNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(1, active);
});
// Attempt to delete second version
myCodeSystemDao.delete(id_second, mySrd);
// Only the resource will be deleted initially, but the URL for the TermCodeSystem will be cleared and not searchable.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(1, myTermCodeSystemVersionDao.count());
assertEquals(222, myTermConceptDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(0, active);
});
// Now the background scheduler will do its thing
myTermDeferredStorageSvc.saveDeferred();
// The remaining versions and Code System entities should be gone now.
runInTransaction(() -> {
assertEquals(1, myTermCodeSystemDao.count());
assertNull(myTermCodeSystemDao.findByCodeSystemUri("http://foo"));
assertEquals(0, myTermCodeSystemVersionDao.count());
List<ResourceTable> resourceList = myResourceTableDao.findAll();
assertEquals(2, resourceList.size());
long active = resourceList
.stream()
.filter(t -> t.getDeleted() == null).count();
assertEquals(0, active);
});
}
private IIdType createLargeCodeSystem(String theVersion) {
CodeSystem cs = new CodeSystem();
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
cs.setUrl("http://foo");
if (theVersion != null) {
cs.setVersion(theVersion);
}
for (int i = 0; i < 222; i++) {
cs.addConcept().setCode("CODE" + i);
}
IIdType id = myCodeSystemDao.create(cs).getId().toUnqualifiedVersionless();
myTermDeferredStorageSvc.saveDeferred();
myTermDeferredStorageSvc.saveDeferred();
return id;
}
@AfterAll
public static void afterClassClearContext() {
TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(false);
}
}

View File

@ -0,0 +1,222 @@
package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
import ca.uhn.fhir.jpa.entity.TermValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.ValueSet;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class FhirResourceDaoR5ValueSetMultiVersionTest extends BaseJpaR5Test {
public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set";
public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system";
private enum ValueSetVersions { NULL, V1, V2 }
@Autowired
protected ITermValueSetConceptDao myTermValueSetConceptDao;
private DaoMethodOutcome createLocalCsAndVs(String theVersion, Set<String> theCodeSystemCodes) {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion(theVersion);
codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
for (String codeSystemCode : theCodeSystemCodes) {
codeSystem.addConcept().setCode(codeSystemCode);
}
myCodeSystemDao.create(codeSystem, mySrd);
return createLocalVs(codeSystem, theVersion);
}
private DaoMethodOutcome createLocalVs(CodeSystem theCodeSystem, String theVersion) {
ValueSet valueSet = new ValueSet();
valueSet.setUrl(URL_MY_VALUE_SET);
valueSet.setVersion(theVersion);
if (theVersion == null) {
valueSet.setName("ValueSet_noVersion");
} else {
valueSet.setName("ValueSet_"+theVersion);
}
valueSet.getCompose().addInclude().setSystem(theCodeSystem.getUrl());
return myValueSetDao.create(valueSet, mySrd);
}
private Map<ValueSetVersions, DaoMethodOutcome> createVersionedValueSets() {
HashMap<ValueSetVersions, DaoMethodOutcome> valueSets = new HashMap<>();
Set<String> valueSetConcepts_noVersion = new HashSet<>();
valueSetConcepts_noVersion.add("hello");
valueSetConcepts_noVersion.add("goodbye");
valueSets.put(ValueSetVersions.NULL, createLocalCsAndVs(null, valueSetConcepts_noVersion));
Set<String> valueSetConcepts_v1 = new HashSet<>(valueSetConcepts_noVersion);
valueSetConcepts_v1.add("hi");
valueSets.put(ValueSetVersions.V1, createLocalCsAndVs("v1", valueSetConcepts_v1));
Set<String> valueSetConcepts_v2 = new HashSet<>(valueSetConcepts_v1);
valueSetConcepts_v2.add("so-long");
valueSets.put(ValueSetVersions.V2, createLocalCsAndVs("v2", valueSetConcepts_v2));
return valueSets;
}
@Test
public void testCreateVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
assertTrue(optionalTermValueSet.isPresent());
Long nullVersion_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.NULL).getEntity()).getId();
assertNotNull(nullVersion_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(nullVersion_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_noVersion", optionalTermValueSet.get().getName());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
assertTrue(optionalTermValueSet.isPresent());
Long v1Version_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.V1).getEntity()).getId();
assertNotNull(v1Version_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(v1Version_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_v1", optionalTermValueSet.get().getName());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2");
assertTrue(optionalTermValueSet.isPresent());
Long v2Version_resid = ((ResourceTable)myValueSets.get(ValueSetVersions.V2).getEntity()).getId();
assertNotNull(v2Version_resid);
assertNotNull(optionalTermValueSet.get().getResource());
assertEquals(v2Version_resid, optionalTermValueSet.get().getResource().getId());
assertEquals("ValueSet_v2", optionalTermValueSet.get().getName());
}
@Test
public void testUpdateVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
TermValueSet termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertEquals("ValueSet_noVersion", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertEquals("ValueSet_v1", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertEquals("ValueSet_v2", termValueSet.getName());
// Update ValueSets
ValueSet updated = (ValueSet)myValueSets.get(ValueSetVersions.NULL).getResource();
updated.setName("ValueSet_noVersion_updated");
DaoMethodOutcome nullVersion_update_outcome = myValueSetDao.update(updated);
Long nullVersion_resid = ((ResourceTable)nullVersion_update_outcome.getEntity()).getId();
updated = (ValueSet)myValueSets.get(ValueSetVersions.V1).getResource();
updated.setName("ValueSet_v1_updated");
DaoMethodOutcome v1Version_update_outcome = myValueSetDao.update(updated);
Long v1Version_resid = ((ResourceTable)v1Version_update_outcome.getEntity()).getId();
updated = (ValueSet)myValueSets.get(ValueSetVersions.V2).getResource();
updated.setName("ValueSet_v2_updated");
DaoMethodOutcome v2Version_update_outcome = myValueSetDao.update(updated);
Long v2Version_resid = ((ResourceTable)v2Version_update_outcome.getEntity()).getId();
// Verify that ValueSets were updated.
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertNotNull(nullVersion_resid);
assertNotNull(termValueSet.getResource());
assertEquals(nullVersion_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_noVersion_updated", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertNotNull(v1Version_resid);
assertNotNull(termValueSet.getResource());
assertEquals(v1Version_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_v1_updated", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertNotNull(v2Version_resid);
assertNotNull(termValueSet.getResource());
assertEquals(v2Version_resid, termValueSet.getResource().getId());
assertEquals("ValueSet_v2_updated", termValueSet.getName());
}
@Test
public void testDeleteVersionedValueSets() {
Map<ValueSetVersions, DaoMethodOutcome> myValueSets = createVersionedValueSets();
assertEquals(3, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
TermValueSet termValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET).orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " with null version"));
assertEquals("ValueSet_noVersion", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
assertEquals("ValueSet_v1", termValueSet.getName());
termValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
assertEquals("ValueSet_v2", termValueSet.getName());
// Delete ValueSets
myValueSetDao.delete(myValueSets.get(ValueSetVersions.NULL).getResource().getIdElement());
assertEquals(2, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
Optional<TermValueSet> optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v1"));
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
myValueSetDao.delete(myValueSets.get(ValueSetVersions.V1).getResource().getIdElement());
assertEquals(1, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
if (optionalTermValueSet.isPresent()) {
fail();
}
myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2").orElseThrow(() -> new IllegalArgumentException("No TerValueSet found for " + URL_MY_VALUE_SET + " version v2"));
myValueSetDao.delete(myValueSets.get(ValueSetVersions.V2).getResource().getIdElement());
assertEquals(0, myTermValueSetDao.findTermValueSetByUrl(PageRequest.of(0, 10), URL_MY_VALUE_SET).size());
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndNullVersion(URL_MY_VALUE_SET);
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v1");
if (optionalTermValueSet.isPresent()) {
fail();
}
optionalTermValueSet = myTermValueSetDao.findTermValueSetByUrlAndVersion(URL_MY_VALUE_SET, "v2");
if (optionalTermValueSet.isPresent()) {
fail();
}
}
}

View File

@ -0,0 +1,282 @@
package ca.uhn.fhir.jpa.dao.r5;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.IdType;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.UriType;
import org.hl7.fhir.r5.model.ValueSet;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class FhirResourceDaoR5ValueSetTest extends BaseJpaR5Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR5ValueSetTest.class);
@Autowired
protected ITermDeferredStorageSvc myTerminologyDeferredStorageSvc;
private IIdType myExtensionalVsId;
@AfterEach
public void after() {
myDaoConfig.setPreExpandValueSets(new DaoConfig().isPreExpandValueSets());
myDaoConfig.setMaximumExpansionSize(new DaoConfig().getMaximumExpansionSize());
}
@BeforeEach
@Transactional
public void before02() throws IOException {
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless();
CodeSystem upload2 = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
myCodeSystemDao.create(upload2, mySrd).getId().toUnqualifiedVersionless();
}
@Test
public void testValidateCodeOperationNoValueSet() {
UriType valueSetIdentifier = null;
IdType id = null;
CodeType code = new CodeType("8450-9-XXX");
UriType system = new UriType("http://acme.org");
StringType display = null;
Coding coding = null;
CodeableConcept codeableConcept = null;
try {
myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
fail();
} catch (InvalidRequestException e) {
assertEquals("Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.", e.getMessage());
}
}
@Test
public void testValidateCodeOperationByIdentifierAndCodeAndSystem() {
UriType valueSetIdentifier = new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
IdType id = null;
CodeType code = new CodeType("11378-7");
UriType system = new UriType("http://acme.org");
StringType display = null;
Coding coding = null;
CodeableConcept codeableConcept = null;
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
}
@Test
public void testValidateCodeOperationByIdentifierAndCodeAndSystemAndBadDisplay() {
UriType valueSetIdentifier = new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
IdType id = null;
CodeType code = new CodeType("11378-7");
UriType system = new UriType("http://acme.org");
StringType display = new StringType("Systolic blood pressure at First encounterXXXX");
Coding coding = null;
CodeableConcept codeableConcept = null;
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertFalse(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
assertEquals("Concept Display \"Systolic blood pressure at First encounterXXXX\" does not match expected \"Systolic blood pressure at First encounter\"", result.getMessage());
}
@Test
public void testValidateCodeOperationByIdentifierAndCodeAndSystemAndGoodDisplay() {
UriType valueSetIdentifier = new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
IdType id = null;
CodeType code = new CodeType("11378-7");
UriType system = new UriType("http://acme.org");
StringType display = new StringType("Systolic blood pressure at First encounter");
Coding coding = null;
CodeableConcept codeableConcept = null;
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
}
@Test
public void testValidateCodeOperationByResourceIdAndCodeableConcept() {
UriType valueSetIdentifier = null;
IIdType id = myExtensionalVsId;
CodeType code = null;
UriType system = null;
StringType display = null;
Coding coding = null;
CodeableConcept codeableConcept = new CodeableConcept();
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
}
@Test
public void testValidateCodeOperationByResourceIdAndCodeableConceptWithExistingValueSetAndPreExpansionEnabled() {
myDaoConfig.setPreExpandValueSets(true);
UriType valueSetIdentifier = null;
IIdType id = myExtensionalVsId;
CodeType code = null;
UriType system = null;
StringType display = null;
Coding coding = null;
CodeableConcept codeableConcept = new CodeableConcept();
codeableConcept.addCoding().setSystem("http://acme.org").setCode("11378-7");
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
myTerminologyDeferredStorageSvc.saveDeferred();
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
}
@Test
public void testValidateCodeOperationByResourceIdAndCodeAndSystem() {
UriType valueSetIdentifier = null;
IIdType id = myExtensionalVsId;
CodeType code = new CodeType("11378-7");
UriType system = new UriType("http://acme.org");
StringType display = null;
Coding coding = null;
CodeableConcept codeableConcept = null;
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
}
@Test
public void testValidateCodeOperationByResourceIdAndCodeAndSystemWithExistingValueSetAndPreExpansionEnabled() {
myDaoConfig.setPreExpandValueSets(true);
UriType valueSetIdentifier = null;
IIdType id = myExtensionalVsId;
CodeType code = new CodeType("11378-7");
UriType system = new UriType("http://acme.org");
StringType display = null;
Coding coding = null;
CodeableConcept codeableConcept = null;
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
myTerminologyDeferredStorageSvc.saveDeferred();
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
result = myValueSetDao.validateCode(valueSetIdentifier, id, code, system, display, coding, codeableConcept, mySrd);
assertTrue(result.isOk());
assertEquals("Systolic blood pressure at First encounter", result.getDisplay());
}
@Test
public void testExpandById() {
String resp;
ValueSet expanded = myValueSetDao.expand(myExtensionalVsId, null, mySrd);
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, containsString("<ValueSet xmlns=\"http://hl7.org/fhir\">"));
assertThat(resp, containsString("<expansion>"));
assertThat(resp, containsString("<contains>"));
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
assertThat(resp, containsString("<code value=\"8450-9\"/>"));
assertThat(resp, containsString("<display value=\"Systolic blood pressure--expiration\"/>"));
assertThat(resp, containsString("</contains>"));
assertThat(resp, containsString("<contains>"));
assertThat(resp, containsString("<system value=\"http://acme.org\"/>"));
assertThat(resp, containsString("<code value=\"11378-7\"/>"));
assertThat(resp, containsString("<display value=\"Systolic blood pressure at First encounter\"/>"));
assertThat(resp, containsString("</contains>"));
assertThat(resp, containsString("</expansion>"));
/*
* Filter with display name
*/
expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd);
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
}
@Test
public void testExpandByValueSet_ExceedsMaxSize() {
// Add a bunch of codes
CustomTerminologySet codesToAdd = new CustomTerminologySet();
for (int i = 0; i < 100; i++) {
codesToAdd.addRootConcept("CODE" + i, "Display " + i);
}
myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://loinc.org", codesToAdd);
myDaoConfig.setMaximumExpansionSize(50);
ValueSet vs = new ValueSet();
vs.setUrl("http://example.com/fhir/ValueSet/observation-vitalsignresult");
vs.getCompose().addInclude().setSystem("http://loinc.org");
myValueSetDao.create(vs);
try {
myValueSetDao.expand(vs, null);
fail();
} catch (InternalErrorException e) {
assertEquals("Expansion of ValueSet produced too many codes (maximum 50) - Operation aborted!", e.getMessage());
}
}
@Test
public void testValidateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
IPrimitiveType<String> display = null;
Coding coding = null;
CodeableConcept codeableConcept = null;
StringType vsIdentifier = new StringType("http://hl7.org/fhir/ValueSet/administrative-gender");
StringType code = new StringType("male");
StringType system = new StringType("http://hl7.org/fhir/administrative-gender");
IValidationSupport.CodeValidationResult result = myValueSetDao.validateCode(vsIdentifier, null, code, system, display, coding, codeableConcept, mySrd);
ourLog.info(result.getMessage());
assertTrue(result.isOk(), result.getMessage());
assertEquals("Male", result.getDisplay());
}
}

View File

@ -6,11 +6,9 @@ import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest;
import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -332,6 +330,19 @@ public class ResourceProviderDstu3CodeSystemTest extends BaseResourceProviderDst
return ourCtx.newJsonParser().parseResource(theType, loadResource(theFilename)); return ourCtx.newJsonParser().parseResource(theType, loadResource(theFilename));
} }
@Test
public void testValidateCodeOperation() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType("https://url"));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
try {
ourClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Invalid request: The FHIR endpoint on this server does not know how to handle POST operation[CodeSystem/$validate-code] with parameters [[]]", e.getMessage());
}
}
} }

View File

@ -0,0 +1,800 @@
package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.dstu3.model.BooleanType;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.Enumerations;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.UriType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
public class ResourceProviderDstu3CodeSystemVersionedTest extends BaseResourceProviderDstu3Test {
private static final String SYSTEM_PARENTCHILD = "http://parentchild";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3CodeSystemVersionedTest.class);
private long parentChildCs1Id;
private long parentChildCs2Id;
@BeforeEach
@Transactional
public void before02() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
cs.setVersion("1");
for(CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent : cs.getConcept()) {
conceptDefinitionComponent.setDisplay(conceptDefinitionComponent.getDisplay() + " v1");
}
myCodeSystemDao.create(cs, mySrd);
cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
cs.setVersion("2");
for(CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent : cs.getConcept()) {
conceptDefinitionComponent.setDisplay(conceptDefinitionComponent.getDisplay() + " v2");
}
myCodeSystemDao.create(cs, mySrd);
CodeSystem parentChildCs = new CodeSystem();
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setVersion("1");
parentChildCs.setName("Parent Child CodeSystem 1");
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA");
parentA.addConcept().setCode("ParentC").setDisplay("Parent C");
parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B");
DaoMethodOutcome parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCs1Id = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
parentChildCs = new CodeSystem();
parentChildCs.setVersion("2");
parentChildCs.setName("Parent Child CodeSystem 2");
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A v2");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA v2");
parentA.addConcept().setCode("ParentB").setDisplay("Parent B v2");
parentChildCs.addConcept().setCode("ParentC").setDisplay("Parent C v2");
parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCs2Id = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
}
@Test
public void testLookupOnExternalCodeMultiVersion() {
ResourceProviderDstu3ValueSetVersionedTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermCodeSystemStorageSvc, mySrd, "1");
ResourceProviderDstu3ValueSetVersionedTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermCodeSystemStorageSvc, mySrd, "2");
// First test with no version specified (should return from last version created)
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A1", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("1"))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("1"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A1", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("2"))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedCode() {
// First test with no version specified (should return from last version created)
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v1"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedNonExistentVersion() {
try {
ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("3"))
.execute();
fail();
} catch (ResourceNotFoundException e) {
ourLog.info("Lookup failed as expected");
}
}
@Test
public void testLookupOperationByCoding() {
// First test with no version specified (should return from last version created)
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 1
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v1"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 2
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInCode() {
// First test with no version specified (should return the one and only version defined).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("N"))
.andParameter("system", new UriType("http://hl7.org/fhir/v2/0243"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2 Identity May Be Divulged", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.8.2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("No", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
// Repeat with version specified.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("N"))
.andParameter("system", new UriType("http://hl7.org/fhir/v2/0243"))
.andParameter("version", new StringType("2.8.2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2 Identity May Be Divulged", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.8.2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("No", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumes", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumes", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumes", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumedby() {
// First test with no version specified (should return result for last version created).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumed-by", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumed-by", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumed-by", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Disjoint() {
// First test with no version specified (should return result for last version created).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("not-subsumed", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("not-subsumed", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("not-subsumed", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_MismatchedCsVersions() {
try {
ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unable to test subsumption across different code system versions", e.getMessage());
}
}
@Test
public void testSubsumesOnCodings_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumes", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumes", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumes", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Subsumedby() {
// First test with no version specified (should return result for last version created).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumed-by", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumed-by", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("subsumed-by", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Disjoint() {
// First test with no version specified (should return result for last version created).
Parameters respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("not-subsumed", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("not-subsumed", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2
respParam = ourClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals("not-subsumed", ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testUpdateCodeSystemById() throws IOException {
CodeSystem initialCodeSystem = ourClient.read().resource(CodeSystem.class).withId(parentChildCs1Id).execute();
assertEquals("Parent Child CodeSystem 1", initialCodeSystem.getName());
initialCodeSystem.setName("Updated Parent Child CodeSystem 1");
String encoded = myFhirCtx.newJsonParser().encodeResourceToString(initialCodeSystem);
HttpPut putRequest = new HttpPut(ourServerBase + "/CodeSystem/" + parentChildCs1Id);
putRequest.setEntity(new StringEntity(encoded, ContentType.parse("application/json+fhir")));
CloseableHttpResponse resp = ourHttpClient.execute(putRequest);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(resp);
}
CodeSystem updatedCodeSystem = ourClient.read().resource(CodeSystem.class).withId(parentChildCs1Id).execute();
assertEquals("Updated Parent Child CodeSystem 1", updatedCodeSystem.getName());
initialCodeSystem = ourClient.read().resource(CodeSystem.class).withId(parentChildCs2Id).execute();
assertEquals("Parent Child CodeSystem 2", initialCodeSystem.getName());
initialCodeSystem.setName("Updated Parent Child CodeSystem 2");
encoded = myFhirCtx.newJsonParser().encodeResourceToString(initialCodeSystem);
putRequest = new HttpPut(ourServerBase + "/CodeSystem/" + parentChildCs2Id);
putRequest.setEntity(new StringEntity(encoded, ContentType.parse("application/json+fhir")));
resp = ourHttpClient.execute(putRequest);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(resp);
}
updatedCodeSystem = ourClient.read().resource(CodeSystem.class).withId(parentChildCs2Id).execute();
assertEquals("Updated Parent Child CodeSystem 2", updatedCodeSystem.getName());
}
}

View File

@ -1,18 +1,30 @@
package ca.uhn.fhir.jpa.provider.dstu3; package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.rest.api.MethodOutcome; import static org.junit.jupiter.api.Assertions.assertEquals;
import ca.uhn.fhir.util.TestUtil; import static org.junit.jupiter.api.Assertions.assertFalse;
import org.hl7.fhir.dstu3.model.*; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.hl7.fhir.dstu3.model.BooleanType;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.dstu3.model.ConceptMap.ConceptMapGroupComponent;
import org.hl7.fhir.dstu3.model.ConceptMap.SourceElementComponent;
import org.hl7.fhir.dstu3.model.ConceptMap.TargetElementComponent;
import org.hl7.fhir.dstu3.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.dstu3.model.Parameters;
import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent; import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.UriType;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.*; import ca.uhn.fhir.rest.api.MethodOutcome;
public class ResourceProviderDstu3ConceptMapTest extends BaseResourceProviderDstu3Test { public class ResourceProviderDstu3ConceptMapTest extends BaseResourceProviderDstu3Test {
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderDstu3ConceptMapTest.class); private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderDstu3ConceptMapTest.class);
@ -114,4 +126,550 @@ public class ResourceProviderDstu3ConceptMapTest extends BaseResourceProviderDst
part = getPartByName(param, "source"); part = getPartByName(param, "source");
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString()); assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
} }
@Test
public void testTranslateWithConceptMapUrlAndVersion() {
String url = "http://url";
createConceptMap(url, "v1", "12222", "Target Code 12222");
createConceptMap(url, "v2", "13333", "Target Code 13333");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getValueAsString());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithVersionedConceptMapUrl_v2() {
String url = "http://url";
createConceptMap(url, "v1", "12222", "Target Code 12222");
createConceptMap(url, "v2", "13333", "Target Code 13333");
// Call translate with ConceptMap v2.
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
// Should return v2 since v2 specified.
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getValueAsString());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithVersionedConceptMapUrl_v1() {
String url = "http://url";
createConceptMap(url, "v1", "12222", "Target Code 12222");
createConceptMap(url, "v2", "13333", "Target Code 13333");
// Call translate with ConceptMap v1.
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v1"));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
// Should return v1 since v1 specified.
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getValueAsString());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("12222", coding.getCode());
assertEquals("Target Code 12222", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithVersionedConceptMapUrl_NoVersion() {
String url = "http://url";
createConceptMap(url, "v1", "12222", "Target Code 12222");
createConceptMap(url, "v2", "13333", "Target Code 13333");
// Call translate with no ConceptMap version.
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
// Should return v2 since v2 is the most recently updated version.
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getValueAsString());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithVersionedConceptMapUrl_NoVersion_null_v1() {
String url = "http://url";
createConceptMap(url, null, "12222", "Target Code 12222"); // first version is null
createConceptMap(url, "v2", "13333", "Target Code 13333");
// Call translate with no ConceptMap version.
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
// Should return v2 since v2 is the most recently updated version.
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getValueAsString());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithVersionedConceptMapUrl_NoVersion_null_v2() {
String url = "http://url";
createConceptMap(url, "v1", "12222", "Target Code 12222");
createConceptMap(url, null, "13333", "Target Code 13333"); // second version is null
// Call translate with no ConceptMap version.
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
// Should return v2 since v2 is the most recently updated version.
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getValueAsString());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithConceptMap_WrongUrl_NoVersion() {
String url = "http://url";
createConceptMap(url, "v1", "12222", "Target Code 12222");
createConceptMap(url, "v2", "13333", "Target Code 13333");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType("http://invalid.url.com")); // no exsits url
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertFalse(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("No matches found!", ((StringType) param.getValue()).getValueAsString());
}
@Test
public void testTranslateWithReverseConceptMapUrlAndVersion() {
String url = "http://url";
createReverseConceptMap(url, "v1", "12222", "Source Code 12222");
createReverseConceptMap(url, "v2", "13333", "Source Code 13333");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
inParams.addParameter().setName("reverse").setValue(new BooleanType(true));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(2, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Source Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL, coding.getSystem());
assertEquals("Version 1", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithReverseConceptMapUrl_NoVersion() {
String url = "http://url";
createReverseConceptMap(url, "v1", "12222", "Source Code 12222");
createReverseConceptMap(url, "v2", "13333", "Source Code 13333");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
inParams.addParameter().setName("reverse").setValue(new BooleanType(true));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(2, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Source Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL, coding.getSystem());
assertEquals("Version 1", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithReverseConceptMapUrl_NoVersion_null_v1() {
String url = "http://url";
createReverseConceptMap(url, null, "12222", "Source Code 12222");
createReverseConceptMap(url, "v2", "13333", "Source Code 13333");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
inParams.addParameter().setName("reverse").setValue(new BooleanType(true));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(2, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Source Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL, coding.getSystem());
assertEquals("Version 1", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithReverseConceptMapUrl_NoVersion_null_v2() {
String url = "http://url";
createReverseConceptMap(url, "v1", "12222", "Source Code 12222");
createReverseConceptMap(url, null, "13333", "Source Code 13333");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
inParams.addParameter().setName("reverse").setValue(new BooleanType(true));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = ourClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(2, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Source Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL, coding.getSystem());
assertEquals("Version 1", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(url, ((UriType) part.getValue()).getValueAsString());
}
private void createConceptMap(String url, String version, String targetCode, String targetDisplay) {
ConceptMap conceptMap = new ConceptMap();
conceptMap.setUrl(url).setVersion(version).setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group1 = conceptMap.addGroup();
group1.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element1 = group1.addElement();
element1.setCode("11111").setDisplay("Source Code 11111");
TargetElementComponent target1 = element1.addTarget();
target1.setCode(targetCode).setDisplay(targetDisplay).setEquivalence(ConceptMapEquivalence.EQUAL);
IIdType conceptMapId = myConceptMapDao.create(conceptMap, mySrd).getId().toUnqualifiedVersionless();
conceptMap = myConceptMapDao.read(conceptMapId);
ourLog.info("ConceptMap: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
}
private void createReverseConceptMap(String url, String version, String sourceCode, String sourceDisplay) {
//- conceptMap1 v1
ConceptMap conceptMap = new ConceptMap();
conceptMap.setUrl(url).setVersion(version).setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group1 = conceptMap.addGroup();
group1.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element1 = group1.addElement();
element1.setCode(sourceCode).setDisplay(sourceDisplay);
TargetElementComponent target1 = element1.addTarget();
target1.setCode("11111").setDisplay("11111");
IIdType conceptMapId = myConceptMapDao.create(conceptMap, mySrd).getId().toUnqualifiedVersionless();
ConceptMap conceptMap1 = myConceptMapDao.read(conceptMapId);
ourLog.info("ConceptMap : \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap1));
}
} }

View File

@ -13,7 +13,6 @@ import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -37,7 +36,6 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator; import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionCallbackWithoutResult;
@ -137,6 +135,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
runInTransaction(() -> { runInTransaction(() -> {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(CS_URL); codeSystem.setUrl(CS_URL);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified();
@ -401,6 +400,28 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
} }
@Test
public void testExpandByUrlNoPreExpansion() throws Exception {
myDaoConfig.setPreExpandValueSets(false);
loadAndPersistCodeSystemAndValueSet();
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, Matchers.stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
}
@Test @Test
public void testExpandByUrlWithBogusUrl() throws Exception { public void testExpandByUrlWithBogusUrl() throws Exception {
loadAndPersistCodeSystemAndValueSet(); loadAndPersistCodeSystemAndValueSet();
@ -823,7 +844,7 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
codeSystem.setName("ACME Codes"); codeSystem.setName("ACME Codes");
codeSystem.setVersion("1.2.3.4"); codeSystem.setVersion("SYSTEM VERSION");
IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified(); IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified();
ResourceTable table = theResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new); ResourceTable table = theResourceTableDao.findById(id.getIdPartAsLong()).orElseThrow(IllegalStateException::new);

View File

@ -1,9 +1,17 @@
package ca.uhn.fhir.jpa.provider.r4; package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest; import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome; import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -18,18 +26,20 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
private static final String SYSTEM_PARENTCHILD = "http://parentchild"; private static final String SYSTEM_PARENTCHILD = "http://parentchild";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4CodeSystemTest.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4CodeSystemTest.class);
private Long parentChildCsId;
private IIdType myCsId;
private static final String CS_ACME_URL = "http://acme.org";
@BeforeEach @BeforeEach
@Transactional @Transactional
public void before02() throws IOException { public void before02() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
myCodeSystemDao.create(cs, mySrd); myCsId = myCodeSystemDao.create(cs, mySrd).getId().toUnqualifiedVersionless();
ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless();
CodeSystem parentChildCs = new CodeSystem(); CodeSystem parentChildCs = new CodeSystem();
parentChildCs.setUrl(SYSTEM_PARENTCHILD); parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setName("Parent Child CodeSystem");
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE); parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE); parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA); parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
@ -38,7 +48,8 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA"); parentA.addConcept().setCode("ChildAA").setDisplay("Child AA");
parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B"); parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B");
myCodeSystemDao.create(parentChildCs); DaoMethodOutcome parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCsId = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
} }
@ -254,7 +265,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
assertEquals("display", respParam.getParameter().get(2).getName()); assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Married", ((StringType) respParam.getParameter().get(2).getValue()).getValue()); assertEquals("Married", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName()); assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).booleanValue()); assertFalse(((BooleanType) respParam.getParameter().get(3).getValue()).booleanValue());
} }
@Test @Test
@ -325,6 +336,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("FOO")) .withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("FOO"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB")) .andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.execute(); .execute();
fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unknown code: [http://parentchild|FOO]", e.getMessage()); assertEquals("HTTP 400 Bad Request: Unknown code: [http://parentchild|FOO]", e.getMessage());
} }
@ -340,6 +352,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB")) .withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("FOO")) .andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("FOO"))
.execute(); .execute();
fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unknown code: [http://parentchild|FOO]", e.getMessage()); assertEquals("HTTP 400 Bad Request: Unknown code: [http://parentchild|FOO]", e.getMessage());
} }
@ -355,6 +368,7 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD + "A").setCode("ChildAA")) .withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD + "A").setCode("ChildAA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD + "B").setCode("ParentA")) .andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD + "B").setCode("ParentA"))
.execute(); .execute();
fail();
} catch (InvalidRequestException e) { } catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unable to test subsumption across different code systems", e.getMessage()); assertEquals("HTTP 400 Bad Request: Unable to test subsumption across different code systems", e.getMessage());
} }
@ -416,5 +430,527 @@ public class ResourceProviderR4CodeSystemTest extends BaseResourceProviderR4Test
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue()); assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
} }
@Test
public void testUpdateCodeSystemById() throws IOException {
CodeSystem initialCodeSystem = myClient.read().resource(CodeSystem.class).withId(parentChildCsId).execute();
assertEquals("Parent Child CodeSystem", initialCodeSystem.getName());
initialCodeSystem.setName("Updated Parent Child CodeSystem");
String encoded = myFhirCtx.newJsonParser().encodeResourceToString(initialCodeSystem);
HttpPut putRequest = new HttpPut(ourServerBase + "/CodeSystem/" + parentChildCsId);
putRequest.setEntity(new StringEntity(encoded, ContentType.parse("application/json+fhir")));
CloseableHttpResponse resp = ourHttpClient.execute(putRequest);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(resp);
}
CodeSystem updatedCodeSystem = myClient.read().resource(CodeSystem.class).withId(parentChildCsId).execute();
assertEquals("Updated Parent Child CodeSystem", updatedCodeSystem.getName());
}
@Test
public void testValidateCodeFoundByCode() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeNotFoundByCode() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("code").setValue(new CodeType("8452-5-a"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertFalse(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Unknown code {http://acme.org}8452-5-a", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeMatchDisplay() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
inParams.addParameter().setName("display").setValue(new StringType("Systolic blood pressure.inspiration - expiration"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeNotMatchDisplay() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
inParams.addParameter().setName("display").setValue(new StringType("Old Systolic blood pressure.inspiration - expiration"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertFalse(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Unknown code {http://acme.org}8452-5 - Concept Display : Old Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeWithoutUrl() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
try {
myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Either CodeSystem ID or CodeSystem identifier must be provided. Unable to validate.",e.getMessage());
}
}
@Test
public void testValidateCodeFoundByCodeWithId() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
Parameters respParam = myClient.operation().onInstance(myCsId).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeWithoutCodeOrCodingOrCodeableConcept() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("display").setValue(new StringType("Systolic blood pressure.inspiration - expiration"));
try {
myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: No code, coding, or codeableConcept provided to validate.",e.getMessage());
}
}
@Test
public void testValidateCodeWithCodeAndCoding() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-1")));
try {
myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: $validate-code can only validate (code) OR (coding) OR (codeableConcept)",e.getMessage());
}
}
@Test
public void testValidateCodeFoundByCodingWithUrlNotMatch() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-5").setSystem("http://url2")));
try {
myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Coding.system 'http://url2' does not equal with CodeSystem.url 'http://acme.org'. Unable to validate.",e.getMessage());
}
}
@Test
public void testValidateCodeFoundByCoding() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-5")));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodingWithSystem() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-5").setSystem(CS_ACME_URL)));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodingUrlNotMatch() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-5").setSystem("http://url2")));
try {
myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Coding.system 'http://url2' does not equal with CodeSystem.url 'http://acme.org'. Unable to validate.",e.getMessage());
}
}
@Test
public void testValidateCodeFoundByCodingWithDisplay() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-5").setDisplay("Systolic blood pressure.inspiration - expiration")));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeNotFoundByCoding() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("coding").setValue((new Coding().setCode("8452-5-a")));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertFalse(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Unknown code {http://acme.org}8452-5-a", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeableConcept() {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeableConceptWithSystem() {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5").setSystem(CS_ACME_URL);
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeableConceptWithDisplay() {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure.inspiration - expiration");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeNotFoundByCodeableConcept() {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5-a");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertFalse(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Unknown code {http://acme.org}8452-5-a", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeableConceptUrlNotMatch() throws Exception {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5").setSystem("http://url2").setDisplay("Systolic blood pressure.inspiration - expiration");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
try {
myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Coding.system 'http://url2' does not equal with CodeSystem.url 'http://acme.org'. Unable to validate.",e.getMessage());
}
}
@Test
public void testValidateCodeFoundByCodeableConceptWithMultipleMatchedEntries() throws Exception {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure.inspiration - expiration");
cc.addCoding().setCode("8451-7").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure--inspiration");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeableConceptWithMultipleMatchedFirstEntry() throws Exception {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure.inspiration - expiration");
cc.addCoding().setCode("8451-7-a").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure--inspiration");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeFoundByCodeableConceptWithMultipleMatchedSecondEntry() throws Exception {
CodeableConcept cc = new CodeableConcept();
cc.addCoding().setCode("8452-5-a").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure.inspiration - expiration");
cc.addCoding().setCode("8451-7").setSystem(CS_ACME_URL).setDisplay("Systolic blood pressure--inspiration");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CS_ACME_URL));
inParams.addParameter().setName("codeableConcept").setValue(cc);
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure--inspiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeWithUrlAndVersion_v1() {
String url = "http://url";
createCodeSystem(url, "v1", "1", "Code v1 display");
createCodeSystem(url, "v2", "1", "Code v2 display");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("version").setValue(new StringType("v1"));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParam));
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Code v1 display", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeWithUrlAndVersion_v2() {
String url = "http://url";
createCodeSystem(url, "v1", "1", "Code v1 display");
createCodeSystem(url, "v2", "1", "Code v2 display");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("version").setValue(new StringType("v2"));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParam));
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Code v2 display", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeWithUrlAndVersion_noVersion() {
String url = "http://url";
createCodeSystem(url, "v1", "1", "Code v1 display");
createCodeSystem(url, "v2", "1", "Code v2 display");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParam));
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Code v2 display", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeWithUrlAndVersion_noVersion_null_v1() {
String url = "http://url";
createCodeSystem(url, null, "1", "Code v1 display");
createCodeSystem(url, "v2", "1", "Code v2 display");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParam));
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Code v2 display", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testValidateCodeWithUrlAndVersion_noVersion_null_v2() {
String url = "http://url";
createCodeSystem(url, "v1", "1", "Code v1 display");
createCodeSystem(url, null, "1", "Code v2 display");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParam));
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Code v2 display", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
private void createCodeSystem(String url, String version, String code, String display) {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(url).setVersion(version);
CodeSystem.ConceptDefinitionComponent concept1 = codeSystem.addConcept();
concept1.setCode("1000").setDisplay("Code Dispaly 1000");
CodeSystem.ConceptDefinitionComponent concept = codeSystem.addConcept();
concept.setCode(code).setDisplay(display);
CodeSystem.ConceptDefinitionComponent concept2 = codeSystem.addConcept();
concept2.setCode("2000").setDisplay("Code Dispaly 2000");
ourLog.info("CodeSystem: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(codeSystem));
myCodeSystemDao.create(codeSystem, mySrd);
}
} }

View File

@ -0,0 +1,822 @@
package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Enumerations;
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.codesystems.ConceptSubsumptionOutcome;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
public class ResourceProviderR4CodeSystemVersionedTest extends BaseResourceProviderR4Test {
private static final String SYSTEM_PARENTCHILD = "http://parentchild";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4CodeSystemVersionedTest.class);
private long parentChildCs1Id;
private long parentChildCs2Id;
@BeforeEach
@Transactional
public void before02() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
cs.setVersion("1");
for(CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent : cs.getConcept()) {
conceptDefinitionComponent.setDisplay(conceptDefinitionComponent.getDisplay() + " v1");
}
myCodeSystemDao.create(cs, mySrd);
cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
cs.setVersion("2");
for(CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent : cs.getConcept()) {
conceptDefinitionComponent.setDisplay(conceptDefinitionComponent.getDisplay() + " v2");
}
myCodeSystemDao.create(cs, mySrd);
CodeSystem parentChildCs = new CodeSystem();
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setVersion("1");
parentChildCs.setName("Parent Child CodeSystem 1");
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA");
parentA.addConcept().setCode("ParentC").setDisplay("Parent C");
parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B");
DaoMethodOutcome parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCs1Id = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
parentChildCs = new CodeSystem();
parentChildCs.setVersion("2");
parentChildCs.setName("Parent Child CodeSystem 2");
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A v2");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA v2");
parentA.addConcept().setCode("ParentB").setDisplay("Parent B v2");
parentChildCs.addConcept().setCode("ParentC").setDisplay("Parent C v2");
parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCs2Id = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
}
@Test
public void testLookupOnExternalCodeMultiVersion() {
ResourceProviderR4ValueSetVersionedTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermCodeSystemStorageSvc, mySrd, "1");
ResourceProviderR4ValueSetVersionedTest.createExternalCs(myCodeSystemDao, myResourceTableDao, myTermCodeSystemStorageSvc, mySrd, "2");
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A1", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("1"))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("1"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A1", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("SYSTEM NAME", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// With HTTP GET
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ParentA"))
.andParameter("system", new UriType(FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM))
.andParameter("version", new StringType("2"))
.useHttpGet()
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("SYSTEM NAME"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals(("2"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Parent A2", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInCode() {
// First test with no version specified (should return the one and only version defined).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Repeat with version specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
.andParameter("version", new StringType("2.9"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInNonexistentVersion() {
try {
myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://hl7.org/fhir/v2/0203"))
.andParameter("version", new StringType("2.8"))
.execute();
fail();
} catch (ResourceNotFoundException e) {
ourLog.info("Lookup failed as expected");
}
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedCode() {
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v1"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedNonExistentVersion() {
try {
myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("3"))
.execute();
fail();
} catch (ResourceNotFoundException e) {
ourLog.info("Lookup failed as expected");
}
}
@Test
public void testLookupOperationByCoding() {
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v1"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumedby() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Disjoint() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentB"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentA"))
.andParameter("codeB", new CodeType("ParentC"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_MismatchedCsVersions() {
try {
myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.execute();
fail();
} catch (InvalidRequestException e) {
assertEquals("HTTP 400 Bad Request: Unable to test subsumption across different code system versions", e.getMessage());
}
}
@Test
public void testSubsumesOnCodings_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Subsumedby() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMEDBY.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Disjoint() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("1"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentB").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA").setVersion("2"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentC").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.NOTSUBSUMED.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testUpdateCodeSystemById() throws IOException {
CodeSystem initialCodeSystem = myClient.read().resource(CodeSystem.class).withId(parentChildCs1Id).execute();
assertEquals("Parent Child CodeSystem 1", initialCodeSystem.getName());
initialCodeSystem.setName("Updated Parent Child CodeSystem 1");
String encoded = myFhirCtx.newJsonParser().encodeResourceToString(initialCodeSystem);
HttpPut putRequest = new HttpPut(ourServerBase + "/CodeSystem/" + parentChildCs1Id);
putRequest.setEntity(new StringEntity(encoded, ContentType.parse("application/json+fhir")));
CloseableHttpResponse resp = ourHttpClient.execute(putRequest);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(resp);
}
CodeSystem updatedCodeSystem = myClient.read().resource(CodeSystem.class).withId(parentChildCs1Id).execute();
assertEquals("Updated Parent Child CodeSystem 1", updatedCodeSystem.getName());
initialCodeSystem = myClient.read().resource(CodeSystem.class).withId(parentChildCs2Id).execute();
assertEquals("Parent Child CodeSystem 2", initialCodeSystem.getName());
initialCodeSystem.setName("Updated Parent Child CodeSystem 2");
encoded = myFhirCtx.newJsonParser().encodeResourceToString(initialCodeSystem);
putRequest = new HttpPut(ourServerBase + "/CodeSystem/" + parentChildCs2Id);
putRequest.setEntity(new StringEntity(encoded, ContentType.parse("application/json+fhir")));
resp = ourHttpClient.execute(putRequest);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(resp);
}
updatedCodeSystem = myClient.read().resource(CodeSystem.class).withId(parentChildCs2Id).execute();
assertEquals("Updated Parent Child CodeSystem 2", updatedCodeSystem.getName());
}
}

View File

@ -1,16 +1,31 @@
package ca.uhn.fhir.jpa.provider.r4; package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.rest.api.MethodOutcome; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.ConceptMap.ConceptMapGroupComponent;
import org.hl7.fhir.r4.model.ConceptMap.SourceElementComponent;
import org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent; import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.*; import ca.uhn.fhir.rest.api.MethodOutcome;
public class ResourceProviderR4ConceptMapTest extends BaseResourceProviderR4Test { public class ResourceProviderR4ConceptMapTest extends BaseResourceProviderR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR4ConceptMapTest.class); private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR4ConceptMapTest.class);
@ -870,6 +885,90 @@ public class ResourceProviderR4ConceptMapTest extends BaseResourceProviderR4Test
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString()); assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
} }
@Test
public void testTranslateWithConceptMapUrlAndVersion() {
//- conceptMap1 v1
ConceptMap conceptMap1 = new ConceptMap();
conceptMap1.setUrl(CM_URL).setVersion("v1").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group1 = conceptMap1.addGroup();
group1.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element1 = group1.addElement();
element1.setCode("11111").setDisplay("Source Code 11111");
TargetElementComponent target1 = element1.addTarget();
target1.setCode("12222").setDisplay("Target Code 12222").setEquivalence(ConceptMapEquivalence.EQUAL);
IIdType conceptMapId1 = myConceptMapDao.create(conceptMap1, mySrd).getId().toUnqualifiedVersionless();
conceptMap1 = myConceptMapDao.read(conceptMapId1);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap1));
//- conceptMap1 v2
ConceptMap conceptMap2 = new ConceptMap();
conceptMap2.setUrl(CM_URL).setVersion("v2").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group2 = conceptMap2.addGroup();
group2.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element2 = group2.addElement();
element2.setCode("11111").setDisplay("Source Code 11111");
TargetElementComponent target2 = element2.addTarget();
target2.setCode("13333").setDisplay("Target Code 13333").setEquivalence(ConceptMapEquivalence.EQUAL);
IIdType conceptMapId2 = myConceptMapDao.create(conceptMap2, mySrd).getId().toUnqualifiedVersionless();
conceptMap2 = myConceptMapDao.read(conceptMapId2);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap2));
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CM_URL));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = myClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getCode());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
}
@Test @Test
public void testTranslateWithInstance() { public void testTranslateWithInstance() {
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId); ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
@ -1621,6 +1720,89 @@ public class ResourceProviderR4ConceptMapTest extends BaseResourceProviderR4Test
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString()); assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
} }
@Test
public void testTranslateWithReverseConceptMapUrlAndVersion() {
//- conceptMap1 v1
ConceptMap conceptMap1 = new ConceptMap();
conceptMap1.setUrl(CM_URL).setVersion("v1").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group1 = conceptMap1.addGroup();
group1.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element1 = group1.addElement();
element1.setCode("12222").setDisplay("Source Code 12222");
TargetElementComponent target1 = element1.addTarget();
target1.setCode("11111").setDisplay("11111").setEquivalence(ConceptMapEquivalence.EQUAL);
IIdType conceptMapId1 = myConceptMapDao.create(conceptMap1, mySrd).getId().toUnqualifiedVersionless();
conceptMap1 = myConceptMapDao.read(conceptMapId1);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap1));
//- conceptMap1 v2
ConceptMap conceptMap2 = new ConceptMap();
conceptMap2.setUrl(CM_URL).setVersion("v2").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group2 = conceptMap2.addGroup();
group2.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element2 = group2.addElement();
element2.setCode("13333").setDisplay("Source Code 13333");
TargetElementComponent target2 = element2.addTarget();
target2.setCode("11111").setDisplay("Target Code 11111").setEquivalence(ConceptMapEquivalence.EQUAL);
IIdType conceptMapId2 = myConceptMapDao.create(conceptMap2, mySrd).getId().toUnqualifiedVersionless();
conceptMap2 = myConceptMapDao.read(conceptMapId2);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap2));
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CM_URL));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
inParams.addParameter().setName("reverse").setValue(new BooleanType(true));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = myClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equal", ((CodeType) part.getValue()).getCode());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Source Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL, coding.getSystem());
assertEquals("Version 1", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
}
@Test @Test
public void testTranslateWithReverseAndInstance() { public void testTranslateWithReverseAndInstance() {
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId); ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);

View File

@ -31,6 +31,7 @@ import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.IntegerType; import org.hl7.fhir.r4.model.IntegerType;
@ -43,6 +44,8 @@ import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
import org.hl7.fhir.r4.model.codesystems.HttpVerb; import org.hl7.fhir.r4.model.codesystems.HttpVerb;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.transaction.TransactionStatus; 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;
@ -54,12 +57,14 @@ import java.util.Optional;
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM; import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_CODE_SYSTEM;
import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_VALUE_SET; import static ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest.URL_MY_VALUE_SET;
import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.containsStringIgnoringCase; import static org.hamcrest.Matchers.containsStringIgnoringCase;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder; import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -244,7 +249,10 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
myDaoConfig.setPreExpandValueSets(true); myDaoConfig.setPreExpandValueSets(true);
loadAndPersistCodeSystemAndValueSet(); loadAndPersistCodeSystemAndValueSet();
await().until(() -> clearDeferredStorageQueue());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
Slice<TermValueSet> page = myTermValueSetDao.findByExpansionStatus(PageRequest.of(0, 10), TermValueSetPreExpansionStatusEnum.EXPANDED);
assertEquals(1, page.getContent().size());
Parameters respParam = myClient Parameters respParam = myClient
.operation() .operation()
@ -296,7 +304,10 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
myDaoConfig.setPreExpandValueSets(true); myDaoConfig.setPreExpandValueSets(true);
loadAndPersistCodeSystemAndValueSet(); loadAndPersistCodeSystemAndValueSet();
await().until(() -> clearDeferredStorageQueue());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
Slice<TermValueSet> page = myTermValueSetDao.findByExpansionStatus(PageRequest.of(0, 10), TermValueSetPreExpansionStatusEnum.EXPANDED);
assertEquals(1, page.getContent().size());
Parameters respParam = myClient Parameters respParam = myClient
.operation() .operation()
@ -333,6 +344,27 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
} }
@Test
public void testExpandByUrlNoPreExpand() throws Exception {
myDaoConfig.setPreExpandValueSets(false);
loadAndPersistCodeSystemAndValueSet();
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
}
@Test @Test
public void testExpandByUrlWithBogusUrl() throws Exception { public void testExpandByUrlWithBogusUrl() throws Exception {
loadAndPersistCodeSystemAndValueSet(); loadAndPersistCodeSystemAndValueSet();
@ -355,7 +387,10 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
myDaoConfig.setPreExpandValueSets(true); myDaoConfig.setPreExpandValueSets(true);
loadAndPersistCodeSystemAndValueSet(); loadAndPersistCodeSystemAndValueSet();
await().until(() -> clearDeferredStorageQueue());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
Slice<TermValueSet> page = myTermValueSetDao.findByExpansionStatus(PageRequest.of(0, 10), TermValueSetPreExpansionStatusEnum.EXPANDED);
assertEquals(1, page.getContent().size());
Parameters respParam = myClient Parameters respParam = myClient
.operation() .operation()
@ -737,6 +772,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
String initialValueSetName = valueSet.getName(); String initialValueSetName = valueSet.getName();
validateTermValueSetNotExpanded(initialValueSetName); validateTermValueSetNotExpanded(initialValueSetName);
await().until(() -> clearDeferredStorageQueue());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
validateTermValueSetExpandedAndChildren(initialValueSetName, codeSystem); validateTermValueSetExpandedAndChildren(initialValueSetName, codeSystem);
@ -766,6 +802,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
String initialValueSetName = valueSet.getName(); String initialValueSetName = valueSet.getName();
validateTermValueSetNotExpanded(initialValueSetName); validateTermValueSetNotExpanded(initialValueSetName);
await().until(() -> clearDeferredStorageQueue());
myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
validateTermValueSetExpandedAndChildren(initialValueSetName, codeSystem); validateTermValueSetExpandedAndChildren(initialValueSetName, codeSystem);
@ -1051,6 +1088,41 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
} }
@Test
public void testValidateCodeOperationByCoding() throws Exception {
loadAndPersistCodeSystemAndValueSet();
Coding codingToValidate = new Coding("http://acme.org", "8495-4", "Systolic blood pressure 24 hour minimum");
// With correct system version specified. Should pass.
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("validate-code")
.withParameter(Parameters.class, "coding", codingToValidate)
.andParameter("url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
}
private boolean clearDeferredStorageQueue() {
if(!myTerminologyDeferredStorageSvc.isStorageQueueEmpty()) {
myTerminologyDeferredStorageSvc.saveAllDeferred();
return false;
} else {
return true;
}
}
@AfterEach @AfterEach
public void afterResetPreExpansionDefault() { public void afterResetPreExpansionDefault() {
myDaoConfig.setPreExpandValueSets(new DaoConfig().isPreExpandValueSets()); myDaoConfig.setPreExpandValueSets(new DaoConfig().isPreExpandValueSets());
@ -1059,6 +1131,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test {
public static CodeSystem createExternalCs(IFhirResourceDao<CodeSystem> theCodeSystemDao, IResourceTableDao theResourceTableDao, ITermCodeSystemStorageSvc theTermCodeSystemStorageSvc, ServletRequestDetails theRequestDetails) { public static CodeSystem createExternalCs(IFhirResourceDao<CodeSystem> theCodeSystemDao, IResourceTableDao theResourceTableDao, ITermCodeSystemStorageSvc theTermCodeSystemStorageSvc, ServletRequestDetails theRequestDetails) {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified(); IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified();

View File

@ -106,7 +106,7 @@ public class TerminologyUploaderProviderR4Test extends BaseResourceProviderR4Tes
ourLog.info(resp); ourLog.info(resp);
assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1)); assertThat(((IntegerType) respParam.getParameter().get(1).getValue()).getValue(), greaterThan(1));
assertThat(((Reference) respParam.getParameter().get(2).getValue()).getReference(), matchesPattern("CodeSystem\\/[a-zA-Z0-9]+")); assertThat(((Reference) respParam.getParameter().get(2).getValue()).getReference(), matchesPattern("CodeSystem\\/[a-zA-Z0-9\\.\\-]+"));
/* /*
* Try uploading a second time * Try uploading a second time

View File

@ -0,0 +1,241 @@
package ca.uhn.fhir.jpa.provider.r5;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
import org.hl7.fhir.r5.model.Enumerations;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.UriType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
public class ResourceProviderR5CodeSystemTest extends BaseResourceProviderR5Test {
private static final String SYSTEM_PARENTCHILD = "http://parentchild";
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR5CodeSystemTest.class);
private Long parentChildCsId;
private IIdType myCsId;
@BeforeEach
@Transactional
public void before02() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
myCsId = myCodeSystemDao.create(cs, mySrd).getId().toUnqualifiedVersionless();
CodeSystem parentChildCs = new CodeSystem();
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setName("Parent Child CodeSystem");
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA");
parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B");
DaoMethodOutcome parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCsId = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
}
@Test
public void testValidateCodeWithUrlAndVersion_v1() {
String url = "http://url";
createCodeSystem(url, "v1", "1", "Code v1 display");
createCodeSystem(url, "v2", "1", "Code v2 display");
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(url));
inParams.addParameter().setName("version").setValue(new StringType("v1"));
inParams.addParameter().setName("code").setValue(new CodeType("1"));
inParams.addParameter().setName("display").setValue(new StringType("Code v1 display"));
Parameters respParam = myClient.operation().onType(CodeSystem.class).named("validate-code").withParameters(inParams).execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParam));
assertEquals(true, ((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Code v1 display", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedCode() {
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(1).getName());
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(2).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumes() {
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ChildAA"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
@Test
public void testSubsumesOnCodings_Subsumes() {
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codingA", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ChildAA"))
.andParameter("codingB", new Coding().setSystem(SYSTEM_PARENTCHILD).setCode("ParentA"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
private void createCodeSystem(String url, String version, String code, String display) {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(url).setVersion(version);
ConceptDefinitionComponent concept1 = codeSystem.addConcept();
concept1.setCode("1000").setDisplay("Code Dispaly 1000");
ConceptDefinitionComponent concept = codeSystem.addConcept();
concept.setCode(code).setDisplay(display);
ConceptDefinitionComponent concept2 = codeSystem.addConcept();
concept2.setCode("2000").setDisplay("Code Dispaly 2000");
ourLog.info("CodeSystem: \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(codeSystem));
myCodeSystemDao.create(codeSystem, mySrd);
}
@Test
public void testLookupOperationByCoding() throws IOException {
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(1).getName());
assertEquals(("Systolic blood pressure--expiration"), ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(2).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(2).getValue()).getValue());
}
@Test
public void testValidateCodeFoundByCodeWithId() {
Parameters inParams = new Parameters();
inParams.addParameter().setName("code").setValue(new CodeType("8452-5"));
Parameters respParam = myClient.operation().onInstance(myCsId).named("validate-code").withParameters(inParams).execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertTrue(((BooleanType) respParam.getParameter().get(0).getValue()).booleanValue());
assertEquals("Systolic blood pressure.inspiration - expiration", ((StringType) respParam.getParameter().get(1).getValue()).getValueAsString());
}
@Test
public void testLookupOperationByCodeAndSystemBuiltInCode() {
// First test with no version specified (should return the one and only version defined).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Repeat with version specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
.andParameter("version", new StringType("2.9"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
}

View File

@ -0,0 +1,273 @@
package ca.uhn.fhir.jpa.provider.r5;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import org.hl7.fhir.r4.model.codesystems.ConceptSubsumptionOutcome;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.UriType;
import org.hl7.fhir.r5.model.Enumerations;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ResourceProviderR5CodeSystemVersionedTest extends BaseResourceProviderR5Test {
private static final String SYSTEM_PARENTCHILD = "http://parentchild";
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR5CodeSystemVersionedTest.class);
private long parentChildCs1Id;
private long parentChildCs2Id;
@BeforeEach
@Transactional
public void before02() throws IOException {
CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
cs.setVersion("1");
for(CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent : cs.getConcept()) {
conceptDefinitionComponent.setDisplay(conceptDefinitionComponent.getDisplay() + " v1");
}
myCodeSystemDao.create(cs, mySrd);
cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
cs.setVersion("2");
for(CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent : cs.getConcept()) {
conceptDefinitionComponent.setDisplay(conceptDefinitionComponent.getDisplay() + " v2");
}
myCodeSystemDao.create(cs, mySrd);
CodeSystem parentChildCs = new CodeSystem();
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setVersion("1");
parentChildCs.setName("Parent Child CodeSystem 1");
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA");
parentA.addConcept().setCode("ParentC").setDisplay("Parent C");
parentChildCs.addConcept().setCode("ParentB").setDisplay("Parent B");
DaoMethodOutcome parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCs1Id = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
parentChildCs = new CodeSystem();
parentChildCs.setVersion("2");
parentChildCs.setName("Parent Child CodeSystem 2");
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A v2");
parentA.addConcept().setCode("ChildAA").setDisplay("Child AA v2");
parentA.addConcept().setCode("ParentB").setDisplay("Parent B v2");
parentChildCs.addConcept().setCode("ParentC").setDisplay("Parent C v2");
parentChildCsOutcome = myCodeSystemDao.create(parentChildCs);
parentChildCs2Id = ((ResourceTable)parentChildCsOutcome.getEntity()).getId();
}
@Test
public void testLookupOperationByCoding() {
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 1
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v1"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version set to 2
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "coding", new Coding().setSystem("http://acme.org").setCode("8450-9").setVersion("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testLookupOperationByCodeAndSystemUserDefinedCode() {
// First test with no version specified (should return from last version created)
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 1 specified.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("1", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v1"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
// Test with version 2 specified
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named("lookup")
.withParameter(Parameters.class, "code", new CodeType("8450-9"))
.andParameter("system", new UriType("http://acme.org"))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals("name", respParam.getParameter().get(0).getName());
assertEquals(("ACME Codes"), ((StringType) respParam.getParameter().get(0).getValue()).getValue());
assertEquals("version", respParam.getParameter().get(1).getName());
assertEquals("2", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
assertEquals("display", respParam.getParameter().get(2).getName());
assertEquals(("Systolic blood pressure--expiration v2"), ((StringType) respParam.getParameter().get(2).getValue()).getValue());
assertEquals("abstract", respParam.getParameter().get(3).getName());
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
}
@Test
public void testSubsumesOnCodes_Subsumes() {
// First test with no version specified (should return result for last version created).
Parameters respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.execute();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 1.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentC"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("1"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
// Test with version set to 2.
respParam = myClient
.operation()
.onType(CodeSystem.class)
.named(JpaConstants.OPERATION_SUBSUMES)
.withParameter(Parameters.class, "codeA", new CodeType("ParentB"))
.andParameter("codeB", new CodeType("ParentA"))
.andParameter("system", new UriType(SYSTEM_PARENTCHILD))
.andParameter("version", new StringType("2"))
.execute();
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
ourLog.info(resp);
assertEquals(1, respParam.getParameter().size());
assertEquals("outcome", respParam.getParameter().get(0).getName());
assertEquals(ConceptSubsumptionOutcome.SUBSUMES.toCode(), ((CodeType) respParam.getParameter().get(0).getValue()).getValue());
}
}

View File

@ -0,0 +1,190 @@
package ca.uhn.fhir.jpa.provider.r5;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.UriType;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ResourceProviderR5ConceptMapTest extends BaseResourceProviderR5Test {
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR5ConceptMapTest.class);
@Test
public void testTranslateWithConceptMapUrlAndVersion() {
//- conceptMap1 v1
ConceptMap conceptMap1 = new ConceptMap();
conceptMap1.setUrl(CM_URL).setVersion("v1").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group1 = conceptMap1.addGroup();
group1.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element1 = group1.addElement();
element1.setCode("11111").setDisplay("Source Code 11111");
TargetElementComponent target1 = element1.addTarget();
target1.setCode("12222").setDisplay("Target Code 12222");
IIdType conceptMapId1 = myConceptMapDao.create(conceptMap1, mySrd).getId().toUnqualifiedVersionless();
conceptMap1 = myConceptMapDao.read(conceptMapId1);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap1));
//- conceptMap1 v2
ConceptMap conceptMap2 = new ConceptMap();
conceptMap2.setUrl(CM_URL).setVersion("v2").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group2 = conceptMap2.addGroup();
group2.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element2 = group2.addElement();
element2.setCode("11111").setDisplay("Source Code 11111");
TargetElementComponent target2 = element2.addTarget();
target2.setCode("13333").setDisplay("Target Code 13333");
IIdType conceptMapId2 = myConceptMapDao.create(conceptMap2, mySrd).getId().toUnqualifiedVersionless();
conceptMap2 = myConceptMapDao.read(conceptMapId2);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap2));
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CM_URL));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("system").setValue(new UriType(CS_URL));
inParams.addParameter().setName("targetsystem").setValue(new UriType(CS_URL_2));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = myClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(2, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Target Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL_2, coding.getSystem());
assertEquals("Version 2", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
}
@Test
public void testTranslateWithReverseConceptMapUrlAndVersion() {
//- conceptMap1 v1
ConceptMap conceptMap1 = new ConceptMap();
conceptMap1.setUrl(CM_URL).setVersion("v1").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group1 = conceptMap1.addGroup();
group1.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element1 = group1.addElement();
element1.setCode("12222").setDisplay("Source Code 12222");
TargetElementComponent target1 = element1.addTarget();
target1.setCode("11111").setDisplay("11111").setRelationship(ConceptMapRelationship.EQUIVALENT);
IIdType conceptMapId1 = myConceptMapDao.create(conceptMap1, mySrd).getId().toUnqualifiedVersionless();
conceptMap1 = myConceptMapDao.read(conceptMapId1);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap1));
//- conceptMap1 v2
ConceptMap conceptMap2 = new ConceptMap();
conceptMap2.setUrl(CM_URL).setVersion("v2").setSource(new UriType(VS_URL)).setTarget(new UriType(VS_URL_2));
ConceptMapGroupComponent group2 = conceptMap2.addGroup();
group2.setSource(CS_URL).setSourceVersion("Version 1").setTarget(CS_URL_2).setTargetVersion("Version 2");
SourceElementComponent element2 = group2.addElement();
element2.setCode("13333").setDisplay("Source Code 13333");
TargetElementComponent target2 = element2.addTarget();
target2.setCode("11111").setDisplay("Target Code 11111").setRelationship(ConceptMapRelationship.EQUIVALENT);
IIdType conceptMapId2 = myConceptMapDao.create(conceptMap2, mySrd).getId().toUnqualifiedVersionless();
conceptMap2 = myConceptMapDao.read(conceptMapId2);
ourLog.info("ConceptMap: 2 \n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap2));
Parameters inParams = new Parameters();
inParams.addParameter().setName("url").setValue(new UriType(CM_URL));
inParams.addParameter().setName("conceptMapVersion").setValue(new StringType("v2"));
inParams.addParameter().setName("code").setValue(new CodeType("11111"));
inParams.addParameter().setName("reverse").setValue(new BooleanType(true));
ourLog.info("Request Parameters:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inParams));
Parameters respParams = myClient
.operation()
.onType(ConceptMap.class)
.named("translate")
.withParameters(inParams)
.execute();
ourLog.info("Response Parameters\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respParams));
ParametersParameterComponent param = getParameterByName(respParams, "result");
assertTrue(((BooleanType) param.getValue()).booleanValue());
param = getParameterByName(respParams, "message");
assertEquals("Matches found!", ((StringType) param.getValue()).getValueAsString());
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
param = getParametersByName(respParams, "match").get(0);
assertEquals(3, param.getPart().size());
ParametersParameterComponent part = getPartByName(param, "equivalence");
assertEquals("equivalent", ((CodeType) part.getValue()).getCode());
part = getPartByName(param, "concept");
Coding coding = (Coding) part.getValue();
assertEquals("13333", coding.getCode());
assertEquals("Source Code 13333", coding.getDisplay());
assertFalse(coding.getUserSelected());
assertEquals(CS_URL, coding.getSystem());
assertEquals("Version 1", coding.getVersion());
part = getPartByName(param, "source");
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
}
}

View File

@ -457,6 +457,27 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
} }
@Test
public void testExpandByUrlNoPreExpand() throws Exception {
myDaoConfig.setPreExpandValueSets(false);
loadAndPersistCodeSystemAndValueSet(HTTPVerb.POST);
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
}
@Test @Test
public void testExpandByUrlWithBogusUrl() throws Exception { public void testExpandByUrlWithBogusUrl() throws Exception {
loadAndPersistCodeSystemAndValueSet(HTTPVerb.POST); loadAndPersistCodeSystemAndValueSet(HTTPVerb.POST);
@ -1405,6 +1426,7 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
public static CodeSystem createExternalCs(IFhirResourceDao<CodeSystem> theCodeSystemDao, IResourceTableDao theResourceTableDao, ITermCodeSystemStorageSvc theTermCodeSystemStorageSvc, ServletRequestDetails theRequestDetails) { public static CodeSystem createExternalCs(IFhirResourceDao<CodeSystem> theCodeSystemDao, IResourceTableDao theResourceTableDao, ITermCodeSystemStorageSvc theTermCodeSystemStorageSvc, ServletRequestDetails theRequestDetails) {
CodeSystem codeSystem = new CodeSystem(); CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setUrl(URL_MY_CODE_SYSTEM);
codeSystem.setVersion("SYSTEM VERSION");
codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT);
IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified(); IIdType id = theCodeSystemDao.create(codeSystem, theRequestDetails).getId().toUnqualified();

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