From a6cbf7eebdbccc12eed369b0c84d43310f582303 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Tue, 6 Apr 2021 17:36:54 -0400 Subject: [PATCH] Add support for hierarchycal valueset expansion (#2525) * Add support for hierarchycal valueset expansion * Add changelog * Add tests * Cleanup * Test fix * Test fixes --- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- .../support/ValueSetExpansionOptions.java | 19 ++ hapi-fhir-bom/pom.xml | 4 +- hapi-fhir-cli/hapi-fhir-cli-api/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- hapi-fhir-converter/pom.xml | 2 +- hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-docs/pom.xml | 8 +- .../5_4_0/2525-hierarchical-expansion.yaml | 6 + hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jaxrsserver-example/pom.xml | 2 +- hapi-fhir-jpaserver-api/pom.xml | 2 +- .../jpa/api/dao/IFhirResourceDaoValueSet.java | 13 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- .../jpa/dao/FhirResourceDaoValueSetDstu2.java | 59 +++--- .../dstu3/FhirResourceDaoValueSetDstu3.java | 33 +-- .../jpa/dao/r4/FhirResourceDaoValueSetR4.java | 47 +--- .../jpa/dao/r5/FhirResourceDaoValueSetR5.java | 33 +-- .../jpa/entity/ITermValueSetConceptView.java | 47 ++++ .../ca/uhn/fhir/jpa/entity/TermConcept.java | 2 +- .../fhir/jpa/entity/TermValueSetConcept.java | 49 ++++- .../jpa/entity/TermValueSetConceptView.java | 77 +++++-- .../entity/TermValueSetConceptViewOracle.java | 75 +++++-- .../BaseJpaResourceProviderValueSetDstu2.java | 8 +- .../BaseJpaResourceProviderValueSetDstu3.java | 72 ++----- .../r4/BaseJpaResourceProviderValueSetR4.java | 110 +++++----- .../r5/BaseJpaResourceProviderValueSetR5.java | 73 ++----- .../fhir/jpa/term/BaseTermReadSvcImpl.java | 200 +++++------------- .../jpa/term/IValueSetConceptAccumulator.java | 8 +- .../jpa/term/ValueSetConceptAccumulator.java | 14 +- ...ansionComponentWithConceptAccumulator.java | 65 ++++-- .../uhn/fhir/jpa/term/api/ITermReadSvc.java | 4 +- .../FhirResourceDaoValueSetDstu2Test.java | 13 +- .../FhirResourceDaoDstu3TerminologyTest.java | 149 +++++++------ .../FhirResourceDaoDstu3ValueSetTest.java | 9 +- ...esourceDaoR4SearchWithElasticSearchIT.java | 7 +- .../r4/FhirResourceDaoR4TerminologyTest.java | 15 +- .../dao/r4/FhirResourceDaoR4ValidateTest.java | 6 +- .../dao/r4/FhirResourceDaoR4ValueSetTest.java | 3 +- .../dao/r5/FhirResourceDaoR5ValueSetTest.java | 3 +- .../ResourceProviderDstu2ValueSetTest.java | 98 +++++---- ...rceProviderR4ValueSetNoVerCSNoVerTest.java | 166 ++++++++++++++- .../term/ValueSetConceptAccumulatorTest.java | 2 +- .../ValueSetExpansionR4ElasticsearchIT.java | 2 +- .../jpa/term/ValueSetExpansionR4Test.java | 16 +- hapi-fhir-jpaserver-batch/pom.xml | 2 +- hapi-fhir-jpaserver-cql/pom.xml | 6 +- hapi-fhir-jpaserver-mdm/pom.xml | 6 +- hapi-fhir-jpaserver-migrate/pom.xml | 2 +- .../tasks/HapiFhirJpaMigrationTasks.java | 4 + hapi-fhir-jpaserver-model/pom.xml | 2 +- .../uhn/fhir/jpa/model/util/JpaConstants.java | 5 + hapi-fhir-jpaserver-searchparam/pom.xml | 2 +- hapi-fhir-jpaserver-subscription/pom.xml | 2 +- hapi-fhir-jpaserver-test-utilities/pom.xml | 2 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 4 +- hapi-fhir-server-mdm/pom.xml | 2 +- hapi-fhir-server/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../hapi-fhir-spring-boot-samples/pom.xml | 2 +- .../hapi-fhir-spring-boot-starter/pom.xml | 2 +- hapi-fhir-spring-boot/pom.xml | 2 +- hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- hapi-fhir-structures-dstu3/pom.xml | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- hapi-fhir-structures-r5/pom.xml | 2 +- hapi-fhir-test-utilities/pom.xml | 2 +- hapi-fhir-testpage-overlay/pom.xml | 2 +- .../pom.xml | 2 +- hapi-fhir-validation-resources-dstu2/pom.xml | 2 +- hapi-fhir-validation-resources-dstu3/pom.xml | 2 +- hapi-fhir-validation-resources-r4/pom.xml | 2 +- hapi-fhir-validation-resources-r5/pom.xml | 2 +- hapi-fhir-validation/pom.xml | 2 +- hapi-tinder-plugin/pom.xml | 16 +- hapi-tinder-test/pom.xml | 2 +- pom.xml | 2 +- restful-server-example/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 93 files changed, 930 insertions(+), 728 deletions(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2525-hierarchical-expansion.yaml create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ITermValueSetConceptView.java diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index 24b70220c38..0bee4719670 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index 7799cb47af2..9eb400b46c0 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index c5a761ca696..ac1fd654c29 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/ValueSetExpansionOptions.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/ValueSetExpansionOptions.java index 443874491f6..0c5edc115f6 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/ValueSetExpansionOptions.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/ValueSetExpansionOptions.java @@ -32,6 +32,17 @@ public class ValueSetExpansionOptions { private boolean myFailOnMissingCodeSystem = true; private int myCount = 1000; private int myOffset = 0; + private boolean myIncludeHierarchy; + private String myFilter; + + public String getFilter() { + return myFilter; + } + + public ValueSetExpansionOptions setFilter(String theFilter) { + myFilter = theFilter; + return this; + } /** * The number of codes to return. @@ -94,6 +105,14 @@ public class ValueSetExpansionOptions { return this; } + public boolean isIncludeHierarchy() { + return myIncludeHierarchy; + } + + public void setIncludeHierarchy(boolean theIncludeHierarchy) { + myIncludeHierarchy = theIncludeHierarchy; + } + public static ValueSetExpansionOptions forOffsetAndCount(int theOffset, int theCount) { return new ValueSetExpansionOptions() .setOffset(theOffset) diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 4dd2fffc8f8..6d6a435eddf 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -3,14 +3,14 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT pom HAPI FHIR BOM ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index 0f7b6eb19c0..b9a5e93b0f6 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index dd903ab4f1b..d7306fba4a9 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index 39c3cc8e20d..4d1fd59e786 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../hapi-deployable-pom diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index 9783866a885..ac83c296578 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index 6893093762d..78ec60b5d68 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index 6f0efaa5903..0783c0ea778 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 20d250d8cc3..ce5eca39f05 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index 6b0955b04ab..837b2992aee 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index fb13d1edbb7..58d067d2797 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml @@ -78,13 +78,13 @@ ca.uhn.hapi.fhir hapi-fhir-structures-dstu2 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT compile ca.uhn.hapi.fhir hapi-fhir-jpaserver-subscription - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT compile @@ -101,7 +101,7 @@ ca.uhn.hapi.fhir hapi-fhir-testpage-overlay - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT classes diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2525-hierarchical-expansion.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2525-hierarchical-expansion.yaml new file mode 100644 index 00000000000..18f3694db46 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_4_0/2525-hierarchical-expansion.yaml @@ -0,0 +1,6 @@ +--- +type: add +issue: 2525 +title: "A new optional parameter has been added to the `ValueSet/$expand` operation. When provided a value of `true`, the + operation will include the concept hierarchy in the expansion response." + diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index 6090e7545d9..bddf4b9e81b 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index 6cfa369bfdc..4d6434eab74 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-example/pom.xml b/hapi-fhir-jaxrsserver-example/pom.xml index 687d6b10dbf..627009d073a 100644 --- a/hapi-fhir-jaxrsserver-example/pom.xml +++ b/hapi-fhir-jaxrsserver-example/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-jpaserver-api/pom.xml b/hapi-fhir-jpaserver-api/pom.xml index 8cf5d00b229..a1b87034a93 100644 --- a/hapi-fhir-jpaserver-api/pom.xml +++ b/hapi-fhir-jpaserver-api/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java index 142158308b0..c0765bf3a46 100644 --- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java +++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.api.dao; */ import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.rest.api.server.RequestDetails; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; @@ -28,17 +29,11 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType; public interface IFhirResourceDaoValueSet extends IFhirResourceDao { - T expand(IIdType theId, String theFilter, RequestDetails theRequestDetails); + T expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails); - T expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails); + T expand(T theSource, ValueSetExpansionOptions theOptions); - T expand(T theSource, String theFilter); - - T expand(T theSource, String theFilter, int theOffset, int theCount); - - T expandByIdentifier(String theUri, String theFilter); - - T expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount); + T expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions); void purgeCaches(); diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index a8958f299a0..7b0116aad18 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoValueSetDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoValueSetDstu2.java index e2102790864..25c3cf98bcb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoValueSetDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoValueSetDstu2.java @@ -24,9 +24,9 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult; +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.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.jpa.model.entity.BaseHasResource; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; @@ -40,6 +40,7 @@ import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.UriParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -51,20 +52,20 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import javax.annotation.Nonnull; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.Collections; import java.util.List; 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.util.LogicUtil.multiXor; import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank; public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao - implements IFhirResourceDaoValueSet, IFhirResourceDaoCodeSystem { + implements IFhirResourceDaoValueSet, IFhirResourceDaoCodeSystem { private DefaultProfileValidationSupport myDefaultProfileValidationSupport; @@ -104,31 +105,32 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao theCode, IPrimitiveType theSystem, CodingDt theCoding, RequestDetails theRequest) { boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode()); @@ -294,20 +287,20 @@ public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao thePrimitive) { - return thePrimitive != null ? thePrimitive.getValue() : null; - } - @Override public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType theValueSetIdentifier, IIdType theId, IPrimitiveType theCode, - IPrimitiveType theSystem, IPrimitiveType theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequest) { + IPrimitiveType theSystem, IPrimitiveType theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequest) { return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept); } @Override - public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType theCodeSystemUrl, IPrimitiveType theVersion, IPrimitiveType theCode, - IPrimitiveType theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequestDetails) { + public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType theCodeSystemUrl, IPrimitiveType theVersion, IPrimitiveType theCode, + IPrimitiveType theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequestDetails) { throw new UnsupportedOperationException(); } + public static String toStringOrNull(IPrimitiveType thePrimitive) { + return thePrimitive != null ? thePrimitive.getValue() : null; + } + } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java index 6145e033b33..968ba695414 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java @@ -47,42 +47,21 @@ import static org.hl7.fhir.convertors.conv30_40.ValueSet30_40.convertValueSet; public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao implements IFhirResourceDaoValueSet { @Override - public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) { + public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) { org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails); - return expand(source, theFilter); + return expand(source, theOptions); } @Override - public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails) { - org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails); - return expand(source, theFilter, theOffset, theCount); - } - - @Override - public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, String theFilter) { - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, theUri, theFilter); - return ValueSet30_40.convertValueSet(canonicalOutput); - } - - @Override - public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) { - ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount); - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, theUri, theFilter); - return ValueSet30_40.convertValueSet(canonicalOutput); - } - - @Override - public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, String theFilter) { + public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, ValueSetExpansionOptions theOptions) { org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet30_40.convertValueSet(theSource); - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, canonicalInput, theFilter); + org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, canonicalInput); return ValueSet30_40.convertValueSet(canonicalOutput); } @Override - public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, String theFilter, int theOffset, int theCount) { - ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount); - org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet30_40.convertValueSet(theSource); - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, canonicalInput, theFilter); + public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) { + org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, theUri); return ValueSet30_40.convertValueSet(canonicalOutput); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java index 8bc50dd690c..0c01b644d52 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java @@ -44,37 +44,20 @@ import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateC public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao implements IFhirResourceDaoValueSet { @Override - public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) { + public ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) { ValueSet source = read(theId, theRequestDetails); - return expand(source, theFilter); + return expand(source, theOptions); + } + + + @Override + public ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) { + return myTerminologySvc.expandValueSet(theOptions, theUri); } @Override - public ValueSet expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails) { - ValueSet source = read(theId, theRequestDetails); - return expand(source, theFilter, theOffset, theCount); - } - - @Override - public ValueSet expandByIdentifier(String theUri, String theFilter) { - return myTerminologySvc.expandValueSet(null, theUri, theFilter); - } - - @Override - public ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) { - ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount); - return myTerminologySvc.expandValueSet(options, theUri, theFilter); - } - - @Override - public ValueSet expand(ValueSet theSource, String theFilter) { - return myTerminologySvc.expandValueSet(null, theSource, theFilter); - } - - @Override - public ValueSet expand(ValueSet theSource, String theFilter, int theOffset, int theCount) { - ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount); - return myTerminologySvc.expandValueSet(options, theSource, theFilter); + public ValueSet expand(ValueSet theSource, ValueSetExpansionOptions theOptions) { + return myTerminologySvc.expandValueSet(theOptions, theSource); } @Override @@ -107,15 +90,5 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao return retVal; } - public static void validateHaveExpansionOrThrowInternalErrorException(IValidationSupport.ValueSetExpansionOutcome theRetVal) { - if (theRetVal != null && theRetVal.getValueSet() == null) { - throw new InternalErrorException("Unable to expand ValueSet: " + theRetVal.getError()); - } - - if (theRetVal == null) { - throw new InternalErrorException("Unable to expand ValueSet"); - } - } - } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java index 13009e60a64..b3cc6c1f331 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java @@ -44,42 +44,21 @@ import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateC public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao implements IFhirResourceDaoValueSet { @Override - public ValueSet expand(IIdType theId, String theFilter, RequestDetails theRequestDetails) { + public ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) { ValueSet source = read(theId, theRequestDetails); - return expand(source, theFilter); + return expand(source, theOptions); } @Override - public ValueSet expand(IIdType theId, String theFilter, int theOffset, int theCount, RequestDetails theRequestDetails) { - ValueSet source = read(theId, theRequestDetails); - return expand(source, theFilter, theOffset, theCount); - } - - @Override - public ValueSet expandByIdentifier(String theUri, String theFilter) { - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, theUri, theFilter); + public ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) { + org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, theUri); return ValueSet40_50.convertValueSet(canonicalOutput); } @Override - public ValueSet expandByIdentifier(String theUri, String theFilter, int theOffset, int theCount) { - ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount); - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, theUri, theFilter); - return ValueSet40_50.convertValueSet(canonicalOutput); - } - - @Override - public ValueSet expand(ValueSet theSource, String theFilter) { + public ValueSet expand(ValueSet theSource, ValueSetExpansionOptions theOptions) { org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet40_50.convertValueSet(theSource); - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(null, canonicalInput, theFilter); - return ValueSet40_50.convertValueSet(canonicalOutput); - } - - @Override - public ValueSet expand(ValueSet theSource, String theFilter, int theOffset, int theCount) { - ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(theOffset, theCount); - org.hl7.fhir.r4.model.ValueSet canonicalInput = ValueSet40_50.convertValueSet(theSource); - org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(options, canonicalInput, theFilter); + org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, canonicalInput); return ValueSet40_50.convertValueSet(canonicalOutput); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ITermValueSetConceptView.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ITermValueSetConceptView.java new file mode 100644 index 00000000000..b8c593f18a8 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ITermValueSetConceptView.java @@ -0,0 +1,47 @@ +package ca.uhn.fhir.jpa.entity; + +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2021 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +public interface ITermValueSetConceptView { + String getConceptSystemUrl(); + + String getConceptCode(); + + String getConceptDisplay(); + + Long getSourceConceptPid(); + + String getSourceConceptDirectParentPids(); + + Long getConceptPid(); + + Long getDesignationPid(); + + String getDesignationUseSystem(); + + String getDesignationUseCode(); + + String getDesignationUseDisplay(); + + String getDesignationVal(); + + String getDesignationLang(); +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java index aafe8449e2d..522df067346 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java @@ -388,7 +388,7 @@ public class TermConcept implements Serializable { b.append("NONE"); } - myParentPids = b.toString(); + setParentPids(b.toString()); } public TermConcept setParentPids(String theParentPids) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java index 2f1a82e10cd..b62120cc213 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java @@ -27,7 +27,21 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import javax.annotation.Nonnull; -import javax.persistence.*; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ForeignKey; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Transient; +import javax.persistence.UniqueConstraint; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -60,6 +74,9 @@ public class TermValueSetConcept implements Serializable { @Column(name = "VALUESET_PID", insertable = false, updatable = false, nullable = false) private Long myValueSetPid; + @Column(name = "INDEX_STATUS", nullable = true) + private Long myIndexStatus; + @Column(name = "VALUESET_ORDER", nullable = false) private int myOrder; @@ -69,6 +86,13 @@ public class TermValueSetConcept implements Serializable { @Transient private String myValueSetName; + @Column(name = "SOURCE_PID", nullable = true) + private Long mySourceConceptPid; + + @Lob + @Column(name = "SOURCE_DIRECT_PARENT_PIDS", nullable = true) + private String mySourceConceptDirectParentPids; + @Column(name = "SYSTEM_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH) private String mySystem; @@ -87,6 +111,13 @@ public class TermValueSetConcept implements Serializable { @Transient private transient Integer myHashCode; + /** + * Constructor + */ + public TermValueSetConcept() { + super(); + } + public Long getId() { return myId; } @@ -219,4 +250,20 @@ public class TermValueSetConcept implements Serializable { .append(myDesignations != null ? ("myDesignations - size=" + myDesignations.size()) : ("myDesignations=(null)")) .toString(); } + + public Long getIndexStatus() { + return myIndexStatus; + } + + public void setIndexStatus(Long theIndexStatus) { + myIndexStatus = theIndexStatus; + } + + public void setSourceConceptPid(Long theSourceConceptPid) { + mySourceConceptPid = theSourceConceptPid; + } + + public void setSourceConceptDirectParentPids(String theSourceConceptDirectParentPids) { + mySourceConceptDirectParentPids = theSourceConceptDirectParentPids; + } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java index 5110ea8baee..22fe57454c0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java @@ -20,16 +20,20 @@ package ca.uhn.fhir.jpa.entity; * #L% */ +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import org.apache.commons.io.IOUtils; import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Subselect; import javax.persistence.Column; -import javax.persistence.EmbeddedId; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.Lob; +import java.io.IOException; +import java.io.Reader; import java.io.Serializable; +import java.sql.Clob; +import java.sql.SQLException; @Entity @Immutable @@ -39,26 +43,28 @@ import java.io.Serializable; * because hibernate won't allow the view the function without it, but */ "SELECT CONCAT_WS(' ', vsc.PID, vscd.PID) AS PID, " + - " vsc.PID AS CONCEPT_PID, " + - " vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " + - " vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " + - " vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " + - " vsc.CODEVAL AS CONCEPT_CODEVAL, " + - " vsc.DISPLAY AS CONCEPT_DISPLAY, " + - " vscd.PID AS DESIGNATION_PID, " + - " vscd.LANG AS DESIGNATION_LANG, " + - " vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " + - " vscd.USE_CODE AS DESIGNATION_USE_CODE, " + - " vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " + - " vscd.VAL AS DESIGNATION_VAL " + - "FROM TRM_VALUESET_CONCEPT vsc " + - "LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID" + " vsc.PID AS CONCEPT_PID, " + + " vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " + + " vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " + + " vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " + + " vsc.CODEVAL AS CONCEPT_CODEVAL, " + + " vsc.DISPLAY AS CONCEPT_DISPLAY, " + + " vsc.SOURCE_PID AS SOURCE_PID, " + + " vsc.SOURCE_DIRECT_PARENT_PIDS AS SOURCE_DIRECT_PARENT_PIDS, " + + " vscd.PID AS DESIGNATION_PID, " + + " vscd.LANG AS DESIGNATION_LANG, " + + " vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " + + " vscd.USE_CODE AS DESIGNATION_USE_CODE, " + + " vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " + + " vscd.VAL AS DESIGNATION_VAL " + + "FROM TRM_VALUESET_CONCEPT vsc " + + "LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID" ) -public class TermValueSetConceptView implements Serializable { +public class TermValueSetConceptView implements Serializable, ITermValueSetConceptView { private static final long serialVersionUID = 1L; @Id - @Column(name="PID", length = 1000 /* length only needed to satisfy JpaEntityTest, it's not used*/) + @Column(name = "PID", length = 1000 /* length only needed to satisfy JpaEntityTest, it's not used*/) private String id; // still set automatically @Column(name = "CONCEPT_PID") @@ -97,43 +103,76 @@ public class TermValueSetConceptView implements Serializable { @Column(name = "DESIGNATION_VAL", length = TermConceptDesignation.MAX_VAL_LENGTH) private String myDesignationVal; + @Column(name = "SOURCE_PID", nullable = true) + private Long mySourceConceptPid; + @Lob + @Column(name = "SOURCE_DIRECT_PARENT_PIDS", nullable = true) + private Clob mySourceConceptDirectParentPids; + + @Override + public Long getSourceConceptPid() { + return mySourceConceptPid; + } + + @Override + public String getSourceConceptDirectParentPids() { + if (mySourceConceptDirectParentPids != null) { + try (Reader characterStream = mySourceConceptDirectParentPids.getCharacterStream()) { + return IOUtils.toString(characterStream); + } catch (IOException | SQLException e) { + throw new InternalErrorException(e); + } + } + return null; + } + + @Override public Long getConceptPid() { return myConceptPid; } + @Override public String getConceptSystemUrl() { return myConceptSystemUrl; } + @Override public String getConceptCode() { return myConceptCode; } + @Override public String getConceptDisplay() { return myConceptDisplay; } + @Override public Long getDesignationPid() { return myDesignationPid; } + @Override public String getDesignationLang() { return myDesignationLang; } + @Override public String getDesignationUseSystem() { return myDesignationUseSystem; } + @Override public String getDesignationUseCode() { return myDesignationUseCode; } + @Override public String getDesignationUseDisplay() { return myDesignationUseDisplay; } + @Override public String getDesignationVal() { return myDesignationVal; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptViewOracle.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptViewOracle.java index 7f6121e50ce..df9fd196713 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptViewOracle.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptViewOracle.java @@ -20,18 +20,20 @@ package ca.uhn.fhir.jpa.entity; * #L% */ +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import org.apache.commons.io.IOUtils; import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Subselect; import javax.persistence.Column; -import javax.persistence.DiscriminatorValue; -import javax.persistence.EmbeddedId; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; import javax.persistence.Id; -import javax.persistence.Table; +import javax.persistence.Lob; +import java.io.IOException; +import java.io.Reader; import java.io.Serializable; +import java.sql.Clob; +import java.sql.SQLException; @Entity @Immutable @@ -41,26 +43,28 @@ import java.io.Serializable; * because hibernate won't allow the view the function without it, but */ "SELECT CONCAT(vsc.PID, CONCAT(' ', vscd.PID)) AS PID, " + - " vsc.PID AS CONCEPT_PID, " + - " vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " + - " vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " + - " vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " + - " vsc.CODEVAL AS CONCEPT_CODEVAL, " + - " vsc.DISPLAY AS CONCEPT_DISPLAY, " + - " vscd.PID AS DESIGNATION_PID, " + - " vscd.LANG AS DESIGNATION_LANG, " + - " vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " + - " vscd.USE_CODE AS DESIGNATION_USE_CODE, " + - " vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " + - " vscd.VAL AS DESIGNATION_VAL " + + " vsc.PID AS CONCEPT_PID, " + + " vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " + + " vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " + + " vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " + + " vsc.CODEVAL AS CONCEPT_CODEVAL, " + + " vsc.DISPLAY AS CONCEPT_DISPLAY, " + + " vsc.SOURCE_PID AS SOURCE_PID, " + + " vsc.SOURCE_DIRECT_PARENT_PIDS AS SOURCE_DIRECT_PARENT_PIDS, " + + " vscd.PID AS DESIGNATION_PID, " + + " vscd.LANG AS DESIGNATION_LANG, " + + " vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " + + " vscd.USE_CODE AS DESIGNATION_USE_CODE, " + + " vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " + + " vscd.VAL AS DESIGNATION_VAL " + "FROM TRM_VALUESET_CONCEPT vsc " + "LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID" ) -public class TermValueSetConceptViewOracle implements Serializable { +public class TermValueSetConceptViewOracle implements Serializable, ITermValueSetConceptView { private static final long serialVersionUID = 1L; @Id - @Column(name="PID", length = 1000 /* length only needed to satisfy JpaEntityTest, it's not used*/) + @Column(name = "PID", length = 1000 /* length only needed to satisfy JpaEntityTest, it's not used*/) private String id; // still set automatically @Column(name = "CONCEPT_PID") @@ -99,43 +103,76 @@ public class TermValueSetConceptViewOracle implements Serializable { @Column(name = "DESIGNATION_VAL", length = TermConceptDesignation.MAX_VAL_LENGTH) private String myDesignationVal; + @Column(name = "SOURCE_PID", nullable = true) + private Long mySourceConceptPid; + @Lob + @Column(name = "SOURCE_DIRECT_PARENT_PIDS", nullable = true) + private Clob mySourceConceptDirectParentPids; + + @Override public Long getConceptPid() { return myConceptPid; } + @Override public String getConceptSystemUrl() { return myConceptSystemUrl; } + @Override public String getConceptCode() { return myConceptCode; } + @Override public String getConceptDisplay() { return myConceptDisplay; } + @Override + public Long getSourceConceptPid() { + return mySourceConceptPid; + } + + @Override + public String getSourceConceptDirectParentPids() { + if (mySourceConceptDirectParentPids != null) { + try (Reader characterStream = mySourceConceptDirectParentPids.getCharacterStream()) { + return IOUtils.toString(characterStream); + } catch (IOException | SQLException e) { + throw new InternalErrorException(e); + } + } + return null; + } + + @Override public Long getDesignationPid() { return myDesignationPid; } + @Override public String getDesignationLang() { return myDesignationLang; } + @Override public String getDesignationUseSystem() { return myDesignationUseSystem; } + @Override public String getDesignationUseCode() { return myDesignationUseCode; } + @Override public String getDesignationUseDisplay() { return myDesignationUseDisplay; } + @Override public String getDesignationVal() { return myDesignationVal; } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderValueSetDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderValueSetDstu2.java index 171fad075e3..75847497200 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderValueSetDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaResourceProviderValueSetDstu2.java @@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.provider; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.support.IValidationSupport; +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.model.util.JpaConstants; @@ -87,8 +88,11 @@ public class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDst } } - private String toFilterString(StringDt theFilter) { - return theFilter != null ? theFilter.getValue() : null; + private ValueSetExpansionOptions toFilterString(StringDt theFilter) { + if (theFilter != null) { + return ValueSetExpansionOptions.forOffsetAndCount(0, 1000).setFilter(theFilter.getValue()); + } + return null; } @Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters = { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderValueSetDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderValueSetDstu3.java index 30fd0f05174..8ef38ecf7bf 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderValueSetDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/BaseJpaResourceProviderValueSetDstu3.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.provider.dstu3; */ import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2; @@ -29,14 +30,24 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import org.hl7.fhir.dstu3.model.*; +import org.hl7.fhir.dstu3.model.BooleanType; +import org.hl7.fhir.dstu3.model.CodeType; +import org.hl7.fhir.dstu3.model.CodeableConcept; +import org.hl7.fhir.dstu3.model.Coding; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.IntegerType; +import org.hl7.fhir.dstu3.model.Parameters; +import org.hl7.fhir.dstu3.model.StringType; +import org.hl7.fhir.dstu3.model.UriType; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import javax.servlet.http.HttpServletRequest; +import static ca.uhn.fhir.jpa.provider.r4.BaseJpaResourceProviderValueSetR4.createValueSetExpansionOptions; import static org.apache.commons.lang3.StringUtils.isNotBlank; public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDstu3 { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaResourceProviderValueSetDstu3.class); @Operation(name = JpaConstants.OPERATION_EXPAND, idempotent = true) public ValueSet expand( @@ -51,6 +62,7 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst @OperationParam(name = "filter", min = 0, max = 1) StringType theFilter, @OperationParam(name = "offset", min = 0, max = 1) IntegerType theOffset, @OperationParam(name = "count", min = 0, max = 1) IntegerType theCount, + @OperationParam(name = JpaConstants.OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY, min = 0, max = 1, typeName = "boolean") IPrimitiveType theIncludeHierarchy, RequestDetails theRequestDetails) { boolean haveId = theId != null && theId.hasIdPart(); @@ -71,56 +83,21 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst throw new InvalidRequestException("$expand must EITHER be invoked at the instance level, or have an identifier specified, or have a ValueSet specified. Can not combine these options."); } - int offset = myDaoConfig.getPreExpandValueSetsDefaultOffset(); - if (theOffset != null && theOffset.hasValue()) { - if (theOffset.getValue() >= 0) { - offset = theOffset.getValue(); - } else { - throw new InvalidRequestException("offset parameter for $expand operation must be >= 0 when specified. offset: " + theOffset.getValue()); - } - } - - int count = myDaoConfig.getPreExpandValueSetsDefaultCount(); - if (theCount != null && theCount.hasValue()) { - if (theCount.getValue() >= 0) { - count = theCount.getValue(); - } else { - throw new InvalidRequestException("count parameter for $expand operation must be >= 0 when specified. count: " + theCount.getValue()); - } - } - int countMax = myDaoConfig.getPreExpandValueSetsMaxCount(); - if (count > countMax) { - ourLog.warn("count parameter for $expand operation of {} exceeds maximum value of {}; using maximum value.", count, countMax); - count = countMax; - } + ValueSetExpansionOptions options = createValueSetExpansionOptions(myDaoConfig, theOffset, theCount, theIncludeHierarchy, theFilter); startRequest(theServletRequest); try { IFhirResourceDaoValueSet dao = (IFhirResourceDaoValueSet) getDao(); - if (myDaoConfig.isPreExpandValueSets()) { - if (haveId) { - return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails); - } else if (haveIdentifier) { - if (haveValueSetVersion) { - return dao.expandByIdentifier(url.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter), offset, count); - } else { - return dao.expandByIdentifier(url.getValue(), toFilterString(theFilter), offset, count); - } + if (haveId) { + return dao.expand(theId, options, theRequestDetails); + } else if (haveIdentifier) { + if (haveValueSetVersion) { + return dao.expandByIdentifier(url.getValue() + "|" + theValueSetVersion.getValue(), options); } else { - return dao.expand(theValueSet, toFilterString(theFilter), offset, count); + return dao.expandByIdentifier(url.getValue(), options); } } else { - if (haveId) { - return dao.expand(theId, toFilterString(theFilter), theRequestDetails); - } else if (haveIdentifier) { - if (haveValueSetVersion) { - return dao.expandByIdentifier(url.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter)); - } else { - return dao.expandByIdentifier(url.getValue(), toFilterString(theFilter)); - } - } else { - return dao.expand(theValueSet, toFilterString(theFilter)); - } + return dao.expand(theValueSet, options); } } finally { endRequest(theServletRequest); @@ -128,11 +105,6 @@ public class BaseJpaResourceProviderValueSetDstu3 extends JpaResourceProviderDst } - private String toFilterString(StringType theFilter) { - return theFilter != null ? theFilter.getValue() : null; - } - - @Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = { @OperationParam(name = "result", type = BooleanType.class, min = 1), @OperationParam(name = "message", type = StringType.class), diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/BaseJpaResourceProviderValueSetR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/BaseJpaResourceProviderValueSetR4.java index 1e8e7425689..94cb8a684e2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/BaseJpaResourceProviderValueSetR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r4/BaseJpaResourceProviderValueSetR4.java @@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.provider.r4; */ import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; +import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2; @@ -29,7 +31,17 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import org.hl7.fhir.r4.model.*; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +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.IdType; +import org.hl7.fhir.r4.model.IntegerType; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.UriType; +import org.hl7.fhir.r4.model.ValueSet; import javax.servlet.http.HttpServletRequest; @@ -48,6 +60,7 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4 theIncludeHierarchy, RequestDetails theRequestDetails) { boolean haveId = theId != null && theId.hasIdPart(); @@ -63,69 +76,28 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4= 0) { - offset = theOffset.getValue(); - } else { - throw new InvalidRequestException("offset parameter for $expand operation must be >= 0 when specified. offset: " + theOffset.getValue()); - } - } - - int count = myDaoConfig.getPreExpandValueSetsDefaultCount(); - if (theCount != null && theCount.hasValue()) { - if (theCount.getValue() >= 0) { - count = theCount.getValue(); - } else { - throw new InvalidRequestException("count parameter for $expand operation must be >= 0 when specified. count: " + theCount.getValue()); - } - } - int countMax = myDaoConfig.getPreExpandValueSetsMaxCount(); - if (count > countMax) { - ourLog.warn("count parameter for $expand operation of {} exceeds maximum value of {}; using maximum value.", count, countMax); - count = countMax; - } + ValueSetExpansionOptions options = createValueSetExpansionOptions(myDaoConfig, theOffset, theCount, theIncludeHierarchy, theFilter); startRequest(theServletRequest); try { + IFhirResourceDaoValueSet dao = (IFhirResourceDaoValueSet) getDao(); - if (myDaoConfig.isPreExpandValueSets()) { - if (haveId) { - return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails); - } else if (haveIdentifier) { - if (haveValueSetVersion) { - return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter), offset, count); - } else { - return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter), offset, count); - } + if (haveId) { + return dao.expand(theId, options, theRequestDetails); + } else if (haveIdentifier) { + if (haveValueSetVersion) { + return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), options); } else { - return dao.expand(theValueSet, toFilterString(theFilter), offset, count); + return dao.expandByIdentifier(theUrl.getValue(), options); } } else { - if (haveId) { - return dao.expand(theId, toFilterString(theFilter), theRequestDetails); - } else if (haveIdentifier) { - if (haveValueSetVersion) { - return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter)); - } else { - return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter)); - } - } else { - return dao.expand(theValueSet, toFilterString(theFilter)); - } + return dao.expand(theValueSet, options); } } finally { endRequest(theServletRequest); } } - - private String toFilterString(StringType theFilter) { - return theFilter != null ? theFilter.getValue() : null; - } - - - @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), @@ -167,6 +139,42 @@ public class BaseJpaResourceProviderValueSetR4 extends JpaResourceProviderR4 theOffset, IPrimitiveType theCount, IPrimitiveType theIncludeHierarchy, IPrimitiveType theFilter) { + int offset = theDaoConfig.getPreExpandValueSetsDefaultOffset(); + if (theOffset != null && theOffset.hasValue()) { + if (theOffset.getValue() >= 0) { + offset = theOffset.getValue(); + } else { + throw new InvalidRequestException("offset parameter for $expand operation must be >= 0 when specified. offset: " + theOffset.getValue()); + } + } + + int count = theDaoConfig.getPreExpandValueSetsDefaultCount(); + if (theCount != null && theCount.hasValue()) { + if (theCount.getValue() >= 0) { + count = theCount.getValue(); + } else { + throw new InvalidRequestException("count parameter for $expand operation must be >= 0 when specified. count: " + theCount.getValue()); + } + } + int countMax = theDaoConfig.getPreExpandValueSetsMaxCount(); + if (count > countMax) { + ourLog.warn("count parameter for $expand operation of {} exceeds maximum value of {}; using maximum value.", count, countMax); + count = countMax; + } + + ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(offset, count); + + if (theIncludeHierarchy != null && Boolean.TRUE.equals(theIncludeHierarchy.getValue())) { + options.setIncludeHierarchy(true); + } + + if (theFilter != null) { + options.setFilter(theFilter.getValue()); + } + + return options; + } private static boolean moreThanOneTrue(boolean... theBooleans) { boolean haveOne = false; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/BaseJpaResourceProviderValueSetR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/BaseJpaResourceProviderValueSetR5.java index c08ca946063..6f17aa2b8c5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/BaseJpaResourceProviderValueSetR5.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/r5/BaseJpaResourceProviderValueSetR5.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.provider.r5; */ import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderValueSetDstu2; @@ -29,14 +30,24 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import org.hl7.fhir.r5.model.*; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.r5.model.BooleanType; +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.IntegerType; +import org.hl7.fhir.r5.model.Parameters; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.UriType; +import org.hl7.fhir.r5.model.ValueSet; import javax.servlet.http.HttpServletRequest; +import static ca.uhn.fhir.jpa.provider.r4.BaseJpaResourceProviderValueSetR4.createValueSetExpansionOptions; import static org.apache.commons.lang3.StringUtils.isNotBlank; public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5 { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseJpaResourceProviderValueSetR5.class); @Operation(name = JpaConstants.OPERATION_EXPAND, idempotent = true) public ValueSet expand( @@ -48,6 +59,7 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5 theIncludeHierarchy, RequestDetails theRequestDetails) { boolean haveId = theId != null && theId.hasIdPart(); @@ -63,56 +75,21 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5= 0) { - offset = theOffset.getValue(); - } else { - throw new InvalidRequestException("offset parameter for $expand operation must be >= 0 when specified. offset: " + theOffset.getValue()); - } - } - - int count = myDaoConfig.getPreExpandValueSetsDefaultCount(); - if (theCount != null && theCount.hasValue()) { - if (theCount.getValue() >= 0) { - count = theCount.getValue(); - } else { - throw new InvalidRequestException("count parameter for $expand operation must be >= 0 when specified. count: " + theCount.getValue()); - } - } - int countMax = myDaoConfig.getPreExpandValueSetsMaxCount(); - if (count > countMax) { - ourLog.warn("count parameter for $expand operation of {} exceeds maximum value of {}; using maximum value.", count, countMax); - count = countMax; - } + ValueSetExpansionOptions options = createValueSetExpansionOptions(myDaoConfig, theOffset, theCount, theIncludeHierarchy, theFilter); startRequest(theServletRequest); try { IFhirResourceDaoValueSet dao = (IFhirResourceDaoValueSet) getDao(); - if (myDaoConfig.isPreExpandValueSets()) { - if (haveId) { - return dao.expand(theId, toFilterString(theFilter), offset, count, theRequestDetails); - } else if (haveIdentifier) { - if (haveValueSetVersion) { - return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter), offset, count); - } else { - return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter), offset, count); - } + if (haveId) { + return dao.expand(theId, options, theRequestDetails); + } else if (haveIdentifier) { + if (haveValueSetVersion) { + return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), options); } else { - return dao.expand(theValueSet, toFilterString(theFilter), offset, count); + return dao.expandByIdentifier(theUrl.getValue(), options); } } else { - if (haveId) { - return dao.expand(theId, toFilterString(theFilter), theRequestDetails); - } else if (haveIdentifier) { - if (haveValueSetVersion) { - return dao.expandByIdentifier(theUrl.getValue() + "|" + theValueSetVersion.getValue(), toFilterString(theFilter)); - } else { - return dao.expandByIdentifier(theUrl.getValue(), toFilterString(theFilter)); - } - } else { - return dao.expand(theValueSet, toFilterString(theFilter)); - } + return dao.expand(theValueSet, options); } } finally { endRequest(theServletRequest); @@ -120,12 +97,6 @@ public class BaseJpaResourceProviderValueSetR5 extends JpaResourceProviderR5 t.getParent().getId().toString()) + .collect(Collectors.joining(" ")); + Collection designations = theConcept.getDesignations(); if (StringUtils.isNotEmpty(theValueSetIncludeVersion)) { - return addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, codeSystem + "|" + theValueSetIncludeVersion, code, display); + return addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, codeSystem + "|" + theValueSetIncludeVersion, code, display, sourceConceptPid, directParentPids); } else { - return addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, codeSystem, code, display); + return addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, codeSystem, code, display, sourceConceptPid, directParentPids); } } - private void addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, boolean theAdd, String theCodeSystem, String theCodeSystemVersion, String theCode, String theDisplay) { + private void addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, boolean theAdd, String theCodeSystem, String theCodeSystemVersion, String theCode, String theDisplay, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { if (StringUtils.isNotEmpty(theCodeSystemVersion)) { if (isNoneBlank(theCodeSystem, theCode)) { if (theAdd && theAddedCodes.add(theCodeSystem + "|" + theCode)) { - theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem + "|" + theCodeSystemVersion, theCode, theDisplay, null); + theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem + "|" + theCodeSystemVersion, theCode, theDisplay, null, theSourceConceptPid, theSourceConceptDirectParentPids); } if (!theAdd && theAddedCodes.remove(theCodeSystem + "|" + theCode)) { @@ -272,7 +280,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } else { if (theAdd && theAddedCodes.add(theCodeSystem + "|" + theCode)) { - theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, null); + theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, null, theSourceConceptPid, theSourceConceptDirectParentPids); } if (!theAdd && theAddedCodes.remove(theCodeSystem + "|" + theCode)) { @@ -281,10 +289,10 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } - private boolean addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, Collection theDesignations, boolean theAdd, String theCodeSystem, String theCode, String theDisplay) { + private boolean addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, Collection theDesignations, boolean theAdd, String theCodeSystem, String theCode, String theDisplay, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { if (isNoneBlank(theCodeSystem, theCode)) { if (theAdd && theAddedCodes.add(theCodeSystem + "|" + theCode)) { - theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, theDesignations); + theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, theDesignations, theSourceConceptPid, theSourceConceptDirectParentPids); return true; } @@ -353,10 +361,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { @Override @Transactional public List expandValueSetIntoConceptList(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl) { - String expansionFilter = null; // TODO: DM 2019-09-10 - This is problematic because an incorrect URL that matches ValueSet.id will not be found in the terminology tables but will yield a ValueSet here. Depending on the ValueSet, the expansion may time-out. - ValueSet expanded = expandValueSet(theExpansionOptions, theValueSetCanonicalUrl, expansionFilter); + ValueSet expanded = expandValueSet(theExpansionOptions, theValueSetCanonicalUrl); ArrayList retVal = new ArrayList<>(); for (ValueSet.ValueSetExpansionContainsComponent nextContains : expanded.getExpansion().getContains()) { @@ -367,25 +374,23 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { @Override @Transactional - public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl, @Nullable String theExpansionFilter) { + public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl) { ValueSet valueSet = fetchCanonicalValueSetFromCompleteContext(theValueSetCanonicalUrl); if (valueSet == null) { throw new ResourceNotFoundException("Unknown ValueSet: " + UrlUtil.escapeUrlParam(theValueSetCanonicalUrl)); } - return expandValueSet(theExpansionOptions, valueSet, theExpansionFilter); + return expandValueSet(theExpansionOptions, valueSet); } @Override @Transactional(propagation = Propagation.REQUIRED) public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand) { - return expandValueSet(theExpansionOptions, theValueSetToExpand, (String) null); - } - - @Override - @Transactional(propagation = Propagation.REQUIRED) - public ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand, @Nullable String theFilter) { - return expandValueSet(theExpansionOptions, theValueSetToExpand, ExpansionFilter.fromFilterString(theFilter)); + String filter = null; + if (theExpansionOptions != null) { + filter = theExpansionOptions.getFilter(); + } + return expandValueSet(theExpansionOptions, theValueSetToExpand, ExpansionFilter.fromFilterString(filter)); } private ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, ExpansionFilter theFilter) { @@ -395,7 +400,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { int offset = expansionOptions.getOffset(); int count = expansionOptions.getCount(); - ValueSetExpansionComponentWithConceptAccumulator accumulator = new ValueSetExpansionComponentWithConceptAccumulator(myContext, count); + ValueSetExpansionComponentWithConceptAccumulator accumulator = new ValueSetExpansionComponentWithConceptAccumulator(myContext, count, expansionOptions.isIncludeHierarchy()); accumulator.setHardExpansionMaximumSize(myDaoConfig.getMaximumExpansionSize()); accumulator.setSkipCountRemaining(offset); accumulator.setIdentifier(UUID.randomUUID().toString()); @@ -424,6 +429,11 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { .setUrl(HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE) .setValue(new StringType(next)); } + + if (expansionOptions.isIncludeHierarchy()) { + accumulator.applyHierarchy(); + } + return valueSet; } @@ -469,124 +479,14 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { */ String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "valueSetExpandedUsingPreExpansion"); theAccumulator.addMessage(msg); - if (isOracleDialect()) { - expandConceptsOracle(theAccumulator, termValueSet, theFilter, theAdd); - } else { - expandConcepts(theAccumulator, termValueSet, theFilter, theAdd); - } + expandConcepts(theAccumulator, termValueSet, theFilter, theAdd, isOracleDialect()); } private boolean isOracleDialect() { return myHibernatePropertiesProvider.getDialect() instanceof org.hibernate.dialect.Oracle12cDialect; } - private void expandConceptsOracle(IValueSetConceptAccumulator theAccumulator, TermValueSet theTermValueSet, ExpansionFilter theFilter, boolean theAdd) { - // Literal copy paste from expandConcepts but tailored for Oracle since we can't reliably extend the DAO and hibernate classes - Integer offset = theAccumulator.getSkipCountRemaining(); - offset = ObjectUtils.defaultIfNull(offset, 0); - offset = Math.min(offset, theTermValueSet.getTotalConcepts().intValue()); - - Integer count = theAccumulator.getCapacityRemaining(); - count = defaultIfNull(count, myDaoConfig.getMaximumExpansionSize()); - - int conceptsExpanded = 0; - int designationsExpanded = 0; - int toIndex = offset + count; - - Collection conceptViews; - boolean wasFilteredResult = false; - String filterDisplayValue = null; - if (!theFilter.getFilters().isEmpty() && JpaConstants.VALUESET_FILTER_DISPLAY.equals(theFilter.getFilters().get(0).getProperty()) && theFilter.getFilters().get(0).getOp() == ValueSet.FilterOperator.EQUAL) { - filterDisplayValue = lowerCase(theFilter.getFilters().get(0).getValue().replace("%", "[%]")); - String displayValue = "%" + lowerCase(filterDisplayValue) + "%"; - conceptViews = myTermValueSetConceptViewOracleDao.findByTermValueSetId(theTermValueSet.getId(), displayValue); - wasFilteredResult = true; - } else { - // TODO JA HS: I'm pretty sure we are overfetching here. test says offset 3, count 4, but we are fetching index 3 -> 10 here, grabbing 7 concepts. - //Specifically this test testExpandInline_IncludePreExpandedValueSetByUri_FilterOnDisplay_LeftMatch_SelectRange - conceptViews = myTermValueSetConceptViewOracleDao.findByTermValueSetId(offset, toIndex, theTermValueSet.getId()); - theAccumulator.consumeSkipCount(offset); - if (theAdd) { - theAccumulator.incrementOrDecrementTotalConcepts(true, theTermValueSet.getTotalConcepts().intValue()); - } - } - - if (conceptViews.isEmpty()) { - logConceptsExpanded("No concepts to expand. ", theTermValueSet, conceptsExpanded); - return; - } - - Map pidToConcept = new LinkedHashMap<>(); - ArrayListMultimap pidToDesignations = ArrayListMultimap.create(); - - for (TermValueSetConceptViewOracle conceptView : conceptViews) { - - String system = conceptView.getConceptSystemUrl(); - String code = conceptView.getConceptCode(); - String display = conceptView.getConceptDisplay(); - - //-- this is quick solution, may need to revisit - if (!applyFilter(display, filterDisplayValue)) - continue; - - Long conceptPid = conceptView.getConceptPid(); - if (!pidToConcept.containsKey(conceptPid)) { - FhirVersionIndependentConcept concept = new FhirVersionIndependentConcept(system, code, display); - pidToConcept.put(conceptPid, concept); - } - - // TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to designations optional. - if (conceptView.getDesignationPid() != null) { - TermConceptDesignation designation = new TermConceptDesignation(); - designation.setUseSystem(conceptView.getDesignationUseSystem()); - designation.setUseCode(conceptView.getDesignationUseCode()); - designation.setUseDisplay(conceptView.getDesignationUseDisplay()); - designation.setValue(conceptView.getDesignationVal()); - designation.setLanguage(conceptView.getDesignationLang()); - pidToDesignations.put(conceptPid, designation); - - if (++designationsExpanded % 250 == 0) { - logDesignationsExpanded("Expansion of designations in progress. ", theTermValueSet, designationsExpanded); - } - } - - if (++conceptsExpanded % 250 == 0) { - logConceptsExpanded("Expansion of concepts in progress. ", theTermValueSet, conceptsExpanded); - } - } - - for (Long nextPid : pidToConcept.keySet()) { - FhirVersionIndependentConcept concept = pidToConcept.get(nextPid); - List designations = pidToDesignations.get(nextPid); - String system = concept.getSystem(); - String code = concept.getCode(); - String display = concept.getDisplay(); - - if (theAdd) { - if (theAccumulator.getCapacityRemaining() != null) { - if (theAccumulator.getCapacityRemaining() == 0) { - break; - } - } - - theAccumulator.includeConceptWithDesignations(system, code, display, designations); - } else { - boolean removed = theAccumulator.excludeConcept(system, code); - if (removed) { - theAccumulator.incrementOrDecrementTotalConcepts(false, 1); - } - } - } - - if (wasFilteredResult && theAdd) { - theAccumulator.incrementOrDecrementTotalConcepts(true, pidToConcept.size()); - } - - logDesignationsExpanded("Finished expanding designations. ", theTermValueSet, designationsExpanded); - logConceptsExpanded("Finished expanding concepts. ", theTermValueSet, conceptsExpanded); - } - - private void expandConcepts(IValueSetConceptAccumulator theAccumulator, TermValueSet theTermValueSet, ExpansionFilter theFilter, boolean theAdd) { + private void expandConcepts(IValueSetConceptAccumulator theAccumulator, TermValueSet theTermValueSet, ExpansionFilter theFilter, boolean theAdd, boolean theOracle) { // NOTE: if you modifiy the logic here, look to `expandConceptsOracle` and see if your new code applies to its copy pasted sibling Integer offset = theAccumulator.getSkipCountRemaining(); offset = ObjectUtils.defaultIfNull(offset, 0); @@ -599,19 +499,26 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { int designationsExpanded = 0; int toIndex = offset + count; - Collection conceptViews; - Collection conceptViewsOracle; + Collection conceptViews; boolean wasFilteredResult = false; String filterDisplayValue = null; if (!theFilter.getFilters().isEmpty() && JpaConstants.VALUESET_FILTER_DISPLAY.equals(theFilter.getFilters().get(0).getProperty()) && theFilter.getFilters().get(0).getOp() == ValueSet.FilterOperator.EQUAL) { filterDisplayValue = lowerCase(theFilter.getFilters().get(0).getValue().replace("%", "[%]")); String displayValue = "%" + lowerCase(filterDisplayValue) + "%"; - conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(theTermValueSet.getId(), displayValue); + if (theOracle) { + conceptViews = myTermValueSetConceptViewOracleDao.findByTermValueSetId(theTermValueSet.getId(), displayValue); + } else { + conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(theTermValueSet.getId(), displayValue); + } wasFilteredResult = true; } else { // TODO JA HS: I'm pretty sure we are overfetching here. test says offset 3, count 4, but we are fetching index 3 -> 10 here, grabbing 7 concepts. //Specifically this test testExpandInline_IncludePreExpandedValueSetByUri_FilterOnDisplay_LeftMatch_SelectRange - conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(offset, toIndex, theTermValueSet.getId()); + if (theOracle) { + conceptViews = myTermValueSetConceptViewOracleDao.findByTermValueSetId(offset, toIndex, theTermValueSet.getId()); + } else { + conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(offset, toIndex, theTermValueSet.getId()); + } theAccumulator.consumeSkipCount(offset); if (theAdd) { theAccumulator.incrementOrDecrementTotalConcepts(true, theTermValueSet.getTotalConcepts().intValue()); @@ -625,8 +532,10 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { Map pidToConcept = new LinkedHashMap<>(); ArrayListMultimap pidToDesignations = ArrayListMultimap.create(); + Map pidToSourcePid = new HashMap<>(); + Map pidToSourceDirectParentPids = new HashMap<>(); - for (TermValueSetConceptView conceptView : conceptViews) { + for (ITermValueSetConceptView conceptView : conceptViews) { String system = conceptView.getConceptSystemUrl(); String code = conceptView.getConceptCode(); @@ -657,6 +566,11 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } + if (theAccumulator.isTrackingHierarchy()) { + pidToSourcePid.put(conceptPid, conceptView.getSourceConceptPid()); + pidToSourceDirectParentPids.put(conceptPid, conceptView.getSourceConceptDirectParentPids()); + } + if (++conceptsExpanded % 250 == 0) { logConceptsExpanded("Expansion of concepts in progress. ", theTermValueSet, conceptsExpanded); } @@ -676,7 +590,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } - theAccumulator.includeConceptWithDesignations(system, code, display, designations); + Long sourceConceptPid = pidToSourcePid.get(nextPid); + String sourceConceptDirectParentPids = pidToSourceDirectParentPids.get(nextPid); + theAccumulator.includeConceptWithDesignations(system, code, display, designations, sourceConceptPid, sourceConceptDirectParentPids); } else { boolean removed = theAccumulator.excludeConcept(system, code); if (removed) { @@ -1158,7 +1074,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { private void addOrRemoveCode(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, boolean theAdd, String theSystem, String theCode, String theDisplay) { if (theAdd && theAddedCodes.add(theSystem + "|" + theCode)) { - theValueSetCodeAccumulator.includeConcept(theSystem, theCode, theDisplay); + theValueSetCodeAccumulator.includeConcept(theSystem, theCode, theDisplay, null, null); } if (!theAdd && theAddedCodes.remove(theSystem + "|" + theCode)) { theValueSetCodeAccumulator.excludeConcept(theSystem, theCode); @@ -1506,7 +1422,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { if (theInclude.getConcept().isEmpty()) { for (TermConcept next : theVersion.getConcepts()) { - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay()); + addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay(), next.getId(), next.getParentPidsAsString()); } } @@ -1514,7 +1430,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { if (!theSystem.equals(theInclude.getSystem()) && isNotBlank(theSystem)) { continue; } - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay()); + addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay(), null, null); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IValueSetConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IValueSetConceptAccumulator.java index 869871e4313..9a60a5e9b95 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IValueSetConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/IValueSetConceptAccumulator.java @@ -29,9 +29,9 @@ public interface IValueSetConceptAccumulator { void addMessage(String theMessage); - void includeConcept(String theSystem, String theCode, String theDisplay); + void includeConcept(String theSystem, String theCode, String theDisplay, Long theSourceConceptPid, String theSourceConceptDirectParentPids); - void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, @Nullable Collection theDesignations); + void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, @Nullable Collection theDesignations, Long theSourceConceptPid, String theSourceConceptDirectParentPids); /** * @return Returns true if the code was actually present and was removed @@ -48,6 +48,10 @@ public interface IValueSetConceptAccumulator { return null; } + default boolean isTrackingHierarchy() { + return true; + } + @Nullable default void consumeSkipCount(int theSkipCountToConsume) { // nothing diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java index b0231fab16b..1cc63e1d8dd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java @@ -66,13 +66,13 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { } @Override - public void includeConcept(String theSystem, String theCode, String theDisplay) { - saveConcept(theSystem, theCode, theDisplay); + public void includeConcept(String theSystem, String theCode, String theDisplay, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { + saveConcept(theSystem, theCode, theDisplay, theSourceConceptPid, theSourceConceptDirectParentPids); } @Override - public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection theDesignations) { - TermValueSetConcept concept = saveConcept(theSystem, theCode, theDisplay); + public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection theDesignations, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { + TermValueSetConcept concept = saveConcept(theSystem, theCode, theDisplay, theSourceConceptPid, theSourceConceptDirectParentPids); if (theDesignations != null) { for (TermConceptDesignation designation : theDesignations) { saveConceptDesignation(concept, designation); @@ -117,7 +117,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { return false; } - private TermValueSetConcept saveConcept(String theSystem, String theCode, String theDisplay) { + private TermValueSetConcept saveConcept(String theSystem, String theCode, String theDisplay, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { ValidateUtil.isNotBlankOrThrowInvalidRequest(theSystem, "ValueSet contains a concept with no system value"); ValidateUtil.isNotBlankOrThrowInvalidRequest(theCode, "ValueSet contains a concept with no code value"); @@ -135,6 +135,10 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { if (isNotBlank(theDisplay)) { concept.setDisplay(theDisplay); } + + concept.setSourceConceptPid(theSourceConceptPid); + concept.setSourceConceptDirectParentPids(theSourceConceptDirectParentPids); + myValueSetConceptDao.save(concept); myValueSetDao.save(myTermValueSet.incrementTotalConcepts()); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetExpansionComponentWithConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetExpansionComponentWithConceptAccumulator.java index d368800ea81..353f44c3911 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetExpansionComponentWithConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetExpansionComponentWithConceptAccumulator.java @@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.term; */ import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.entity.TermConceptDesignation; import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException; import ca.uhn.fhir.model.api.annotation.Block; @@ -32,9 +31,15 @@ import org.hl7.fhir.r4.model.ValueSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; @Block() public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.ValueSetExpansionComponent implements IValueSetConceptAccumulator { @@ -45,25 +50,21 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V private List myMessages; private int myAddedConcepts; private Integer myTotalConcepts; - - /** - * Constructor - * - * @param theDaoConfig Will be used to determine the max capacity for this accumulator - */ - public ValueSetExpansionComponentWithConceptAccumulator(FhirContext theContext, DaoConfig theDaoConfig) { - this(theContext, theDaoConfig.getMaximumExpansionSize()); - } + private Map mySourcePidToConcept = new HashMap<>(); + private Map myConceptToSourceDirectParentPids = new HashMap<>(); + private boolean myTrackingHierarchy; /** * Constructor * * @param theMaxCapacity The maximum number of results this accumulator will accept before throwing * an {@link InternalErrorException} + * @param theTrackingHierarchy */ - ValueSetExpansionComponentWithConceptAccumulator(FhirContext theContext, int theMaxCapacity) { + ValueSetExpansionComponentWithConceptAccumulator(FhirContext theContext, int theMaxCapacity, boolean theTrackingHierarchy) { myMaxCapacity = theMaxCapacity; myContext = theContext; + myTrackingHierarchy = theTrackingHierarchy; } @Nonnull @@ -79,6 +80,11 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V return Collections.unmodifiableList(myMessages); } + @Override + public boolean isTrackingHierarchy() { + return myTrackingHierarchy; + } + @Override public void addMessage(String theMessage) { if (myMessages == null) { @@ -88,7 +94,7 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V } @Override - public void includeConcept(String theSystem, String theCode, String theDisplay) { + public void includeConcept(String theSystem, String theCode, String theDisplay, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { if (mySkipCountRemaining > 0) { mySkipCountRemaining--; return; @@ -103,7 +109,7 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V } @Override - public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection theDesignations) { + public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection theDesignations, Long theSourceConceptPid, String theSourceConceptDirectParentPids) { if (mySkipCountRemaining > 0) { mySkipCountRemaining--; return; @@ -112,6 +118,14 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V incrementConceptsCount(); ValueSet.ValueSetExpansionContainsComponent contains = this.addContains(); + + if (theSourceConceptPid != null) { + mySourcePidToConcept.put(theSourceConceptPid, contains); + } + if (theSourceConceptDirectParentPids != null) { + myConceptToSourceDirectParentPids.put(contains, theSourceConceptDirectParentPids); + } + setSystemAndVersion(theSystem, contains); contains.setCode(theCode); contains.setDisplay(theDisplay); @@ -215,4 +229,29 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V public void setHardExpansionMaximumSize(int theHardExpansionMaximumSize) { myHardExpansionMaximumSize = theHardExpansionMaximumSize; } + + public void applyHierarchy() { + for (int i = 0; i < this.getContains().size(); i++) { + ValueSet.ValueSetExpansionContainsComponent nextContains = this.getContains().get(i); + + String directParentPidsString = myConceptToSourceDirectParentPids.get(nextContains); + if (isNotBlank(directParentPidsString)) { + List directParentPids = Arrays.stream(directParentPidsString.split(" ")).map(t -> Long.parseLong(t)).collect(Collectors.toList()); + + boolean firstMatch = false; + for (Long next : directParentPids) { + ValueSet.ValueSetExpansionContainsComponent parentConcept = mySourcePidToConcept.get(next); + if (parentConcept != null) { + if (!firstMatch) { + firstMatch = true; + this.getContains().remove(i); + i--; + } + + parentConcept.addContains(nextContains); + } + } + } + } + } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermReadSvc.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermReadSvc.java index 94e482fddba..0f04f62bd8e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermReadSvc.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/api/ITermReadSvc.java @@ -58,12 +58,10 @@ import java.util.Set; */ public interface ITermReadSvc extends IValidationSupport { - ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl, @Nullable String theExpansionFilter); + ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull String theValueSetCanonicalUrl); ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand); - ValueSet expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, @Nonnull ValueSet theValueSetToExpand, @Nullable String theFilter); - void expandValueSet(@Nullable ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator); /** diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoValueSetDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoValueSetDstu2Test.java index a4569557dd1..8b8289a3980 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoValueSetDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoValueSetDstu2Test.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao.dstu2; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodingDt; @@ -180,7 +181,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test { * Filter with display name */ - expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd); + expanded = myValueSetDao.expand(myExtensionalVsId, new ValueSetExpansionOptions().setFilter("systolic"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off @@ -193,7 +194,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test { * Filter with code */ - expanded = myValueSetDao.expand(myExtensionalVsId, ("11378"), mySrd); + expanded = myValueSetDao.expand(myExtensionalVsId, new ValueSetExpansionOptions().setFilter("11378"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off @@ -205,7 +206,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test { @Test public void testExpandByIdentifier() { - ValueSet expanded = myValueSetDao.expandByIdentifier("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", "11378"); + ValueSet expanded = myValueSetDao.expandByIdentifier("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", new ValueSetExpansionOptions().setFilter("11378")); String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off @@ -220,7 +221,7 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test { @Test public void testExpandByValueSet() throws IOException { ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml"); - ValueSet expanded = myValueSetDao.expand(toExpand, "11378"); + ValueSet expanded = myValueSetDao.expand(toExpand, new ValueSetExpansionOptions().setFilter("11378")); String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off @@ -235,12 +236,12 @@ public class FhirResourceDaoValueSetDstu2Test extends BaseJpaDstu2Test { @Test public void testValidateCodeForCodeSystemOperationNotSupported() { try { - ((IFhirResourceDaoCodeSystem)myValueSetDao).validateCode(null, null, null, null, null, null, null, null); + ((IFhirResourceDaoCodeSystem) myValueSetDao).validateCode(null, null, null, null, null, null, null, null); fail(); } catch (UnsupportedOperationException theE) { assertNotNull(theE); } } - + } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java index 70d144cbe00..8dac2aa1096 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java @@ -1,16 +1,17 @@ package ca.uhn.fhir.jpa.dao.dstu3; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; -import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParamModifier; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -18,7 +19,6 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.ValidationResult; import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; @@ -38,7 +38,6 @@ import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator; import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -48,26 +47,27 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsStringIgnoringCase; import static org.hamcrest.Matchers.empty; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.fail; public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3TerminologyTest.class); public static final String URL_MY_CODE_SYSTEM = "http://example.com/my_code_system"; public static final String URL_MY_VALUE_SET = "http://example.com/my_value_set"; - + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3TerminologyTest.class); @Autowired private CachingValidationSupport myCachingValidationSupport; + @Autowired + private ITermDeferredStorageSvc myTermDeferredStorageSvc; @AfterEach public void after() { myDaoConfig.setDeferIndexingForCodesystemsOfSize(new DaoConfig().getDeferIndexingForCodesystemsOfSize()); - + TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(false); } @@ -138,7 +138,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { cs.getConcepts().add(parentA); for (int i = 0; i < 450; i++) { - TermConcept childI = new TermConcept(cs, "subCodeA"+i).setDisplay("Sub-code A"+i); + TermConcept childI = new TermConcept(cs, "subCodeA" + i).setDisplay("Sub-code A" + i); parentA.addChild(childI, RelationshipTypeEnum.ISA); } @@ -146,18 +146,15 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { cs.getConcepts().add(parentB); for (int i = 0; i < 450; i++) { - TermConcept childI = new TermConcept(cs, "subCodeB"+i).setDisplay("Sub-code B"+i); + TermConcept childI = new TermConcept(cs, "subCodeB" + i).setDisplay("Sub-code B" + i); parentB.addChild(childI, RelationshipTypeEnum.ISA); } - myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION" , cs, table); + myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); myTermDeferredStorageSvc.saveAllDeferred(); } - @Autowired - private ITermDeferredStorageSvc myTermDeferredStorageSvc; - private void createExternalCsAndLocalVs() { CodeSystem codeSystem = createExternalCs(); @@ -181,17 +178,17 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { TermConcept goodbye = new TermConcept(cs, "goodbye").setDisplay("Goodbye"); cs.getConcepts().add(goodbye); - + TermConcept dogs = new TermConcept(cs, "dogs").setDisplay("Dogs"); cs.getConcepts().add(dogs); - + TermConcept labrador = new TermConcept(cs, "labrador").setDisplay("Labrador"); dogs.addChild(labrador, RelationshipTypeEnum.ISA); TermConcept beagle = new TermConcept(cs, "beagle").setDisplay("Beagle"); dogs.addChild(beagle, RelationshipTypeEnum.ISA); - myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM,"SYSTEM NAME", "SYSTEM VERSION" , cs, table); + myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), URL_MY_CODE_SYSTEM, "SYSTEM NAME", "SYSTEM VERSION", cs, table); return codeSystem; } @@ -199,17 +196,17 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { //@formatter:off CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(URL_MY_CODE_SYSTEM); - codeSystem.setContent(CodeSystemContentMode.COMPLETE); + codeSystem.setContent(CodeSystemContentMode.COMPLETE); codeSystem .addConcept().setCode("A").setDisplay("Code A") - .addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA") - .addConcept(new ConceptDefinitionComponent().setCode("AAA").setDisplay("Code AAA")) - ) - .addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB")); + .addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA") + .addConcept(new ConceptDefinitionComponent().setCode("AAA").setDisplay("Code AAA")) + ) + .addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB")); codeSystem .addConcept().setCode("B").setDisplay("Code B") - .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA")) - .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB")); + .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA")) + .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB")); //@formatter:on myCodeSystemDao.create(codeSystem, mySrd); @@ -262,15 +259,15 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { //@formatter:off CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(URL_MY_CODE_SYSTEM); - codeSystem.setContent(CodeSystemContentMode.COMPLETE); + codeSystem.setContent(CodeSystemContentMode.COMPLETE); codeSystem .addConcept().setCode("A").setDisplay("Code A") - .addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA")) - .addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB")); + .addConcept(new ConceptDefinitionComponent().setCode("AA").setDisplay("Code AA")) + .addConcept(new ConceptDefinitionComponent().setCode("AB").setDisplay("Code AB")); codeSystem .addConcept().setCode("B").setDisplay("Code A") - .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code AA")) - .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB")); + .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code AA")) + .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB")); //@formatter:on IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); @@ -306,20 +303,20 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { valueSet.setUrl(URL_MY_VALUE_SET); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()) - .addConcept(new ConceptReferenceComponent().setCode("hello")) - .addConcept(new ConceptReferenceComponent().setCode("goodbye")); + .setSystem(codeSystem.getUrl()) + .addConcept(new ConceptReferenceComponent().setCode("hello")) + .addConcept(new ConceptReferenceComponent().setCode("goodbye")); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()) - .addFilter() - .setProperty("concept") - .setOp(FilterOperator.ISA) - .setValue("dogs"); - + .setSystem(codeSystem.getUrl()) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("dogs"); + myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, ""); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("")); logAndValidateValueSet(result); assertEquals(4, result.getExpansion().getTotal()); @@ -332,13 +329,13 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { @Disabled @Test public void testExpandWithOpEquals() { - - - ValueSet result = myValueSetDao.expandByIdentifier("http://hl7.org/fhir/ValueSet/doc-typecodes", ""); + + + ValueSet result = myValueSetDao.expandByIdentifier("http://hl7.org/fhir/ValueSet/doc-typecodes", new ValueSetExpansionOptions().setFilter("")); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result)); } - - + + @Test public void testExpandWithCodesAndDisplayFilterPartialOnFilter() { CodeSystem codeSystem = createExternalCsDogs(); @@ -347,20 +344,20 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { valueSet.setUrl(URL_MY_VALUE_SET); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()) - .addConcept(new ConceptReferenceComponent().setCode("hello")) - .addConcept(new ConceptReferenceComponent().setCode("goodbye")); + .setSystem(codeSystem.getUrl()) + .addConcept(new ConceptReferenceComponent().setCode("hello")) + .addConcept(new ConceptReferenceComponent().setCode("goodbye")); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()) - .addFilter() - .setProperty("concept") - .setOp(FilterOperator.ISA) - .setValue("dogs"); - + .setSystem(codeSystem.getUrl()) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("dogs"); + myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, "lab"); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("lab")); logAndValidateValueSet(result); assertEquals(1, result.getExpansion().getTotal()); @@ -377,20 +374,20 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { valueSet.setUrl(URL_MY_VALUE_SET); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()) - .addConcept(new ConceptReferenceComponent().setCode("hello")) - .addConcept(new ConceptReferenceComponent().setCode("goodbye")); + .setSystem(codeSystem.getUrl()) + .addConcept(new ConceptReferenceComponent().setCode("hello")) + .addConcept(new ConceptReferenceComponent().setCode("goodbye")); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()) - .addFilter() - .setProperty("concept") - .setOp(FilterOperator.ISA) - .setValue("dogs"); - + .setSystem(codeSystem.getUrl()) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("dogs"); + myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, "hel"); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("hel")); logAndValidateValueSet(result); assertEquals(1, result.getExpansion().getTotal()); @@ -408,7 +405,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl()); myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, "lab"); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("lab")); logAndValidateValueSet(result); assertEquals(1, result.getExpansion().getTotal()); @@ -512,7 +509,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { @Test public void testExpandWithIsAInExternalValueSetReindex() { TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(true); - + createExternalCsAndLocalVs(); // We're making sure that a reindex doesn't wipe out all of the @@ -524,7 +521,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { myTerminologyDeferredStorageSvc.saveDeferred(); myTerminologyDeferredStorageSvc.saveDeferred(); - IValidationSupport.LookupCodeResult lookupResults = myCodeSystemDao.lookupCode(new StringType("childAA"), new StringType(URL_MY_CODE_SYSTEM),null, mySrd); + IValidationSupport.LookupCodeResult lookupResults = myCodeSystemDao.lookupCode(new StringType("childAA"), new StringType(URL_MY_CODE_SYSTEM), null, mySrd); assertEquals(true, lookupResults.isFound()); ValueSet vs = new ValueSet(); @@ -569,7 +566,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { assertEquals("Unknown CodeSystem URI \"http://example.com/my_code_systemAA\" referenced from ValueSet", e.getMessage()); } } - + @Test public void testExpandWithSystemAndCodesInExternalValueSet() { createExternalCsAndLocalVs(); @@ -628,9 +625,9 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { valueSet.setUrl(URL_MY_VALUE_SET); valueSet.getCompose() .addInclude() - .setSystem(codeSystem.getUrl()); + .setSystem(codeSystem.getUrl()); - ValueSet result = myValueSetDao.expand(valueSet, ""); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("")); logAndValidateValueSet(result); assertEquals(5, result.getExpansion().getTotal()); @@ -711,7 +708,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { cs.setResource(table); TermConcept parentA = new TermConcept(cs, "ParentA").setDisplay("Parent A"); cs.getConcepts().add(parentA); - myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION" , cs, table); + myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(new ResourcePersistentId(table.getId()), "http://snomed.info/sct", "Snomed CT", "SYSTEM VERSION", cs, table); StringType code = new StringType("ParentA"); StringType system = new StringType("http://snomed.info/sct"); @@ -767,7 +764,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { myResourceReindexingSvc.forceReindexingPass(); myTerminologyDeferredStorageSvc.saveDeferred(); myTerminologyDeferredStorageSvc.saveDeferred(); - + // Again myResourceReindexingSvc.markAllResourcesForReindexing(); myResourceReindexingSvc.forceReindexingPass(); @@ -917,7 +914,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { } - + @Test public void testSearchCodeBelowLocalCodesystem() { createLocalCsAndVs(); @@ -1018,7 +1015,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { SearchParameterMap params; ourLog.info("testSearchCodeInEmptyValueSet without status"); - + params = new SearchParameterMap(); params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); @@ -1029,7 +1026,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); params.add(Observation.SP_STATUS, new TokenParam(null, "final")); assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); - + ourLog.info("testSearchCodeInEmptyValueSet done"); } @@ -1125,12 +1122,12 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { SearchParameterMap params; ourLog.info("testSearchCodeInEmptyValueSet without status"); - + params = new SearchParameterMap(); params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); try { myObservationDao.search(params); - } catch(InvalidRequestException e) { + } catch (InvalidRequestException e) { assertEquals("Unable to expand imported value set: Unable to find imported value set http://non_existant_VS", e.getMessage()); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValueSetTest.java index 9500b926ac7..a12be5c911a 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValueSetTest.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao.dstu3; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.entity.TermValueSet; import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; @@ -99,7 +100,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test { private boolean clearDeferredStorageQueue() { - if(!myTerminologyDeferredStorageSvc.isStorageQueueEmpty()) { + if (!myTerminologyDeferredStorageSvc.isStorageQueueEmpty()) { myTerminologyDeferredStorageSvc.saveAllDeferred(); return false; } else { @@ -155,7 +156,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test { * Filter with display name */ - expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd); + expanded = myValueSetDao.expand(myExtensionalVsId, new ValueSetExpansionOptions().setFilter("systolic"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off @@ -169,7 +170,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test { @Test @Disabled public void testExpandByIdentifier() { - ValueSet expanded = myValueSetDao.expandByIdentifier("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", "11378"); + ValueSet expanded = myValueSetDao.expandByIdentifier("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", new ValueSetExpansionOptions().setFilter("11378")); String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off @@ -188,7 +189,7 @@ public class FhirResourceDaoDstu3ValueSetTest extends BaseJpaDstu3Test { @Disabled public void testExpandByValueSet() throws IOException { ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); - ValueSet expanded = myValueSetDao.expand(toExpand, "11378"); + ValueSet expanded = myValueSetDao.expand(toExpand, new ValueSetExpansionOptions().setFilter("11378")); String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java index a35337b8a16..7e71ceab8ad 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithElasticSearchIT.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.test.utilities.docker.RequiresDocker; import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; @@ -169,7 +170,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest { ValueSet.ConceptSetComponent include = vs.getCompose().addInclude(); include.setSystem(URL_MY_CODE_SYSTEM); - ValueSet result = myValueSetDao.expand(vs, "child"); + ValueSet result = myValueSetDao.expand(vs, new ValueSetExpansionOptions().setFilter("child")); logAndValidateValueSet(result); @@ -187,7 +188,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest { ValueSet.ConceptSetComponent include = vs.getCompose().addInclude(); include.setSystem(URL_MY_CODE_SYSTEM); - ValueSet result = myValueSetDao.expand(vs, "chi"); + ValueSet result = myValueSetDao.expand(vs, new ValueSetExpansionOptions().setFilter("chi")); logAndValidateValueSet(result); @@ -205,7 +206,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest { ValueSet.ConceptSetComponent include = vs.getCompose().addInclude(); include.setSystem(URL_MY_CODE_SYSTEM); - ValueSet result = myValueSetDao.expand(vs, "hil"); + ValueSet result = myValueSetDao.expand(vs, new ValueSetExpansionOptions().setFilter("hil")); logAndValidateValueSet(result); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java index 5c653decb9a..661a4776d23 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao.r4; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; @@ -344,7 +345,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, ""); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("")); logAndValidateValueSet(result); assertEquals(2, result.getExpansion().getTotal()); @@ -379,7 +380,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, ""); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("")); logAndValidateValueSet(result); assertEquals(4, result.getExpansion().getTotal()); @@ -409,7 +410,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, "hel"); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("hel")); logAndValidateValueSet(result); assertEquals(1, result.getExpansion().getTotal()); @@ -427,7 +428,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { valueSet.getCompose().addInclude().setSystem(codeSystem.getUrl()); myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, "lab"); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("lab")); logAndValidateValueSet(result); assertEquals(1, result.getExpansion().getTotal()); @@ -457,7 +458,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { myValueSetDao.create(valueSet, mySrd); - ValueSet result = myValueSetDao.expand(valueSet, "lab"); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("lab")); logAndValidateValueSet(result); assertEquals(1, result.getExpansion().getTotal()); @@ -677,7 +678,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { public void testExpandWithOpEquals() { - ValueSet result = myValueSetDao.expandByIdentifier("http://hl7.org/fhir/ValueSet/doc-typecodes", ""); + ValueSet result = myValueSetDao.expandByIdentifier("http://hl7.org/fhir/ValueSet/doc-typecodes", new ValueSetExpansionOptions().setFilter("")); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(result)); } @@ -795,7 +796,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { .addInclude() .setSystem(codeSystem.getUrl()); - ValueSet result = myValueSetDao.expand(valueSet, ""); + ValueSet result = myValueSetDao.expand(valueSet, new ValueSetExpansionOptions().setFilter("")); logAndValidateValueSet(result); assertEquals(5, result.getExpansion().getTotal()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java index c531a58cd9f..7a702e63b49 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao.r4; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; @@ -258,8 +259,6 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test { obs.setEffective(DateTimeType.now()); obs.setStatus(ObservationStatus.FINAL); - OperationOutcome oo; - // Valid code obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123)); try { @@ -1702,7 +1701,8 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test { myTermReadSvc.preExpandDeferredValueSetsToTerminologyTables(); - ValueSet expansion = myValueSetDao.expand(id, null, 0, 10000, mySrd); + ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(0, 10000); + ValueSet expansion = myValueSetDao.expand(id, options, mySrd); ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); assertEquals(2, expansion.getExpansion().getContains().size()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetTest.java index 1311279136b..03ee310a43f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetTest.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao.r4; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -221,7 +222,7 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test { * Filter with display name */ - expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd); + expanded = myValueSetDao.expand(myExtensionalVsId, new ValueSetExpansionOptions().setFilter("systolic"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoR5ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoR5ValueSetTest.java index 2172ae6d808..a8b1dab9229 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoR5ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoR5ValueSetTest.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao.r5; import ca.uhn.fhir.context.support.IValidationSupport; +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet; @@ -226,7 +227,7 @@ public class FhirResourceDaoR5ValueSetTest extends BaseJpaR5Test { * Filter with display name */ - expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd); + expanded = myValueSetDao.expand(myExtensionalVsId, new ValueSetExpansionOptions().setFilter("systolic"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2ValueSetTest.java index c577f3abc27..5398279ba6f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2ValueSetTest.java @@ -1,21 +1,6 @@ package ca.uhn.fhir.jpa.provider; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.stringContainsInOrder; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.IOException; - -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.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.transaction.annotation.Transactional; - +import ca.uhn.fhir.context.support.ValueSetExpansionOptions; import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.ValueSet; @@ -24,12 +9,25 @@ import ca.uhn.fhir.model.primitive.CodeDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import ca.uhn.fhir.util.TestUtil; +import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +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.not; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2Test { - private IIdType myExtensionalVsId; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2ValueSetTest.class); + private IIdType myExtensionalVsId; @BeforeEach @Transactional @@ -38,7 +36,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 upload.setId(""); myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); } - + @Test public void testValidateCodeOperationByCodeAndSystemInstance() { Parameters respParam = ourClient @@ -51,7 +49,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); - + assertEquals(new BooleanDt(true), respParam.getParameter().get(0).getValue()); } @@ -67,7 +65,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); - + assertEquals("name", respParam.getParameter().get(0).getName()); assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue()); assertEquals("display", respParam.getParameter().get(1).getName()); @@ -75,7 +73,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 assertEquals("abstract", respParam.getParameter().get(2).getName()); assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue()); } - + @Test @Disabled public void testLookupOperationForBuiltInCode() { @@ -89,7 +87,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); - + assertEquals("name", respParam.getParameter().get(0).getName()); assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue()); assertEquals("display", respParam.getParameter().get(1).getName()); @@ -109,7 +107,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); - + assertEquals("name", respParam.getParameter().get(0).getName()); assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue()); assertEquals("display", respParam.getParameter().get(1).getName()); @@ -179,20 +177,20 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); assertThat(resp, - stringContainsInOrder("", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - )); + stringContainsInOrder("", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + )); /* * Filter with display name @@ -206,12 +204,12 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 .execute(); expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd); + expanded = myValueSetDao.expand(myExtensionalVsId, new ValueSetExpansionOptions().setFilter("systolic"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); assertThat(resp, stringContainsInOrder( - "", - "")); + "", + "")); /* * Filter with code @@ -227,10 +225,10 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); assertThat(resp, stringContainsInOrder( - "", - "")); + "", + "")); } - + @Test public void testExpandByIdentifier() { Parameters respParam = ourClient @@ -245,8 +243,8 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); assertThat(resp, stringContainsInOrder( - "", - "")); + "", + "")); assertThat(resp, not(containsString(""))); } @@ -254,7 +252,7 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 @Test public void testExpandByValueSet() throws IOException { ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml"); - + Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -267,8 +265,8 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); assertThat(resp, stringContainsInOrder( - "", - "")); + "", + "")); assertThat(resp, not(containsString(""))); } @@ -316,5 +314,5 @@ public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2 } } - + } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetNoVerCSNoVerTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetNoVerCSNoVerTest.java index 500eba52486..85831734d67 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetNoVerCSNoVerTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetNoVerCSNoVerTest.java @@ -8,9 +8,9 @@ import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermValueSet; import ca.uhn.fhir.jpa.entity.TermValueSetConcept; -import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation; import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum; import ca.uhn.fhir.jpa.model.entity.ResourceTable; +import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -38,6 +38,7 @@ import org.hl7.fhir.r4.model.IntegerType; 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.UrlType; import org.hl7.fhir.r4.model.ValueSet; import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r4.model.ValueSet.FilterOperator; @@ -53,12 +54,16 @@ import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Nonnull; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; 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.util.HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE; import static org.awaitility.Awaitility.await; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsStringIgnoringCase; import static org.hamcrest.Matchers.is; @@ -1037,6 +1042,165 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv testValidateCodeOperationByCodeAndSystemInstanceOnInstance(); } + + @Test + public void testExpandUsingHierarchy_PreStored_NotPreCalculated() { + createLocalCs(); + createHierarchicalVs(); + + myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless(); + + ValueSet expansion; + + // Non-hierarchical + myCaptureQueriesListener.clear(); + expansion = myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "url", new UrlType(URL_MY_VALUE_SET)) + .returnResourceType(ValueSet.class) + .execute(); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); + assertThat(toDirectCodes(expansion.getExpansion().getContains()), containsInAnyOrder("A", "AA", "AB", "AAA")); + assertEquals(19, myCaptureQueriesListener.getSelectQueries().size()); + assertEquals("ValueSet \"ValueSet.url[http://example.com/my_value_set]\" has not yet been pre-expanded. Performing in-memory expansion without parameters. Current status: NOT_EXPANDED | The ValueSet is waiting to be picked up and pre-expanded by a scheduled task.", expansion.getMeta().getExtensionString(EXT_VALUESET_EXPANSION_MESSAGE)); + + // Hierarchical + myCaptureQueriesListener.clear(); + expansion = myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "url", new UrlType(URL_MY_VALUE_SET)) + .andParameter(JpaConstants.OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY, new BooleanType("true")) + .returnResourceType(ValueSet.class) + .execute(); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); + assertThat(toDirectCodes(expansion.getExpansion().getContains()), containsInAnyOrder("A")); + assertThat(toDirectCodes(expansion.getExpansion().getContains().get(0).getContains()), containsInAnyOrder("AA", "AB")); + assertThat(toDirectCodes(expansion.getExpansion().getContains().get(0).getContains().stream().filter(t->t.getCode().equals("AA")).findFirst().orElseThrow(()->new IllegalArgumentException()).getContains()), containsInAnyOrder("AAA")); + assertEquals(16, myCaptureQueriesListener.getSelectQueries().size()); + + } + + @Test + public void testExpandUsingHierarchy_NotPreStored() { + createLocalCs(); + createHierarchicalVs(); + myLocalVs.setUrl(null); + + ValueSet expansion; + + // Non-hierarchical + myCaptureQueriesListener.clear(); + expansion = myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "valueSet", myLocalVs) + .returnResourceType(ValueSet.class) + .execute(); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); + assertThat(toDirectCodes(expansion.getExpansion().getContains()), containsInAnyOrder("A", "AA", "AB", "AAA")); + assertEquals(15, myCaptureQueriesListener.getSelectQueries().size()); + assertEquals(null, expansion.getMeta().getExtensionString(EXT_VALUESET_EXPANSION_MESSAGE)); + + // Hierarchical + myCaptureQueriesListener.clear(); + expansion = myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "valueSet", myLocalVs) + .andParameter(JpaConstants.OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY, new BooleanType("true")) + .returnResourceType(ValueSet.class) + .execute(); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); + assertThat(toDirectCodes(expansion.getExpansion().getContains()), containsInAnyOrder("A")); + assertThat(toDirectCodes(expansion.getExpansion().getContains().get(0).getContains()), containsInAnyOrder("AA", "AB")); + assertThat(toDirectCodes(expansion.getExpansion().getContains().get(0).getContains().stream().filter(t->t.getCode().equals("AA")).findFirst().orElseThrow(()->new IllegalArgumentException()).getContains()), containsInAnyOrder("AAA")); + assertEquals(14, myCaptureQueriesListener.getSelectQueries().size()); + + } + + @Test + public void testExpandUsingHierarchy_PreStored_PreCalculated() { + createLocalCs(); + createHierarchicalVs(); + + myLocalValueSetId = myValueSetDao.create(myLocalVs, mySrd).getId().toUnqualifiedVersionless(); + + ValueSet expansion; + + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + // Do a warm-up pass to precache anything that can be pre-cached + myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "url", new UrlType(URL_MY_VALUE_SET)) + .returnResourceType(ValueSet.class) + .execute(); + + // Non-hierarchical + myCaptureQueriesListener.clear(); + expansion = myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "url", new UrlType(URL_MY_VALUE_SET)) + .returnResourceType(ValueSet.class) + .execute(); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); + assertThat(toDirectCodes(expansion.getExpansion().getContains()), containsInAnyOrder("A", "AA", "AB", "AAA")); + assertEquals(3, myCaptureQueriesListener.getSelectQueries().size()); + assertEquals("ValueSet was expanded using a pre-calculated expansion", expansion.getMeta().getExtensionString(EXT_VALUESET_EXPANSION_MESSAGE)); + + // Hierarchical + myCaptureQueriesListener.clear(); + expansion = myClient + .operation() + .onType("ValueSet") + .named(JpaConstants.OPERATION_EXPAND) + .withParameter(Parameters.class, "url", new UrlType(URL_MY_VALUE_SET)) + .andParameter(JpaConstants.OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY, new BooleanType("true")) + .returnResourceType(ValueSet.class) + .execute(); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); + assertThat(toDirectCodes(expansion.getExpansion().getContains()), containsInAnyOrder("A")); + assertThat(toDirectCodes(expansion.getExpansion().getContains().get(0).getContains()), containsInAnyOrder("AA", "AB")); + assertThat(toDirectCodes(expansion.getExpansion().getContains().get(0).getContains().stream().filter(t->t.getCode().equals("AA")).findFirst().orElseThrow(()->new IllegalArgumentException()).getContains()), containsInAnyOrder("AAA")); + assertEquals(3, myCaptureQueriesListener.getSelectQueries().size()); + + } + + private void createHierarchicalVs() { + myLocalVs = new ValueSet(); + myLocalVs.setUrl(URL_MY_VALUE_SET); + myLocalVs + .getCompose() + .addInclude() + .setSystem(URL_MY_CODE_SYSTEM) + .addFilter() + .setProperty("concept") + .setOp(FilterOperator.ISA) + .setValue("A"); + myLocalVs + .getCompose() + .addInclude() + .setSystem(URL_MY_CODE_SYSTEM) + .addConcept() + .setCode("A"); + } + + public List toDirectCodes(List theContains) { + List collect = theContains.stream().map(t -> t.getCode()).collect(Collectors.toList()); + ourLog.info("Codes: {}", collect); + return collect; + } + private void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException { String url = ourServerBase + "/ValueSet/" + myLocalValueSetId.getIdPart() + "/$validate-code?system=" + diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulatorTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulatorTest.java index 16d3dc3d930..c2eeddb15f0 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulatorTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulatorTest.java @@ -42,7 +42,7 @@ public class ValueSetConceptAccumulatorTest { @Test public void testIncludeConcept() { for (int i = 0; i < 1000; i++) { - myAccumulator.includeConcept("sys", "code", "display"); + myAccumulator.includeConcept("sys", "code", "display", null, null); } verify(myValueSetConceptDao, times(1000)).save(any()); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4ElasticsearchIT.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4ElasticsearchIT.java index 23f79370f69..7680e88baec 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4ElasticsearchIT.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4ElasticsearchIT.java @@ -195,7 +195,7 @@ public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest { include.setSystem(CS_URL); myTermSvc.expandValueSet(null, vs, myValueSetCodeAccumulator); - verify(myValueSetCodeAccumulator, times(9)).includeConceptWithDesignations(anyString(), anyString(), nullable(String.class), anyCollection()); + verify(myValueSetCodeAccumulator, times(9)).includeConceptWithDesignations(anyString(), anyString(), nullable(String.class), anyCollection(), nullable(Long.class), nullable(String.class)); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java index 58634856eb6..f7ae6f80a2e 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java @@ -7,7 +7,6 @@ import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConceptDesignation; import ca.uhn.fhir.jpa.entity.TermValueSet; import ca.uhn.fhir.jpa.entity.TermValueSetConcept; -import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation; import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.util.JpaConstants; @@ -38,11 +37,10 @@ import java.io.IOException; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import java.util.stream.Stream; import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -228,7 +226,8 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { // ValueSet by ID { myCaptureQueriesListener.clear(); - ValueSet expandedValueSet = myValueSetDao.expand(vsId, "display value 100", 0, 1000, mySrd); + ValueSetExpansionOptions options = ValueSetExpansionOptions.forOffsetAndCount(0, 1000).setFilter("display value 100"); + ValueSet expandedValueSet = myValueSetDao.expand(vsId, options, mySrd); List codes = expandedValueSet.getExpansion().getContains().stream().map(t -> t.getCode()).collect(Collectors.toList()); assertThat(codes.toString(), codes, containsInAnyOrder("code100", "code1000", "code1001", "code1002", "code1003", "code1004")); @@ -300,7 +299,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { ValueSet expandedValueSet = myTermSvc.expandValueSet(null, input); ourLog.debug("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); - assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains( "code99" )); + assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains("code99")); // Make sure we used the pre-expanded version List selectQueries = myCaptureQueriesListener.getSelectQueries(); @@ -786,7 +785,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { assertEquals(1000, expandedValueSet.getExpansion().getParameter().get(1).getValueIntegerType().getValue().intValue()); assertEquals(codeSystem.getConcept().size() - expandedValueSet.getExpansion().getOffset(), expandedValueSet.getExpansion().getContains().size()); - assertThat(toCodes(expandedValueSet), is(equalTo(expandedConcepts.subList(1,expandedConcepts.size())))); + assertThat(toCodes(expandedValueSet), is(equalTo(expandedConcepts.subList(1, expandedConcepts.size())))); } @Test @@ -818,7 +817,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { assertEquals(1000, expandedValueSet.getExpansion().getParameter().get(1).getValueIntegerType().getValue().intValue()); assertEquals(codeSystem.getConcept().size() - expandedValueSet.getExpansion().getOffset(), expandedValueSet.getExpansion().getContains().size()); - assertThat(toCodes(expandedValueSet), is(equalTo(expandedConcepts.subList(1,expandedConcepts.size())))); + assertThat(toCodes(expandedValueSet), is(equalTo(expandedConcepts.subList(1, expandedConcepts.size())))); } @Test @@ -953,7 +952,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { include.setSystem(CS_URL); myTermSvc.expandValueSet(null, vs, myValueSetCodeAccumulator); - verify(myValueSetCodeAccumulator, times(9)).includeConceptWithDesignations(anyString(), anyString(), nullable(String.class), anyCollection()); + verify(myValueSetCodeAccumulator, times(9)).includeConceptWithDesignations(anyString(), anyString(), nullable(String.class), anyCollection(), nullable(Long.class), nullable(String.class)); } @Test @@ -1433,5 +1432,4 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { } - } diff --git a/hapi-fhir-jpaserver-batch/pom.xml b/hapi-fhir-jpaserver-batch/pom.xml index 781f0e34231..b4436c319ec 100644 --- a/hapi-fhir-jpaserver-batch/pom.xml +++ b/hapi-fhir-jpaserver-batch/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-cql/pom.xml b/hapi-fhir-jpaserver-cql/pom.xml index d7df70c1bea..440cd4e30e4 100644 --- a/hapi-fhir-jpaserver-cql/pom.xml +++ b/hapi-fhir-jpaserver-cql/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml @@ -144,13 +144,13 @@ ca.uhn.hapi.fhir hapi-fhir-test-utilities - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT test ca.uhn.hapi.fhir hapi-fhir-jpaserver-test-utilities - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT test diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 855dfe0501a..236fc33d3ab 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml @@ -55,13 +55,13 @@ ca.uhn.hapi.fhir hapi-fhir-test-utilities - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT test ca.uhn.hapi.fhir hapi-fhir-jpaserver-test-utilities - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT test diff --git a/hapi-fhir-jpaserver-migrate/pom.xml b/hapi-fhir-jpaserver-migrate/pom.xml index 767f5422571..ab2347ac99c 100644 --- a/hapi-fhir-jpaserver-migrate/pom.xml +++ b/hapi-fhir-jpaserver-migrate/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java index de5042f9a43..4e14b8594d7 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java @@ -87,6 +87,10 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_FORCED_ID").addIndex("20210309.2", "IDX_FORCEID_FID") .unique(false).withColumns("FORCED_ID"); + //-- ValueSet Concept Fulltext Indexing + version.onTable("TRM_VALUESET_CONCEPT").addColumn("20210406.1", "INDEX_STATUS").nullable().type(ColumnTypeEnum.LONG); + version.onTable("TRM_VALUESET_CONCEPT").addColumn("20210406.2", "SOURCE_DIRECT_PARENT_PIDS").nullable().type(ColumnTypeEnum.CLOB); + version.onTable("TRM_VALUESET_CONCEPT").addColumn("20210406.3", "SOURCE_PID").nullable().type(ColumnTypeEnum.LONG); } private void init530() { diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index fc6b066de31..8c915ff27c6 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java index 3cf09bb4efc..feb1fbf5bd2 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java @@ -218,6 +218,11 @@ public class JpaConstants { */ public static final String DEFAULT_PARTITION_NAME = "DEFAULT"; + /** + * Parameter for the $expand operation + */ + public static final String OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY = "includeHierarchy"; + /** * Non-instantiable */ diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 23fa53e26a7..0cccf93a45b 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index e1878aacf98..633843691b3 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 7f20b4b2dc5..e00e23537da 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index 9314f0dbd85..ffbe7a1164c 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml @@ -164,7 +164,7 @@ ca.uhn.hapi.fhir hapi-fhir-converter - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index 71c5ec9049a..6f7664a8f48 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index bdf8b874600..2524d2960e8 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index 6a615025f8d..58483804fd3 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index cea3284ea07..bb0460f5f2c 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index 729b752242d..ec97e7f6b0f 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT hapi-fhir-spring-boot-sample-client-okhttp diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index c70d6428ecc..b20cdc12fac 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT hapi-fhir-spring-boot-sample-server-jersey diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index 01709779112..1643433e6ef 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT hapi-fhir-spring-boot-samples diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index 81895a5dc6c..04d4fe39150 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 5798cb0a6f5..b3490ba702b 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index da1cff255bb..d80fff6935b 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 108cf5a0825..412d69d642c 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index f37268d1445..24f6bfd53d9 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index cffad70ec0e..035dabec631 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index fe444b0a1c9..67dd6dfeb59 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 72fd8b4b0ab..8760ce684e3 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index bbb540c8ded..654c33c28fe 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 305b835d2d1..1dfb066f20b 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index bef3d99f342..6aae3187f80 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 0e98d4c8ead..ecdbbd4a635 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 77b38d6c862..560106316d0 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index 222c7a6db50..68ae7002bdd 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index c3885abf4c3..9ac87f4b79d 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 1bbb77e484d..b180c3de905 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index d21005fb478..5e946ea683b 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml @@ -58,37 +58,37 @@ ca.uhn.hapi.fhir hapi-fhir-structures-dstu3 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-hl7org-dstu2 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-r4 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-r5 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-dstu2 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-dstu3 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-r4 - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT org.apache.velocity diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index 9497e5e2aea..b4a180ec8ca 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 8dfad0cf1c8..36b38d441db 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. https://hapifhir.io diff --git a/restful-server-example/pom.xml b/restful-server-example/pom.xml index 051b36516f5..37c4a874033 100644 --- a/restful-server-example/pom.xml +++ b/restful-server-example/pom.xml @@ -8,7 +8,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../pom.xml diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index c6e0d2c9d18..4e51e91c572 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index b399e7eae87..20a96ef3c9e 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index bb5a3413ee0..897bcbb0b07 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.4.0-PRE4-SNAPSHOT + 5.4.0-PRE5-SNAPSHOT ../../pom.xml