From 4f6be9d9a7c424f6bd065f007c821fe702023061 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Mon, 9 Nov 2020 14:46:15 -0500 Subject: [PATCH 01/10] Reduce test timeout --- .../ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java index 7bdbf1a4d9d..9eb61dabdf2 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java @@ -168,7 +168,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test { confProvider.setSearchParamRegistry(ourSearchParamRegistry); myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); - myFhirCtx.getRestfulClientFactory().setSocketTimeout(5000000); + myFhirCtx.getRestfulClientFactory().setSocketTimeout(20000); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); HttpClientBuilder builder = HttpClientBuilder.create(); From 881193cf245a766119f1018fd4e08512e03f4a58 Mon Sep 17 00:00:00 2001 From: ianmarshall Date: Mon, 9 Nov 2020 16:19:05 -0500 Subject: [PATCH 02/10] Truncate package descriptions that are longer than 200 characters. --- .../fhir/jpa/packages/JpaPackageCache.java | 10 ++++-- .../jpa/packages/JpaPackageCacheTest.java | 31 +++++++++++++++++- .../packages/package-davinci-cdex-0.2.0.tgz | Bin 0 -> 213767 bytes .../model/entity/NpmPackageVersionEntity.java | 5 +-- 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 hapi-fhir-jpaserver-base/src/test/resources/packages/package-davinci-cdex-0.2.0.tgz diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/JpaPackageCache.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/JpaPackageCache.java index ac651b16ecd..552aa1b53b8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/JpaPackageCache.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/JpaPackageCache.java @@ -217,10 +217,16 @@ public class JpaPackageCache extends BasePackageCacheManager implements IHapiPac } boolean currentVersion = updateCurrentVersionFlagForAllPackagesBasedOnNewIncomingVersion(thePackageId, packageVersionId); + String packageDesc; + if (npmPackage.description().length() > NpmPackageVersionEntity.PACKAGE_DESC_LENGTH) { + packageDesc = npmPackage.description().substring(0, NpmPackageVersionEntity.PACKAGE_DESC_LENGTH - 4) + "..."; + } else { + packageDesc = npmPackage.description(); + } if (currentVersion) { getProcessingMessages(npmPackage).add("Marking package " + thePackageId + "#" + thePackageVersionId + " as current version"); pkg.setCurrentVersionId(packageVersionId); - pkg.setDescription(npmPackage.description()); + pkg.setDescription(packageDesc); myPackageDao.save(pkg); } else { getProcessingMessages(npmPackage).add("Package " + thePackageId + "#" + thePackageVersionId + " is not the newest version"); @@ -232,7 +238,7 @@ public class JpaPackageCache extends BasePackageCacheManager implements IHapiPac packageVersion.setPackage(pkg); packageVersion.setPackageBinary(persistedPackage); packageVersion.setSavedTime(new Date()); - packageVersion.setDescription(npmPackage.description()); + packageVersion.setDescription(packageDesc); packageVersion.setFhirVersionId(npmPackage.fhirVersion()); packageVersion.setFhirVersion(fhirVersion); packageVersion.setCurrentVersion(currentVersion); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheTest.java index 33ca5efe37f..adef1a64ce8 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheTest.java @@ -1,7 +1,11 @@ package ca.uhn.fhir.jpa.packages; +import ca.uhn.fhir.jpa.dao.data.INpmPackageDao; +import ca.uhn.fhir.jpa.dao.data.INpmPackageVersionDao; import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; +import ca.uhn.fhir.util.JsonUtil; import org.hl7.fhir.utilities.npm.IPackageCacheManager; import org.hl7.fhir.utilities.npm.NpmPackage; import org.junit.jupiter.api.Test; @@ -10,13 +14,21 @@ import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; import java.io.InputStream; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; public class JpaPackageCacheTest extends BaseJpaR4Test { @Autowired - private IPackageCacheManager myPackageCacheManager; + private IHapiPackageCacheManager myPackageCacheManager; + + @Autowired + private INpmPackageDao myPackageDao; + @Autowired + private INpmPackageVersionDao myPackageVersionDao; + @Test public void testSavePackage() throws IOException { @@ -41,6 +53,23 @@ public class JpaPackageCacheTest extends BaseJpaR4Test { } + @Test + public void testSavePackageWithLongDescription() throws IOException { + try (InputStream stream = IgInstallerDstu3Test.class.getResourceAsStream("/packages/package-davinci-cdex-0.2.0.tgz")) { + myPackageCacheManager.addPackageToCache("hl7.fhir.us.davinci-cdex", "0.2.0", stream, "hl7.fhir.us.davinci-cdex"); + } + + NpmPackage pkg; + + pkg = myPackageCacheManager.loadPackage("hl7.fhir.us.davinci-cdex", null); + assertEquals("0.2.0", pkg.version()); + + assertEquals("This IG provides detailed guidance that helps implementers use FHIR-based interactions and resources relevant to support specific exchanges of clinical information between provider and payers (or ...", myPackageDao.findByPackageId("hl7.fhir.us.davinci-cdex").get().getDescription()); + assertEquals("This IG provides detailed guidance that helps implementers use FHIR-based interactions and resources relevant to support specific exchanges of clinical information between provider and payers (or ...", myPackageVersionDao.findByPackageIdAndVersion("hl7.fhir.us.davinci-cdex", "0.2.0").get().getDescription()); + + } + + @Test public void testSavePackageCorrectFhirVersion() { diff --git a/hapi-fhir-jpaserver-base/src/test/resources/packages/package-davinci-cdex-0.2.0.tgz b/hapi-fhir-jpaserver-base/src/test/resources/packages/package-davinci-cdex-0.2.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..05a56c4c558ed667dd195b46147df28e393fd4dd GIT binary patch literal 213767 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≪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 literal 0 HcmV?d00001 diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NpmPackageVersionEntity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NpmPackageVersionEntity.java index a51caf5656f..53b836a0fd4 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NpmPackageVersionEntity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/NpmPackageVersionEntity.java @@ -54,6 +54,7 @@ import java.util.List; public class NpmPackageVersionEntity { public static final int VERSION_ID_LENGTH = 200; + public static final int PACKAGE_DESC_LENGTH = 200; public static final int FHIR_VERSION_LENGTH = 10; @SequenceGenerator(name = "SEQ_NPM_PACKVER", sequenceName = "SEQ_NPM_PACKVER") @@ -74,9 +75,9 @@ public class NpmPackageVersionEntity { @Temporal(TemporalType.TIMESTAMP) @Column(name = "SAVED_TIME", nullable = false) private Date mySavedTime; - @Column(name = "PKG_DESC", nullable = true, length = 200) + @Column(name = "PKG_DESC", nullable = true, length = PACKAGE_DESC_LENGTH) private String myDescription; - @Column(name = "DESC_UPPER", nullable = true, length = 200) + @Column(name = "DESC_UPPER", nullable = true, length = PACKAGE_DESC_LENGTH) private String myDescriptionUpper; @Column(name = "CURRENT_VERSION", nullable = false) private boolean myCurrentVersion; From 40c34a45182825463e675450a31bae9b357c1e21 Mon Sep 17 00:00:00 2001 From: ianmarshall Date: Mon, 9 Nov 2020 16:36:37 -0500 Subject: [PATCH 03/10] Truncate package descriptions that are longer than 200 characters. --- .../2164-package-description-longer-than-200-characters.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2164-package-description-longer-than-200-characters.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2164-package-description-longer-than-200-characters.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2164-package-description-longer-than-200-characters.yaml new file mode 100644 index 00000000000..6db3880b1b8 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2164-package-description-longer-than-200-characters.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 2164 +title: "The JPA Package loader was failing if the package had a description longer than 200 characters. This has been fixed." From 63b7b379c2887c9b93c3af80ef3ba7a5c229f3c3 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Tue, 10 Nov 2020 11:01:13 -0500 Subject: [PATCH 04/10] Improve ValueSet filtering (#2162) * Improve filter search * Filter improvements * Tests passing * Test fixes * Fix transaction filter * Add changelog * Test fix * Update hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties Co-authored-by: Diederik Muylwyk * Update hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java Co-authored-by: Diederik Muylwyk * Resolve FIXME * Test fix * Update hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java Co-authored-by: Diederik Muylwyk Co-authored-by: Diederik Muylwyk --- .../ca/uhn/fhir/i18n/hapi-messages.properties | 3 + .../2162-improve-vs-expansion-filtering.yaml | 5 + .../dao/data/ITermValueSetConceptViewDao.java | 5 + .../jpa/dao/r4/FhirResourceDaoValueSetR4.java | 3 +- .../jpa/dao/tx/HapiTransactionService.java | 1 - .../jpa/search/SearchCoordinatorSvcImpl.java | 34 +- .../predicate/UriPredicateBuilder.java | 18 +- .../fhir/jpa/term/BaseTermReadSvcImpl.java | 443 ++++++++++-------- .../ca/uhn/fhir/jpa/term/ExpansionFilter.java | 98 ++++ .../jpa/term/IValueSetConceptAccumulator.java | 27 +- .../jpa/term/ValueSetConceptAccumulator.java | 5 +- ...ansionComponentWithConceptAccumulator.java | 108 ++++- .../FhirResourceDaoDstu3ValidateTest.java | 19 +- .../r4/FhirResourceDaoR4TerminologyTest.java | 1 + .../jpa/term/ValueSetExpansionR4Test.java | 278 ++++++++++- .../tasks/HapiFhirJpaMigrationTasks.java | 12 +- .../uhn/fhir/jpa/model/util/JpaConstants.java | 1 + 17 files changed, 777 insertions(+), 284 deletions(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2162-improve-vs-expansion-filtering.yaml create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ExpansionFilter.java diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties index d6a664c918d..75041ec815c 100644 --- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties +++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties @@ -1,5 +1,8 @@ ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.expansionRefersToUnknownCs=Unknown CodeSystem URI "{0}" referenced from ValueSet +ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.valueSetNotYetExpanded=ValueSet "{0}" has not yet been pre-expanded. Performing in-memory expansion without parameters. Current status: {1} | {2} +ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.valueSetNotYetExpanded_OffsetNotAllowed=ValueSet expansion can not combine "offset" with "ValueSet.compose.exclude" unless the ValueSet has been pre-expanded. ValueSet "{0}" must be pre-expanded for this operation to work. + # Core Library Messages ca.uhn.fhir.context.FhirContext.unknownResourceName=Unknown resource name "{0}" (this name is not known in FHIR version "{1}") diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2162-improve-vs-expansion-filtering.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2162-improve-vs-expansion-filtering.yaml new file mode 100644 index 00000000000..775946a3f34 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_2_0/2162-improve-vs-expansion-filtering.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 2162 +title: "When expanding a pre-expanded ValueSet using a filter, the filter was ignored and the pre-expansion was not used + resulting in an inefficient and potentially incorrect expansion. This has been corrected." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java index 1d192308de4..ae3889d0a79 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java @@ -1,6 +1,8 @@ package ca.uhn.fhir.jpa.dao.data; import ca.uhn.fhir.jpa.entity.TermValueSetConceptView; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -32,4 +34,7 @@ public interface ITermValueSetConceptViewDao extends JpaRepository= :from AND v.myConceptOrder < :to ORDER BY v.myConceptOrder") List findByTermValueSetId(@Param("from") int theFrom, @Param("to") int theTo, @Param("pid") Long theValueSetId); + @Query("SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND v.myConceptDisplay LIKE :display ORDER BY v.myConceptOrder") + List findByTermValueSetId(@Param("pid") Long theValueSetId, @Param("display") String theDisplay); + } 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 e93d8beccc9..554f9dfed8d 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 @@ -27,6 +27,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource; import ca.uhn.fhir.jpa.model.entity.ResourceTable; +import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -221,7 +222,7 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao private void addFilterIfPresent(String theFilter, ConceptSetComponent include) { if (ElementUtil.isEmpty(include.getConcept())) { if (isNotBlank(theFilter)) { - include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter); + include.addFilter().setProperty(JpaConstants.VALUESET_FILTER_DISPLAY).setOp(FilterOperator.EQUAL).setValue(theFilter); } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/tx/HapiTransactionService.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/tx/HapiTransactionService.java index c825fdf2816..34fcad258fb 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/tx/HapiTransactionService.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/tx/HapiTransactionService.java @@ -94,7 +94,6 @@ public class HapiTransactionService { } } - } /** diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java index 6a7053195ac..68527f6f4ec 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java @@ -37,8 +37,6 @@ import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.entity.SearchInclude; import ca.uhn.fhir.jpa.entity.SearchTypeEnum; import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails; -import ca.uhn.fhir.model.api.IQueryParameterType; -import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc; @@ -47,6 +45,7 @@ import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.util.InterceptorUtil; import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; +import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.Constants; @@ -468,7 +467,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { TransactionTemplate txTemplate = new TransactionTemplate(myManagedTxManager); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); return txTemplate.execute(t -> { - + // Load the results synchronously final List pids = new ArrayList<>(); @@ -668,6 +667,12 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { myRequestPartitionHelperService = theRequestPartitionHelperService; } + private boolean isWantCount(SearchParameterMap myParams, boolean wantOnlyCount) { + return wantOnlyCount || + SearchTotalModeEnum.ACCURATE.equals(myParams.getSearchTotalMode()) || + (myParams.getSearchTotalMode() == null && SearchTotalModeEnum.ACCURATE.equals(myDaoConfig.getDefaultTotalMode())); + } + /** * A search task is a Callable task that runs in * a thread pool to handle an individual search. One instance @@ -691,6 +696,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { private final ArrayList myUnsyncedPids = new ArrayList<>(); private final RequestDetails myRequest; private final RequestPartitionId myRequestPartitionId; + private final SearchRuntimeDetails mySearchRuntimeDetails; + private final Transaction myParentTransaction; private Search mySearch; private boolean myAbortRequested; private int myCountSavedTotal = 0; @@ -699,8 +706,6 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { private boolean myAdditionalPrefetchThresholdsRemaining; private List myPreviouslyAddedResourcePids; private Integer myMaxResultsToFetch; - private final SearchRuntimeDetails mySearchRuntimeDetails; - private final Transaction myParentTransaction; /** * Constructor @@ -1193,17 +1198,6 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { } } - private boolean isWantCount(SearchParameterMap myParams, boolean wantOnlyCount) { - return wantOnlyCount || - SearchTotalModeEnum.ACCURATE.equals(myParams.getSearchTotalMode()) || - (myParams.getSearchTotalMode() == null && SearchTotalModeEnum.ACCURATE.equals(myDaoConfig.getDefaultTotalMode())); - } - - private static boolean isWantOnlyCount(SearchParameterMap myParams) { - return SummaryEnum.COUNT.equals(myParams.getSummaryMode()) - | INTEGER_0.equals(myParams.getCount()); - } - public class SearchContinuationTask extends SearchTask { public SearchContinuationTask(Search theSearch, IDao theCallingDao, SearchParameterMap theParams, String theResourceType, RequestDetails theRequest, RequestPartitionId theRequestPartitionId) { @@ -1242,6 +1236,10 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { } + private static boolean isWantOnlyCount(SearchParameterMap myParams) { + return SummaryEnum.COUNT.equals(myParams.getSummaryMode()) + | INTEGER_0.equals(myParams.getCount()); + } public static void populateSearchEntity(SearchParameterMap theParams, String theResourceType, String theSearchUuid, String theQueryString, Search theSearch) { theSearch.setDeleted(false); @@ -1270,8 +1268,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { * Creates a {@link Pageable} using a start and end index */ @SuppressWarnings("WeakerAccess") - public static @Nullable - Pageable toPage(final int theFromIndex, int theToIndex) { + @Nullable + public static Pageable toPage(final int theFromIndex, int theToIndex) { int pageSize = theToIndex - theFromIndex; if (pageSize < 1) { return null; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/UriPredicateBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/UriPredicateBuilder.java index 9cc3bf4922a..ad3889c1bf6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/UriPredicateBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/UriPredicateBuilder.java @@ -77,6 +77,7 @@ public class UriPredicateBuilder extends BaseSearchParamPredicateBuilder { public Condition addPredicate(List theUriOrParameterList, String theParamName, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequestDetails) { List codePredicates = new ArrayList<>(); + boolean predicateIsHash = false; for (IQueryParameterType nextOr : theUriOrParameterList) { if (nextOr instanceof UriParam) { @@ -141,8 +142,8 @@ public class UriPredicateBuilder extends BaseSearchParamPredicateBuilder { Condition uriPredicate = null; if (theOperation == null || theOperation == SearchFilterParser.CompareOperation.eq) { long hashUri = ResourceIndexedSearchParamUri.calculateHashUri(getPartitionSettings(), getRequestPartitionId(), getResourceType(), theParamName, value); - Condition hashPredicate = BinaryCondition.equalTo(myColumnHashUri, generatePlaceholder(hashUri)); - codePredicates.add(hashPredicate); + uriPredicate = BinaryCondition.equalTo(myColumnHashUri, generatePlaceholder(hashUri)); + predicateIsHash = true; } else if (theOperation == SearchFilterParser.CompareOperation.ne) { uriPredicate = BinaryCondition.notEqualTo(myColumnUri, generatePlaceholder(value)); } else if (theOperation == SearchFilterParser.CompareOperation.co) { @@ -164,11 +165,7 @@ public class UriPredicateBuilder extends BaseSearchParamPredicateBuilder { theOperation.toString())); } - if (uriPredicate != null) { - long hashIdentity = BaseResourceIndexedSearchParam.calculateHashIdentity(getPartitionSettings(), getRequestPartitionId(), getResourceType(), theParamName); - BinaryCondition hashIdentityPredicate = BinaryCondition.equalTo(getColumnHashIdentity(), generatePlaceholder(hashIdentity)); - codePredicates.add(ComboCondition.and(hashIdentityPredicate, uriPredicate)); - } + codePredicates.add(uriPredicate); } } else { @@ -186,8 +183,11 @@ public class UriPredicateBuilder extends BaseSearchParamPredicateBuilder { } ComboCondition orPredicate = ComboCondition.or(codePredicates.toArray(new Condition[0])); - Condition outerPredicate = combineWithHashIdentityPredicate(getResourceType(), theParamName, orPredicate); - return outerPredicate; + if (predicateIsHash) { + return orPredicate; + } else { + return combineWithHashIdentityPredicate(getResourceType(), theParamName, orPredicate); + } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java index 00a23abb7c1..a8b244c2a2c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java @@ -66,6 +66,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.sched.HapiJob; import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition; +import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc; @@ -81,14 +82,17 @@ 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.CoverageIgnore; +import ca.uhn.fhir.util.FhirVersionIndependentConcept; +import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.ValidateUtil; -import ca.uhn.fhir.util.FhirVersionIndependentConcept; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; +import com.google.common.collect.ArrayListMultimap; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.time.DateUtils; @@ -137,6 +141,8 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.NoRollbackRuleAttribute; import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Nonnull; @@ -158,19 +164,22 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; import java.util.stream.Collectors; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isEmpty; @@ -248,66 +257,64 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { return cs != null; } - private void addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, TermConcept theConcept, boolean theAdd, AtomicInteger theCodeCounter, String theValueSetIncludeVersion) { + private boolean addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, TermConcept theConcept, boolean theAdd, String theValueSetIncludeVersion) { String codeSystem = theConcept.getCodeSystemVersion().getCodeSystem().getCodeSystemUri(); String code = theConcept.getCode(); String display = theConcept.getDisplay(); Collection designations = theConcept.getDesignations(); if (StringUtils.isNotEmpty(theValueSetIncludeVersion)) { - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, theCodeCounter, codeSystem + "|" + theValueSetIncludeVersion, code, display); + return addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, codeSystem + "|" + theValueSetIncludeVersion, code, display); } else { - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, theCodeCounter, codeSystem, code, display); + return addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, designations, theAdd, codeSystem, code, display); } } - private void addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, Collection theDesignations, boolean theAdd, AtomicInteger theCodeCounter, 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) { if (StringUtils.isNotEmpty(theCodeSystemVersion)) { if (isNoneBlank(theCodeSystem, theCode)) { if (theAdd && theAddedCodes.add(theCodeSystem + "|" + theCode)) { - theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem + "|" + theCodeSystemVersion, theCode, theDisplay, theDesignations); - theCodeCounter.incrementAndGet(); + theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem + "|" + theCodeSystemVersion, theCode, theDisplay, null); } if (!theAdd && theAddedCodes.remove(theCodeSystem + "|" + theCode)) { theValueSetCodeAccumulator.excludeConcept(theCodeSystem + "|" + theCodeSystemVersion, theCode); - theCodeCounter.decrementAndGet(); } } } else { if (theAdd && theAddedCodes.add(theCodeSystem + "|" + theCode)) { - theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, theDesignations); - theCodeCounter.incrementAndGet(); + theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, null); } if (!theAdd && theAddedCodes.remove(theCodeSystem + "|" + theCode)) { theValueSetCodeAccumulator.excludeConcept(theCodeSystem, theCode); - theCodeCounter.decrementAndGet(); } } } - private void addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, Collection theDesignations, boolean theAdd, AtomicInteger theCodeCounter, String theCodeSystem, String theCode, String theDisplay) { + private boolean addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, Collection theDesignations, boolean theAdd, String theCodeSystem, String theCode, String theDisplay) { if (isNoneBlank(theCodeSystem, theCode)) { if (theAdd && theAddedCodes.add(theCodeSystem + "|" + theCode)) { theValueSetCodeAccumulator.includeConceptWithDesignations(theCodeSystem, theCode, theDisplay, theDesignations); - theCodeCounter.incrementAndGet(); + return true; } if (!theAdd && theAddedCodes.remove(theCodeSystem + "|" + theCode)) { theValueSetCodeAccumulator.excludeConcept(theCodeSystem, theCode); - theCodeCounter.decrementAndGet(); + return true; } } + + return false; } - private void addConceptsToList(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, String theSystem, List theConcept, boolean theAdd, FhirVersionIndependentConcept theWantConceptOrNull) { + private void addConceptsToList(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, String theSystem, List theConcept, boolean theAdd, @Nonnull ExpansionFilter theExpansionFilter) { for (CodeSystem.ConceptDefinitionComponent next : theConcept) { if (isNoneBlank(theSystem, next.getCode())) { - if (theWantConceptOrNull == null || theWantConceptOrNull.getCode().equals(next.getCode())) { + if (!theExpansionFilter.hasCode() || theExpansionFilter.getCode().equals(next.getCode())) { addOrRemoveCode(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, next.getCode(), next.getDisplay()); } } - addConceptsToList(theValueSetCodeAccumulator, theAddedCodes, theSystem, next.getConcept(), theAdd, theWantConceptOrNull); + addConceptsToList(theValueSetCodeAccumulator, theAddedCodes, theSystem, next.getConcept(), theAdd, theExpansionFilter); } } @@ -387,28 +394,14 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { deleteValueSetForResource(theResourceTable); } - private ValueSet expandValueSetInMemory(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, FhirVersionIndependentConcept theWantConceptOrNull) { - - int maxCapacity = myDaoConfig.getMaximumExpansionSize(); - ValueSetExpansionComponentWithConceptAccumulator expansionComponent = new ValueSetExpansionComponentWithConceptAccumulator(myContext, maxCapacity); - expansionComponent.setIdentifier(UUID.randomUUID().toString()); - expansionComponent.setTimestamp(new Date()); - - AtomicInteger codeCounter = new AtomicInteger(0); - - expandValueSet(theExpansionOptions, theValueSetToExpand, expansionComponent, codeCounter, theWantConceptOrNull); - - expansionComponent.setTotal(codeCounter.get()); - - ValueSet valueSet = new ValueSet(); - valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); - valueSet.setCompose(theValueSetToExpand.getCompose()); - valueSet.setExpansion(expansionComponent); - return valueSet; - } @Override public List expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet) { + ExpansionFilter expansionFilter = ExpansionFilter.NO_FILTER; + return expandValueSet(theExpansionOptions, theValueSet, expansionFilter); + } + + private List expandValueSet(ValueSetExpansionOptions theExpansionOptions, String theValueSet, ExpansionFilter theExpansionFilter) { // 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 valueSet = fetchCanonicalValueSetFromCompleteContext(theValueSet); @@ -416,7 +409,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { throwInvalidValueSet(theValueSet); } - return expandValueSetAndReturnVersionIndependentConcepts(theExpansionOptions, valueSet, null); + return expandValueSetAndReturnVersionIndependentConcepts(theExpansionOptions, valueSet, theExpansionFilter); } @Override @@ -424,6 +417,47 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { public ValueSet expandValueSet(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand) { ValidateUtil.isNotNullOrThrowUnprocessableEntity(theValueSetToExpand, "ValueSet to expand can not be null"); + ValueSetExpansionOptions expansionOptions = provideExpansionOptions(theExpansionOptions); + int offset = expansionOptions.getOffset(); + int count = expansionOptions.getCount(); + + ValueSetExpansionComponentWithConceptAccumulator accumulator = new ValueSetExpansionComponentWithConceptAccumulator(myContext, count); + accumulator.setHardExpansionMaximumSize(myDaoConfig.getMaximumExpansionSize()); + accumulator.setSkipCountRemaining(offset); + accumulator.setIdentifier(UUID.randomUUID().toString()); + accumulator.setTimestamp(new Date()); + accumulator.setOffset(offset); + + if (theExpansionOptions != null) { + accumulator.addParameter().setName("offset").setValue(new IntegerType(offset)); + } + if (theExpansionOptions != null) { + accumulator.addParameter().setName("count").setValue(new IntegerType(count)); + } + + ExpansionFilter filter = ExpansionFilter.NO_FILTER; + + expandValueSetIntoAccumulator(theValueSetToExpand, theExpansionOptions, accumulator, filter, true); + + if (accumulator.getTotalConcepts() != null) { + accumulator.setTotal(accumulator.getTotalConcepts()); + } + + ValueSet valueSet = new ValueSet(); + valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); + valueSet.setCompose(theValueSetToExpand.getCompose()); + valueSet.setExpansion(accumulator); + + for (String next : accumulator.getMessages()) { + valueSet.getMeta().addExtension() + .setUrl(HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE) + .setValue(new StringType(next)); + } + + return valueSet; + } + + private void expandValueSetIntoAccumulator(ValueSet theValueSetToExpand, ValueSetExpansionOptions theExpansionOptions, IValueSetConceptAccumulator theAccumulator, ExpansionFilter theFilter, boolean theAdd) { Optional optionalTermValueSet; if (theValueSetToExpand.hasUrl()) { if (theValueSetToExpand.hasVersion()) { @@ -440,85 +474,87 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { optionalTermValueSet = Optional.empty(); } + /* + * ValueSet doesn't exist in pre-expansion database, so perform in-memory expansion + */ if (!optionalTermValueSet.isPresent()) { ourLog.debug("ValueSet is not present in terminology tables. Will perform in-memory expansion without parameters. {}", getValueSetInfo(theValueSetToExpand)); - return expandValueSetInMemory(theExpansionOptions, theValueSetToExpand, null); // In-memory expansion. - } - - TermValueSet termValueSet = optionalTermValueSet.get(); - - if (termValueSet.getExpansionStatus() != TermValueSetPreExpansionStatusEnum.EXPANDED) { - ourLog.warn("{} is present in terminology tables but not ready for persistence-backed invocation of operation $expand. Will perform in-memory expansion without parameters. Current status: {} | {}", - getValueSetInfo(theValueSetToExpand), termValueSet.getExpansionStatus().name(), termValueSet.getExpansionStatus().getDescription()); - return expandValueSetInMemory(theExpansionOptions, theValueSetToExpand, null); // In-memory expansion. - } - - ValueSet.ValueSetExpansionComponent expansionComponent = new ValueSet.ValueSetExpansionComponent(); - expansionComponent.setIdentifier(UUID.randomUUID().toString()); - expansionComponent.setTimestamp(new Date()); - - ValueSetExpansionOptions expansionOptions = provideExpansionOptions(theExpansionOptions); - int offset = expansionOptions.getOffset(); - int count = expansionOptions.getCount(); - populateExpansionComponent(expansionComponent, termValueSet, offset, count); - - ValueSet valueSet = new ValueSet(); - valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE); - valueSet.setCompose(theValueSetToExpand.getCompose()); - valueSet.setExpansion(expansionComponent); - return valueSet; - } - - private void populateExpansionComponent(ValueSet.ValueSetExpansionComponent theExpansionComponent, TermValueSet theTermValueSet, int theOffset, int theCount) { - int total = theTermValueSet.getTotalConcepts().intValue(); - theExpansionComponent.setTotal(total); - theExpansionComponent.setOffset(theOffset); - theExpansionComponent.addParameter().setName("offset").setValue(new IntegerType(theOffset)); - theExpansionComponent.addParameter().setName("count").setValue(new IntegerType(theCount)); - - if (theCount == 0) { + expandValueSet(theExpansionOptions, theValueSetToExpand, theAccumulator, theFilter); return; } - expandConcepts(theExpansionComponent, theTermValueSet, theOffset, theCount); + /* + * ValueSet exists in pre-expansion database, but pre-expansion is not yet complete so perform in-memory expansion + */ + TermValueSet termValueSet = optionalTermValueSet.get(); + if (termValueSet.getExpansionStatus() != TermValueSetPreExpansionStatusEnum.EXPANDED) { + String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "valueSetNotYetExpanded", getValueSetInfo(theValueSetToExpand), termValueSet.getExpansionStatus().name(), termValueSet.getExpansionStatus().getDescription()); + theAccumulator.addMessage(msg); + expandValueSet(theExpansionOptions, theValueSetToExpand, theAccumulator, theFilter); + return; + } + + /* + * ValueSet is pre-expanded in database so let's use that + */ + expandConcepts(theAccumulator, termValueSet, theFilter, theAdd); } - private void expandConcepts(ValueSet.ValueSetExpansionComponent theExpansionComponent, TermValueSet theTermValueSet, int theOffset, int theCount) { + + private void expandConcepts(IValueSetConceptAccumulator theAccumulator, TermValueSet theTermValueSet, ExpansionFilter theFilter, boolean theAdd) { + 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 = theOffset + theCount; - Collection conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(theOffset, toIndex, theTermValueSet.getId()); + int toIndex = offset + count; + + Collection conceptViews; + boolean wasFilteredResult = false; + if (!theFilter.getFilters().isEmpty() && JpaConstants.VALUESET_FILTER_DISPLAY.equals(theFilter.getFilters().get(0).getProperty()) && theFilter.getFilters().get(0).getOp() == ValueSet.FilterOperator.EQUAL) { + String displayValue = theFilter.getFilters().get(0).getValue().replace("%", "[%]") + "%"; + conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(theTermValueSet.getId(), displayValue); + wasFilteredResult = true; + } else { + conceptViews = myTermValueSetConceptViewDao.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 HashMap<>(); + Map pidToConcept = new LinkedHashMap<>(); + ArrayListMultimap pidToDesignations = ArrayListMultimap.create(); + for (TermValueSetConceptView conceptView : conceptViews) { Long conceptPid = conceptView.getConceptPid(); - ValueSet.ValueSetExpansionContainsComponent containsComponent; - if (!pidToConcept.containsKey(conceptPid)) { - containsComponent = theExpansionComponent.addContains(); - containsComponent.setSystem(conceptView.getConceptSystemUrl()); - containsComponent.setCode(conceptView.getConceptCode()); - containsComponent.setDisplay(conceptView.getConceptDisplay()); - pidToConcept.put(conceptPid, containsComponent); - } else { - containsComponent = pidToConcept.get(conceptPid); + String system = conceptView.getConceptSystemUrl(); + String code = conceptView.getConceptCode(); + String display = conceptView.getConceptDisplay(); + 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) { - ValueSet.ConceptReferenceDesignationComponent designationComponent = containsComponent.addDesignation(); - designationComponent.setLanguage(conceptView.getDesignationLang()); - designationComponent.setUse(new Coding( - conceptView.getDesignationUseSystem(), - conceptView.getDesignationUseCode(), - conceptView.getDesignationUseDisplay())); - designationComponent.setValue(conceptView.getDesignationVal()); + 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); @@ -530,6 +566,33 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } + 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); } @@ -549,25 +612,34 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { @Override @Transactional(propagation = Propagation.REQUIRED) public void expandValueSet(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator) { - expandValueSet(theExpansionOptions, theValueSetToExpand, theValueSetCodeAccumulator, new AtomicInteger(0), null); + expandValueSet(theExpansionOptions, theValueSetToExpand, theValueSetCodeAccumulator, ExpansionFilter.NO_FILTER); } @SuppressWarnings("ConstantConditions") - private void expandValueSet(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator, AtomicInteger theCodeCounter, FhirVersionIndependentConcept theWantConceptOrNull) { + private void expandValueSet(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpand, IValueSetConceptAccumulator theValueSetCodeAccumulator, @Nonnull ExpansionFilter theExpansionFilter) { Set addedCodes = new HashSet<>(); StopWatch sw = new StopWatch(); String valueSetInfo = getValueSetInfo(theValueSetToExpand); ourLog.debug("Working with {}", valueSetInfo); + // Offset can't be combined with excludes + Integer skipCountRemaining = theValueSetCodeAccumulator.getSkipCountRemaining(); + if (skipCountRemaining != null && skipCountRemaining > 0) { + if (theValueSetToExpand.getCompose().getExclude().size() > 0) { + String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "valueSetNotYetExpanded_OffsetNotAllowed", valueSetInfo); + throw new InvalidRequestException(msg); + } + } + // Handle includes ourLog.debug("Handling includes"); for (ValueSet.ConceptSetComponent include : theValueSetToExpand.getCompose().getInclude()) { for (int i = 0; ; i++) { int queryIndex = i; - Boolean shouldContinue = myTxTemplate.execute(t -> { + Boolean shouldContinue = executeInNewTransactionIfNeeded(() -> { boolean add = true; - return expandValueSetHandleIncludeOrExclude(theExpansionOptions, theValueSetCodeAccumulator, addedCodes, include, add, theCodeCounter, queryIndex, theWantConceptOrNull); + return expandValueSetHandleIncludeOrExclude(theExpansionOptions, theValueSetCodeAccumulator, addedCodes, include, add, queryIndex, theExpansionFilter); }); if (!shouldContinue) { break; @@ -575,20 +647,15 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } - // If the accumulator filled up, abort - if (theValueSetCodeAccumulator.getCapacityRemaining() != null && theValueSetCodeAccumulator.getCapacityRemaining() <= 0) { - String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "expansionTooLarge", myDaoConfig.getMaximumExpansionSize()); - throw new ExpansionTooCostlyException(msg); - } - // Handle excludes ourLog.debug("Handling excludes"); for (ValueSet.ConceptSetComponent exclude : theValueSetToExpand.getCompose().getExclude()) { for (int i = 0; ; i++) { int queryIndex = i; - Boolean shouldContinue = myTxTemplate.execute(t -> { + Boolean shouldContinue = executeInNewTransactionIfNeeded(() -> { boolean add = false; - return expandValueSetHandleIncludeOrExclude(theExpansionOptions, theValueSetCodeAccumulator, addedCodes, exclude, add, theCodeCounter, queryIndex, null); + ExpansionFilter expansionFilter = ExpansionFilter.NO_FILTER; + return expandValueSetHandleIncludeOrExclude(theExpansionOptions, theValueSetCodeAccumulator, addedCodes, exclude, add, queryIndex, expansionFilter); }); if (!shouldContinue) { break; @@ -603,47 +670,49 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { ourLog.debug("Done working with {} in {}ms", valueSetInfo, sw.getMillis()); } + /** + * Execute in a new transaction only if we aren't already in one. We do this because in some cases + * when performing a VS expansion we throw an {@link ExpansionTooCostlyException} and we don't want + * this to cause the TX to be marked a rollback prematurely. + */ + private T executeInNewTransactionIfNeeded(Supplier theAction) { + if (TransactionSynchronizationManager.isSynchronizationActive()) { + return theAction.get(); + } + return myTxTemplate.execute(t->theAction.get()); + } + private String getValueSetInfo(ValueSet theValueSet) { StringBuilder sb = new StringBuilder(); boolean isIdentified = false; - sb - .append("ValueSet:"); - if (theValueSet.hasId()) { - isIdentified = true; - sb - .append(" ValueSet.id[") - .append(theValueSet.getId()) - .append("]"); - } if (theValueSet.hasUrl()) { isIdentified = true; sb - .append(" ValueSet.url[") + .append("ValueSet.url[") .append(theValueSet.getUrl()) .append("]"); - } - if (theValueSet.hasIdentifier()) { + } else if (theValueSet.hasId()) { isIdentified = true; sb - .append(" ValueSet.identifier[") - .append(theValueSet.getIdentifierFirstRep().getSystem()) - .append("|") - .append(theValueSet.getIdentifierFirstRep().getValue()) + .append("ValueSet.id[") + .append(theValueSet.getId()) .append("]"); } if (!isIdentified) { - sb.append(" None of ValueSet.id, ValueSet.url, and ValueSet.identifier are provided."); + sb.append("Unidentified ValueSet"); } return sb.toString(); } - protected List expandValueSetAndReturnVersionIndependentConcepts(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpandR4, FhirVersionIndependentConcept theWantConceptOrNull) { - org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent expandedR4 = expandValueSetInMemory(theExpansionOptions, theValueSetToExpandR4, theWantConceptOrNull).getExpansion(); + protected List expandValueSetAndReturnVersionIndependentConcepts(ValueSetExpansionOptions theExpansionOptions, ValueSet theValueSetToExpandR4, @Nonnull ExpansionFilter theExpansionFilter) { + int maxCapacity = myDaoConfig.getMaximumExpansionSize(); + ValueSetExpansionComponentWithConceptAccumulator accumulator = new ValueSetExpansionComponentWithConceptAccumulator(myContext, maxCapacity); + expandValueSet(theExpansionOptions, theValueSetToExpandR4, accumulator, theExpansionFilter); ArrayList retVal = new ArrayList<>(); - for (org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent nextContains : expandedR4.getContains()) { + for (org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent nextContains : accumulator.getContains()) { retVal.add(new FhirVersionIndependentConcept(nextContains.getSystem(), nextContains.getCode(), nextContains.getDisplay(), nextContains.getVersion())); } return retVal; @@ -652,7 +721,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { /** * @return Returns true if there are potentially more results to process. */ - private Boolean expandValueSetHandleIncludeOrExclude(@Nullable ValueSetExpansionOptions theExpansionOptions, IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, ValueSet.ConceptSetComponent theIncludeOrExclude, boolean theAdd, AtomicInteger theCodeCounter, int theQueryIndex, FhirVersionIndependentConcept theWantConceptOrNull) { + private Boolean expandValueSetHandleIncludeOrExclude(@Nullable ValueSetExpansionOptions theExpansionOptions, IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, ValueSet.ConceptSetComponent theIncludeOrExclude, boolean theAdd, int theQueryIndex, @Nonnull ExpansionFilter theExpansionFilter) { String system = theIncludeOrExclude.getSystem(); boolean hasSystem = isNotBlank(system); @@ -660,7 +729,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { if (hasSystem) { - if (theWantConceptOrNull != null && theWantConceptOrNull.getSystem() != null && !system.equals(theWantConceptOrNull.getSystem())) { + if (theExpansionFilter.hasCode() && theExpansionFilter.getSystem() != null && !system.equals(theExpansionFilter.getSystem())) { return false; } @@ -669,13 +738,13 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(system); if (cs != null) { - return expandValueSetHandleIncludeOrExcludeUsingDatabase(theValueSetCodeAccumulator, theAddedCodes, theIncludeOrExclude, theAdd, theCodeCounter, theQueryIndex, theWantConceptOrNull, system, cs); + return expandValueSetHandleIncludeOrExcludeUsingDatabase(theValueSetCodeAccumulator, theAddedCodes, theIncludeOrExclude, theAdd, theQueryIndex, theExpansionFilter, system, cs); } else { - if (theIncludeOrExclude.getConcept().size() > 0 && theWantConceptOrNull != null) { - if (defaultString(theIncludeOrExclude.getSystem()).equals(theWantConceptOrNull.getSystem())) { - if (theIncludeOrExclude.getConcept().stream().noneMatch(t -> t.getCode().equals(theWantConceptOrNull.getCode()))) { + if (theIncludeOrExclude.getConcept().size() > 0 && theExpansionFilter.hasCode()) { + if (defaultString(theIncludeOrExclude.getSystem()).equals(theExpansionFilter.getSystem())) { + if (theIncludeOrExclude.getConcept().stream().noneMatch(t -> t.getCode().equals(theExpansionFilter.getCode()))) { return false; } } @@ -691,9 +760,9 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { // if someone creates a valueset that includes UCUM codes, since we don't have a CodeSystem resource for those // but CommonCodeSystemsTerminologyService can validate individual codes. List includedConcepts = null; - if (theWantConceptOrNull != null) { + if (theExpansionFilter.hasCode()) { includedConcepts = new ArrayList<>(); - includedConcepts.add(theWantConceptOrNull); + includedConcepts.add(theExpansionFilter.toFhirVersionIndependentConcept()); } else if (!theIncludeOrExclude.getConcept().isEmpty()) { includedConcepts = theIncludeOrExclude .getConcept() @@ -737,7 +806,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { if (!theIncludeOrExclude.getConcept().isEmpty()) { for (ValueSet.ConceptReferenceComponent next : theIncludeOrExclude.getConcept()) { String nextCode = next.getCode(); - if (theWantConceptOrNull == null || theWantConceptOrNull.getCode().equals(nextCode)) { + if (!theExpansionFilter.hasCode() || theExpansionFilter.getCode().equals(nextCode)) { if (isNoneBlank(system, nextCode) && !theAddedCodes.contains(system + "|" + nextCode)) { CodeSystem.ConceptDefinitionComponent code = findCode(codeSystemFromContext.getConcept(), nextCode); @@ -751,7 +820,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } else { List concept = codeSystemFromContext.getConcept(); - addConceptsToList(theValueSetCodeAccumulator, theAddedCodes, system, concept, theAdd, theWantConceptOrNull); + addConceptsToList(theValueSetCodeAccumulator, theAddedCodes, system, concept, theAdd, theExpansionFilter); } return false; @@ -760,44 +829,20 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } else if (hasValueSet) { for (CanonicalType nextValueSet : theIncludeOrExclude.getValueSet()) { - ourLog.debug("Starting {} expansion around ValueSet: {}", (theAdd ? "inclusion" : "exclusion"), nextValueSet.getValueAsString()); + String valueSetUrl = nextValueSet.getValueAsString(); + ourLog.debug("Starting {} expansion around ValueSet: {}", (theAdd ? "inclusion" : "exclusion"), valueSetUrl); - List expanded = expandValueSet(theExpansionOptions, nextValueSet.getValueAsString()); - Map uriToCodeSystem = new HashMap<>(); + ExpansionFilter subExpansionFilter = new ExpansionFilter(theExpansionFilter, theIncludeOrExclude.getFilter(), theValueSetCodeAccumulator.getCapacityRemaining()); - for (FhirVersionIndependentConcept nextConcept : expanded) { - if (theAdd) { + // 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. - if (!uriToCodeSystem.containsKey(nextConcept.getSystem())) { - TermCodeSystem codeSystem = myCodeSystemDao.findByCodeSystemUri(nextConcept.getSystem()); - uriToCodeSystem.put(nextConcept.getSystem(), codeSystem); - } - - TermCodeSystem codeSystem = uriToCodeSystem.get(nextConcept.getSystem()); - if (codeSystem != null) { - TermCodeSystemVersion termCodeSystemVersion; - if (nextConcept.getSystemVersion() != null) { - termCodeSystemVersion = myCodeSystemVersionDao.findByCodeSystemPidAndVersion(codeSystem.getPid(), nextConcept.getSystemVersion()); - } else { - termCodeSystemVersion = codeSystem.getCurrentVersion(); - } - myConceptDao - .findByCodeSystemAndCode(termCodeSystemVersion, nextConcept.getCode()) - .ifPresent(concept -> - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, concept, theAdd, theCodeCounter, nextConcept.getSystemVersion()) - ); - } else { - // This will happen if we're expanding against a built-in (part of FHIR) ValueSet that - // isn't actually in the database anywhere - Collection emptyCollection = Collections.emptyList(); - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, emptyCollection, theAdd, theCodeCounter, nextConcept.getSystem(), nextConcept.getSystemVersion(), nextConcept.getCode(), nextConcept.getDisplay()); - } - } - if (isNoneBlank(nextConcept.getSystem(), nextConcept.getCode()) && !theAdd && theAddedCodes.remove(nextConcept.getSystem() + "|" + nextConcept.getCode())) { - theValueSetCodeAccumulator.excludeConcept(nextConcept.getSystem(), nextConcept.getCode()); - } + ValueSet valueSet = fetchCanonicalValueSetFromCompleteContext(valueSetUrl); + if (valueSet == null) { + throw new ResourceNotFoundException("Unknown ValueSet: " + UrlUtil.escapeUrlParam(valueSetUrl)); } + expandValueSetIntoAccumulator(valueSet, theExpansionOptions, theValueSetCodeAccumulator, subExpansionFilter, theAdd); + } return false; @@ -810,7 +855,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } @Nonnull - private Boolean expandValueSetHandleIncludeOrExcludeUsingDatabase(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, ValueSet.ConceptSetComponent theIncludeOrExclude, boolean theAdd, AtomicInteger theCodeCounter, int theQueryIndex, FhirVersionIndependentConcept theWantConceptOrNull, String theSystem, TermCodeSystem theCs) { + private Boolean expandValueSetHandleIncludeOrExcludeUsingDatabase(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, ValueSet.ConceptSetComponent theIncludeOrExclude, boolean theAdd, int theQueryIndex, @Nonnull ExpansionFilter theExpansionFilter, String theSystem, TermCodeSystem theCs) { String includeOrExcludeVersion = theIncludeOrExclude.getVersion(); TermCodeSystemVersion csv; if (isEmpty(includeOrExcludeVersion)) { @@ -825,7 +870,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { * since we're going to do it without the database. */ if (myFulltextSearchSvc == null) { - expandWithoutHibernateSearch(theValueSetCodeAccumulator, csv, theAddedCodes, theIncludeOrExclude, theSystem, theAdd, theCodeCounter); + expandWithoutHibernateSearch(theValueSetCodeAccumulator, csv, theAddedCodes, theIncludeOrExclude, theSystem, theAdd); return false; } @@ -837,8 +882,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { bool.must(qb.keyword().onField("myCodeSystemVersionPid").matching(csv.getPid()).createQuery()); - if (theWantConceptOrNull != null) { - bool.must(qb.keyword().onField("myCode").matching(theWantConceptOrNull.getCode()).createQuery()); + if (theExpansionFilter.hasCode()) { + bool.must(qb.keyword().onField("myCode").matching(theExpansionFilter.getCode()).createQuery()); } /* @@ -850,7 +895,12 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } else { codeSystemUrlAndVersion = theSystem; } - handleFilters(bool, codeSystemUrlAndVersion, qb, theIncludeOrExclude); + for (ValueSet.ConceptSetFilterComponent nextFilter : theIncludeOrExclude.getFilter()) { + handleFilter(codeSystemUrlAndVersion, qb, bool, nextFilter); + } + for (ValueSet.ConceptSetFilterComponent nextFilter : theExpansionFilter.getFilters()) { + handleFilter(codeSystemUrlAndVersion, qb, bool, nextFilter); + } Query luceneQuery = bool.createQuery(); @@ -917,21 +967,22 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { StopWatch swForBatch = new StopWatch(); AtomicInteger countForBatch = new AtomicInteger(0); - List resultList = jpaQuery.getResultList(); + List resultList = jpaQuery.getResultList(); int resultsInBatch = resultList.size(); int firstResult = jpaQuery.getFirstResult(); + int delta = 0; for (Object next : resultList) { count.incrementAndGet(); countForBatch.incrementAndGet(); TermConcept concept = (TermConcept) next; - try { - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, concept, theAdd, theCodeCounter, includeOrExcludeVersion); - } catch (ExpansionTooCostlyException e) { - return false; + boolean added = addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, concept, theAdd, includeOrExcludeVersion); + if (added) { + delta++; } } ourLog.debug("Batch expansion for {} with starting index of {} produced {} results in {}ms", (theAdd ? "inclusion" : "exclusion"), firstResult, countForBatch, swForBatch.getMillis()); + theValueSetCodeAccumulator.incrementOrDecrementTotalConcepts(theAdd, delta); if (resultsInBatch < maxResultsPerBatch) { ourLog.debug("Expansion for {} produced {} results in {}ms", (theAdd ? "inclusion" : "exclusion"), count, sw.getMillis()); @@ -959,14 +1010,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } - private void handleFilters(BooleanJunction theBool, String theCodeSystemIdentifier, QueryBuilder theQb, ValueSet.ConceptSetComponent theIncludeOrExclude) { - if (theIncludeOrExclude.getFilter().size() > 0) { - for (ValueSet.ConceptSetFilterComponent nextFilter : theIncludeOrExclude.getFilter()) { - handleFilter(theCodeSystemIdentifier, theQb, theBool, nextFilter); - } - } - } - private void handleFilter(String theCodeSystemIdentifier, QueryBuilder theQb, BooleanJunction theBool, ValueSet.ConceptSetFilterComponent theFilter) { if (isBlank(theFilter.getValue()) && theFilter.getOp() == null && isBlank(theFilter.getProperty())) { return; @@ -1264,7 +1307,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } } - private void expandWithoutHibernateSearch(IValueSetConceptAccumulator theValueSetCodeAccumulator, TermCodeSystemVersion theVersion, Set theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd, AtomicInteger theCodeCounter) { + private void expandWithoutHibernateSearch(IValueSetConceptAccumulator theValueSetCodeAccumulator, TermCodeSystemVersion theVersion, Set theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd) { ourLog.trace("Hibernate search is not enabled"); if (theValueSetCodeAccumulator instanceof ValueSetExpansionComponentWithConceptAccumulator) { @@ -1277,7 +1320,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { if (theInclude.getConcept().isEmpty()) { for (TermConcept next : theVersion.getConcepts()) { - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, null, theAdd, theCodeCounter, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay()); + addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay()); } } @@ -1285,7 +1328,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { if (!theSystem.equals(theInclude.getSystem()) && isNotBlank(theSystem)) { continue; } - addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, null, theAdd, theCodeCounter, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay()); + addCodeIfNotAlreadyAdded(theValueSetCodeAccumulator, theAddedCodes, theAdd, theSystem, theInclude.getVersion(), next.getCode(), next.getDisplay()); } @@ -1447,14 +1490,13 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { @Nullable private TermCodeSystemVersion getCurrentCodeSystemVersion(String theCodeSystemIdentifier) { - String myVersion = getVersionFromIdentifier(theCodeSystemIdentifier); - String key = theCodeSystemIdentifier; - TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(key.toString(), t -> myTxTemplate.execute(tx -> { + String version = getVersionFromIdentifier(theCodeSystemIdentifier); + TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(theCodeSystemIdentifier, t -> myTxTemplate.execute(tx -> { TermCodeSystemVersion csv = null; TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(getUrlFromIdentifier(theCodeSystemIdentifier)); if (cs != null) { - if (myVersion != null) { - csv = myCodeSystemVersionDao.findByCodeSystemPidAndVersion(cs.getPid(), myVersion); + if (version != null) { + csv = myCodeSystemVersionDao.findByCodeSystemPidAndVersion(cs.getPid(), version); } else if (cs.getCurrentVersion() != null) { csv = cs.getCurrentVersion(); } @@ -1642,7 +1684,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { */ String conceptMapUrl = termConceptMap.getUrl(); String conceptMapVersion = termConceptMap.getVersion(); - Optional optionalExistingTermConceptMapByUrl = null; + Optional optionalExistingTermConceptMapByUrl; if (isBlank(conceptMapVersion)) { optionalExistingTermConceptMapByUrl = myConceptMapDao.findTermConceptMapByUrlAndNullVersion(conceptMapUrl); } else { @@ -1776,9 +1818,10 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { // We have a ValueSet to pre-expand. try { ValueSet valueSet = txTemplate.execute(t -> { - TermValueSet refreshedValueSetToExpand = myValueSetDao.findById(valueSetToExpand.getId()).get(); + TermValueSet refreshedValueSetToExpand = myValueSetDao.findById(valueSetToExpand.getId()).orElseThrow(()->new IllegalStateException("Unknown VS ID: " + valueSetToExpand.getId())); return getValueSetFromResourceTable(refreshedValueSetToExpand.getResource()); }); + assert valueSet != null; ValueSetConceptAccumulator accumulator = new ValueSetConceptAccumulator(valueSetToExpand, myValueSetDao, myValueSetConceptDao, myValueSetConceptDesignationDao); expandValueSet(null, valueSet, accumulator); @@ -2604,6 +2647,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { String systemVersion = theCodeSystemIdentifierType != null ? getVersionFromIdentifier(theCodeSystemIdentifierType.getValueAsString()): null; if (theCodingType != null) { Coding canonicalizedCoding = toCanonicalCoding(theCodingType); + assert canonicalizedCoding != null; // Shouldn't be null, since theCodingType isn't code = canonicalizedCoding.getCode(); system = canonicalizedCoding.getSystem(); systemVersion = canonicalizedCoding.getVersion(); @@ -2675,7 +2719,6 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { String code = theCode; - String version = theVersion; String display = theDisplay; if (haveCodeableConcept) { @@ -2689,7 +2732,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } code = nextCoding.getCode(); display = nextCoding.getDisplay(); - CodeValidationResult nextValidation = codeSystemValidateCode(codeSystemUrl, version, code, display); + CodeValidationResult nextValidation = codeSystemValidateCode(codeSystemUrl, theVersion, code, display); if (nextValidation.isOk() || i == codeableConcept.getCoding().size() - 1) { return nextValidation; } @@ -2705,7 +2748,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { display = coding.getDisplay(); } - return codeSystemValidateCode(codeSystemUrl, version, code, display); + return codeSystemValidateCode(codeSystemUrl, theVersion, code, display); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ExpansionFilter.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ExpansionFilter.java new file mode 100644 index 00000000000..ee5a067aa4c --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ExpansionFilter.java @@ -0,0 +1,98 @@ +package ca.uhn.fhir.jpa.term; + +/*- + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2020 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import ca.uhn.fhir.util.FhirVersionIndependentConcept; +import org.apache.commons.lang3.Validate; +import org.hl7.fhir.r4.model.ValueSet; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collections; +import java.util.List; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +class ExpansionFilter { + + public static final ExpansionFilter NO_FILTER = new ExpansionFilter(null, null); + private final String myCode; + private final String mySystem; + private final List myFilters; + private final Integer myMaxCount; + /** + * Constructor + */ + ExpansionFilter(String theSystem, String theCode) { + this(theSystem, theCode, Collections.emptyList(), null); + } + + /** + * Constructor + */ + ExpansionFilter(ExpansionFilter theExpansionFilter, List theFilters, Integer theMaxCount) { + this(theExpansionFilter.getSystem(), theExpansionFilter.getCode(), theFilters, theMaxCount); + } + + /** + * Constructor + */ + ExpansionFilter(@Nullable String theSystem, @Nullable String theCode, @Nonnull List theFilters, Integer theMaxCount) { + Validate.isTrue(isNotBlank(theSystem) == isNotBlank(theCode)); + Validate.notNull(theFilters); + + mySystem = theSystem; + myCode = theCode; + myFilters = theFilters; + myMaxCount = theMaxCount; + } + + public List getFilters() { + return myFilters; + } + + boolean hasCode() { + return myCode != null; + } + + String getCode() { + return myCode; + } + + String getSystem() { + return mySystem; + } + + /** + * Converts the system/code in this filter to a FhirVersionIndependentConcept. This method + * should not be called if {@link #hasCode()} returns false + */ + @Nonnull + public FhirVersionIndependentConcept toFhirVersionIndependentConcept() { + Validate.isTrue(hasCode()); + + return new FhirVersionIndependentConcept(mySystem, myCode); + } + + public Integer getMaxCount() { + return myMaxCount; + } +} 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 db098111343..66db9e09013 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 @@ -33,11 +33,36 @@ public interface IValueSetConceptAccumulator { void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, @Nullable Collection theDesignations); - void excludeConcept(String theSystem, String theCode); + /** + * @return Returns true if the code was actually present and was removed + */ + boolean excludeConcept(String theSystem, String theCode); @Nullable default Integer getCapacityRemaining() { return null; } + @Nullable + default Integer getSkipCountRemaining() { + return null; + } + + @Nullable + default void consumeSkipCount(int theSkipCountToConsume) { + // nothing + } + + /** + * Add or subtract from the total concept count (this is not necessarily the same thing as the number of concepts in + * the accumulator, since the offset and count parameters applied to the expansion can cause + * concepts to not actually be added. + * + * @param theAdd If true, increment. If false, decrement. + * @param theDelta The number of codes to add or subtract + */ + default void incrementOrDecrementTotalConcepts(boolean theAdd, int theDelta) { + // 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 525b85c45b0..3a1d618c3d4 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 @@ -81,9 +81,9 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { } @Override - public void excludeConcept(String theSystem, String theCode) { + public boolean excludeConcept(String theSystem, String theCode) { if (isAnyBlank(theSystem, theCode)) { - return; + return false; } // Get existing entity so it can be deleted. @@ -114,6 +114,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { ourLog.info("Have excluded {} concepts from ValueSet[{}]", myConceptsExcluded, myTermValueSet.getUrl()); } } + return false; } private TermValueSetConcept saveConcept(String theSystem, String theCode, String theDisplay) { 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 6005d871f3a..e401a108b0f 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 @@ -25,19 +25,25 @@ import ca.uhn.fhir.jpa.entity.TermConceptDesignation; import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException; import ca.uhn.fhir.model.api.annotation.Block; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; -import ca.uhn.fhir.util.HapiExtensions; import org.apache.commons.lang3.StringUtils; -import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.ValueSet; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; @Block() public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.ValueSetExpansionComponent implements IValueSetConceptAccumulator { private final int myMaxCapacity; private final FhirContext myContext; - private int myConceptsCount; + private int mySkipCountRemaining; + private int myHardExpansionMaximumSize; + private List myMessages; + private int myAddedConcepts; + private Integer myTotalConcepts; /** * Constructor @@ -46,27 +52,40 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V * an {@link InternalErrorException} */ ValueSetExpansionComponentWithConceptAccumulator(FhirContext theContext, int theMaxCapacity) { - myContext = theContext; myMaxCapacity = theMaxCapacity; - myConceptsCount = 0; + myContext = theContext; } - @Nullable + @Nonnull @Override public Integer getCapacityRemaining() { - return myMaxCapacity - myConceptsCount; + return (myMaxCapacity - myAddedConcepts) + mySkipCountRemaining; + } + + public List getMessages() { + if (myMessages == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(myMessages); } @Override public void addMessage(String theMessage) { - addExtension() - .setUrl(HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE) - .setValue(new StringType(theMessage)); + if (myMessages == null) { + myMessages = new ArrayList<>(); + } + myMessages.add(theMessage); } @Override public void includeConcept(String theSystem, String theCode, String theDisplay) { + if (mySkipCountRemaining > 0) { + mySkipCountRemaining--; + return; + } + incrementConceptsCount(); + ValueSet.ValueSetExpansionContainsComponent contains = this.addContains(); setSystemAndVersion(theSystem, contains); contains.setCode(theCode); @@ -75,7 +94,13 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V @Override public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection theDesignations) { + if (mySkipCountRemaining > 0) { + mySkipCountRemaining--; + return; + } + incrementConceptsCount(); + ValueSet.ValueSetExpansionContainsComponent contains = this.addContains(); setSystemAndVersion(theSystem, contains); contains.setCode(theCode); @@ -95,11 +120,22 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V } @Override - public void excludeConcept(String theSystem, String theCode) { + public void consumeSkipCount(int theSkipCountToConsume) { + mySkipCountRemaining -= theSkipCountToConsume; + } + + @Nullable + @Override + public Integer getSkipCountRemaining() { + return mySkipCountRemaining; + } + + @Override + public boolean excludeConcept(String theSystem, String theCode) { String excludeSystem; String excludeSystemVersion; int versionSeparator = theSystem.indexOf("|"); - if(versionSeparator > -1) { + if (versionSeparator > -1) { excludeSystemVersion = theSystem.substring(versionSeparator + 1); excludeSystem = theSystem.substring(0, versionSeparator); } else { @@ -107,22 +143,47 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V excludeSystemVersion = null; } if (excludeSystemVersion != null) { - this.getContains().removeIf(t -> + return this.getContains().removeIf(t -> excludeSystem.equals(t.getSystem()) && - theCode.equals(t.getCode()) && - excludeSystemVersion.equals(t.getVersion())); + theCode.equals(t.getCode()) && + excludeSystemVersion.equals(t.getVersion())); } else { - this.getContains().removeIf(t -> - theSystem.equals(t.getSystem()) && - theCode.equals(t.getCode())); + return this.getContains().removeIf(t -> + theSystem.equals(t.getSystem()) && + theCode.equals(t.getCode())); } } private void incrementConceptsCount() { - if (++myConceptsCount > myMaxCapacity) { + Integer capacityRemaining = getCapacityRemaining(); + if (capacityRemaining == 0) { String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "expansionTooLarge", myMaxCapacity); throw new ExpansionTooCostlyException(msg); } + + if (myHardExpansionMaximumSize > 0 && myAddedConcepts > myHardExpansionMaximumSize) { + String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "expansionTooLarge", myHardExpansionMaximumSize); + throw new ExpansionTooCostlyException(msg); + } + + myAddedConcepts++; + } + + public Integer getTotalConcepts() { + return myTotalConcepts; + } + + @Override + public void incrementOrDecrementTotalConcepts(boolean theAdd, int theDelta) { + int delta = theDelta; + if (!theAdd) { + delta = -delta; + } + if (myTotalConcepts == null) { + myTotalConcepts = delta; + } else { + myTotalConcepts = myTotalConcepts + delta; + } } private void setSystemAndVersion(String theSystemAndVersion, ValueSet.ValueSetExpansionContainsComponent myComponent) { @@ -130,11 +191,18 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V int versionSeparator = theSystemAndVersion.lastIndexOf('|'); if (versionSeparator != -1) { myComponent.setVersion(theSystemAndVersion.substring(versionSeparator + 1)); - myComponent.setSystem(theSystemAndVersion.substring(0,versionSeparator)); + myComponent.setSystem(theSystemAndVersion.substring(0, versionSeparator)); } else { myComponent.setSystem(theSystemAndVersion); } } } + public void setSkipCountRemaining(int theSkipCountRemaining) { + mySkipCountRemaining = theSkipCountRemaining; + } + + public void setHardExpansionMaximumSize(int theHardExpansionMaximumSize) { + myHardExpansionMaximumSize = theHardExpansionMaximumSize; + } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java index 350bf1aa0ab..8b50cd2c2ed 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java @@ -32,7 +32,9 @@ import org.springframework.test.util.AopTestUtils; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -100,7 +102,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test { @Test - public void testValidateQuestionnaireResponseWithValueSetIncludingCompleteCodeSystem() throws IOException { + public void testExpandLocalCodeSystemWithExplicitCodes() throws IOException { CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/dstu3/iar/CodeSystem-iar-citizenship-status.xml"); myCodeSystemDao.create(cs); @@ -110,18 +112,9 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test { ValueSet expansion = myValueSetDao.expandByIdentifier("http://ccim.on.ca/fhir/iar/ValueSet/iar-citizenship-status", null); ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expansion)); -// Questionnaire q = loadResourceFromClasspath(Questionnaire.class,"/dstu3/iar/Questionnaire-iar-test.xml" ); -// myQuestionnaireDao.create(q); -// -// -// -// Bundle bundleForValidation = loadResourceFromClasspath(Bundle.class, "/dstu3/iar/Bundle-for-validation.xml"); -// try { -// MethodOutcome outcome = myBundleDao.validate(bundleForValidation, null, null, null, null, null, null); -// ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome.getOperationOutcome())); -// } catch (PreconditionFailedException e) { -// ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome())); -// } + assertThat(expansion.getExpansion().getContains().stream().map(t->t.getCode()).collect(Collectors.toList()), containsInAnyOrder( + "CDN", "PR", "TR", "REF", "UNK", "ASKU" + )); } 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 b589f843df2..b1887af5705 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 @@ -1015,6 +1015,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { myAllergyIntoleranceDao.create(ai3, mySrd).getId().toUnqualifiedVersionless().getValue(); SearchParameterMap params; + params = new SearchParameterMap(); params.add(AllergyIntolerance.SP_CLINICAL_STATUS, new TokenParam(null, "active")); assertThat(toUnqualifiedVersionlessIdValues(myAllergyIntoleranceDao.search(params)), containsInAnyOrder(id1)); 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 40850b23eaf..d24cb78e467 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 @@ -10,8 +10,11 @@ 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.custom.CustomTerminologySet; +import ca.uhn.fhir.jpa.util.SqlQuery; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.HapiExtensions; import com.google.common.collect.Lists; import org.hl7.fhir.instance.model.api.IIdType; @@ -31,9 +34,12 @@ import javax.annotation.Nonnull; import java.io.IOException; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.empty; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -87,6 +93,260 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { assertEquals(24, expandedValueSet.getExpansion().getContains().size()); } + + @Test + public void testExpandInline_IncludeCodeSystem_FilterOnDisplay_NoFilter() throws Exception { + loadAndPersistCodeSystemWithDesignations(HttpVerb.PUT); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .setSystem("http://acme.org"); + ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input); + ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertEquals(24, expandedValueSet.getExpansion().getTotal()); + } + + @Test + public void testExpandInline_IncludeCodeSystem_FilterOnDisplay_ExactFilter() throws Exception { + loadAndPersistCodeSystemWithDesignations(HttpVerb.PUT); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .setSystem("http://acme.org") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("Systolic blood pressure--inspiration"); + + ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input); + ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertEquals(1, expandedValueSet.getExpansion().getTotal()); + assertThat(expandedValueSet.getExpansion().getContains().stream().map(t -> t.getDisplay()).collect(Collectors.toList()), containsInAnyOrder( + "Systolic blood pressure--inspiration" + )); + } + + @Test + public void testExpandInline_IncludeCodeSystem_FilterOnDisplay_LeftMatchFilter() throws Exception { + loadAndPersistCodeSystemWithDesignations(HttpVerb.PUT); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .setSystem("http://acme.org") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("Systolic blood pressure 1"); + + ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input); + ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertEquals(3, expandedValueSet.getExpansion().getTotal()); + assertThat(expandedValueSet.getExpansion().getContains().stream().map(t -> t.getDisplay()).collect(Collectors.toList()), containsInAnyOrder( + "Systolic blood pressure 1 hour minimum", + "Systolic blood pressure 1 hour mean", + "Systolic blood pressure 1 hour maximum" + )); + } + + @Test + public void testExpandInline_IncludePreExpandedValueSetByUri_FilterOnDisplay_LeftMatch_SelectAll() { + myDaoConfig.setPreExpandValueSets(true); + create100ConceptsCodeSystemAndValueSet(); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 9"); + + myCaptureQueriesListener.clear(); + ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input); + ourLog.debug("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains( + "code9", "code90", "code91", "code92", "code93", "code94", "code95", "code96", "code97", "code98", "code99" + )); + assertEquals(11, expandedValueSet.getExpansion().getContains().size(), toCodes(expandedValueSet).toString()); + assertEquals(11, expandedValueSet.getExpansion().getTotal()); + + // Make sure we used the pre-expanded version + List selectQueries = myCaptureQueriesListener.getSelectQueries(); + String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase(); + assertThat(lastSelectQuery, containsString("concept_display like 'display value 9%'")); + + } + + @Test + public void testExpandInline_IncludePreExpandedValueSetByUri_FilterOnDisplay_LeftMatch_SelectRange() { + myDaoConfig.setPreExpandValueSets(true); + create100ConceptsCodeSystemAndValueSet(); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 9"); + + myCaptureQueriesListener.clear(); + ValueSetExpansionOptions expansionOptions = new ValueSetExpansionOptions() + .setOffset(3) + .setCount(4); + ValueSet expandedValueSet = myTermSvc.expandValueSet(expansionOptions, input); + ourLog.debug("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains( + "code92", "code93", "code94", "code95" + )); + assertEquals(4, expandedValueSet.getExpansion().getContains().size(), toCodes(expandedValueSet).toString()); + assertEquals(11, expandedValueSet.getExpansion().getTotal()); + + // Make sure we used the pre-expanded version + List selectQueries = myCaptureQueriesListener.getSelectQueries(); + String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase(); + assertThat(lastSelectQuery, containsString("concept_display like 'display value 9%'")); + + } + + + @Test + public void testExpandInline_IncludePreExpandedValueSetByUri_ExcludeCodes_FilterOnDisplay_LeftMatch_SelectAll() { + myDaoConfig.setPreExpandValueSets(true); + create100ConceptsCodeSystemAndValueSet(); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 9"); + input.getCompose() + .addExclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 90"); + + myCaptureQueriesListener.clear(); + ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input); + ourLog.debug("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains( + "code9", "code91", "code92", "code93", "code94", "code95", "code96", "code97", "code98", "code99" + )); + assertEquals(10, expandedValueSet.getExpansion().getContains().size(), toCodes(expandedValueSet).toString()); + assertEquals(10, expandedValueSet.getExpansion().getTotal()); + + // Make sure we used the pre-expanded version + List selectQueries = myCaptureQueriesListener.getSelectQueries(); + String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase(); + assertThat(lastSelectQuery, containsString("concept_display like 'display value 90%'")); + + } + + + @Test + public void testExpandInline_IncludePreExpandedValueSetByUri_ExcludeCodes_FilterOnDisplay_LeftMatch_SelectRange() { + myDaoConfig.setPreExpandValueSets(true); + create100ConceptsCodeSystemAndValueSet(); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 9"); + input.getCompose() + .addExclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 90"); + + myCaptureQueriesListener.clear(); + ValueSetExpansionOptions options = new ValueSetExpansionOptions(); + options.setOffset(3); + options.setCount(4); + try { + myTermSvc.expandValueSet(options, input); + fail(); + } catch (InvalidRequestException e) { + assertEquals("ValueSet expansion can not combine \"offset\" with \"ValueSet.compose.exclude\" unless the ValueSet has been pre-expanded. ValueSet \"Unidentified ValueSet\" must be pre-expanded for this operation to work.", e.getMessage()); + } + } + + + public void create100ConceptsCodeSystemAndValueSet() { + CodeSystem cs = new CodeSystem(); + cs.setUrl("http://foo/cs"); + cs.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT); + myCodeSystemDao.create(cs); + + CustomTerminologySet additions = new CustomTerminologySet(); + for (int i = 0; i < 100; i++) { + additions.addRootConcept("code" + i, "display value " + i); + } + myTermCodeSystemStorageSvc.applyDeltaCodeSystemsAdd("http://foo/cs", additions); + + ValueSet vs = new ValueSet(); + vs.setUrl("http://foo/vs"); + vs.getCompose().addInclude().setSystem("http://foo/cs"); + myValueSetDao.create(vs); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + } + + @Test + public void testExpandInline_IncludeNonPreExpandedValueSetByUri_FilterOnDisplay_LeftMatch() { + myDaoConfig.setPreExpandValueSets(true); + create100ConceptsCodeSystemAndValueSet(); + + ValueSet input = new ValueSet(); + input.getCompose() + .addInclude() + .addValueSet("http://foo/vs") + .addFilter() + .setProperty(JpaConstants.VALUESET_FILTER_DISPLAY) + .setOp(ValueSet.FilterOperator.EQUAL) + .setValue("display value 9"); + + myCaptureQueriesListener.clear(); + ValueSet expandedValueSet = myTermSvc.expandValueSet(new ValueSetExpansionOptions(), input); + ourLog.debug("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); + + assertThat(toCodes(expandedValueSet).toString(), toCodes(expandedValueSet), contains( + "code9", "code90", "code91", "code92", "code93", "code94", "code95", "code96", "code97", "code98", "code99" + )); + assertEquals(11, expandedValueSet.getExpansion().getContains().size(), toCodes(expandedValueSet).toString()); + assertEquals(11, expandedValueSet.getExpansion().getTotal(), toCodes(expandedValueSet).toString()); + + // Make sure we used the pre-expanded version + List selectQueries = myCaptureQueriesListener.getSelectQueries(); + String lastSelectQuery = selectQueries.get(selectQueries.size() - 1).getSql(true, true).toLowerCase(); + assertThat(lastSelectQuery, containsString("concept_display like 'display value 9%'")); + } + + @Nonnull + public List toCodes(ValueSet theExpandedValueSet) { + return theExpandedValueSet.getExpansion().getContains().stream().map(t -> t.getCode()).collect(Collectors.toList()); + } + @SuppressWarnings("SpellCheckingInspection") @Test public void testExpandTermValueSetAndChildren() throws Exception { @@ -115,11 +375,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getTotal()); assertEquals(myDaoConfig.getPreExpandValueSetsDefaultOffset(), expandedValueSet.getExpansion().getOffset()); - assertEquals(2, expandedValueSet.getExpansion().getParameter().size()); - assertEquals("offset", expandedValueSet.getExpansion().getParameter().get(0).getName()); - assertEquals(0, expandedValueSet.getExpansion().getParameter().get(0).getValueIntegerType().getValue().intValue()); - assertEquals("count", expandedValueSet.getExpansion().getParameter().get(1).getName()); - assertEquals(1000, expandedValueSet.getExpansion().getParameter().get(1).getValueIntegerType().getValue().intValue()); + assertEquals(0, expandedValueSet.getExpansion().getParameter().size()); assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getContains().size()); @@ -337,11 +593,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getTotal()); assertEquals(myDaoConfig.getPreExpandValueSetsDefaultOffset(), expandedValueSet.getExpansion().getOffset()); - assertEquals(2, expandedValueSet.getExpansion().getParameter().size()); - assertEquals("offset", expandedValueSet.getExpansion().getParameter().get(0).getName()); - assertEquals(0, expandedValueSet.getExpansion().getParameter().get(0).getValueIntegerType().getValue().intValue()); - assertEquals("count", expandedValueSet.getExpansion().getParameter().get(1).getName()); - assertEquals(1000, expandedValueSet.getExpansion().getParameter().get(1).getValueIntegerType().getValue().intValue()); + assertEquals(0, expandedValueSet.getExpansion().getParameter().size()); assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getContains().size()); @@ -796,7 +1048,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome); ourLog.info(encoded); - Extension extensionByUrl = outcome.getExpansion().getExtensionByUrl(HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE); + Extension extensionByUrl = outcome.getMeta().getExtensionByUrl(HapiExtensions.EXT_VALUESET_EXPANSION_MESSAGE); assertEquals("Unknown CodeSystem URI \"http://unknown-system\" referenced from ValueSet", extensionByUrl.getValueAsPrimitive().getValueAsString()); } @@ -877,8 +1129,8 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test { ValueSet.ConceptSetComponent include = vs.getCompose().addInclude(); include.setSystem(CS_URL); try { - myTermSvc.expandValueSet(null, vs); - fail(); + ValueSet expansion = myTermSvc.expandValueSet(null, vs); + fail("Expanded to " + expansion.getExpansion().getContains().size() + " but max was " + myDaoConfig.getMaximumExpansionSize()); } catch (InternalErrorException e) { assertEquals("Expansion of ValueSet produced too many codes (maximum 50) - Operation aborted!", e.getMessage()); } 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 75805f40de7..5b380224189 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 @@ -134,7 +134,7 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { init510_20200706_to_20200714(); Builder.BuilderWithTableName empiLink = version.onTable("MPI_LINK"); - empiLink.addColumn("20200715.1", "VERSION").nonNullable().type(ColumnTypeEnum.STRING, EmpiLink.VERSION_LENGTH); + empiLink.addColumn("20200715.1", "VERSION").nonNullable().type(ColumnTypeEnum.STRING, 16); empiLink.addColumn("20200715.2", "EID_MATCH").nullable().type(ColumnTypeEnum.BOOLEAN); empiLink.addColumn("20200715.3", "NEW_PERSON").nullable().type(ColumnTypeEnum.BOOLEAN); empiLink.addColumn("20200715.4", "VECTOR").nullable().type(ColumnTypeEnum.LONG); @@ -143,11 +143,11 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { init510_20200725(); //EMPI Target Type - empiLink.addColumn("20200727.1","TARGET_TYPE").nullable().type(ColumnTypeEnum.STRING, EmpiLink.TARGET_TYPE_LENGTH); + empiLink.addColumn("20200727.1","TARGET_TYPE").nullable().type(ColumnTypeEnum.STRING, 40); //ConceptMap add version for search Builder.BuilderWithTableName trmConceptMap = version.onTable("TRM_CONCEPT_MAP"); - trmConceptMap.addColumn("20200910.1", "VER").nullable().type(ColumnTypeEnum.STRING, TermConceptMap.MAX_VER_LENGTH); + trmConceptMap.addColumn("20200910.1", "VER").nullable().type(ColumnTypeEnum.STRING, 200); trmConceptMap.dropIndex("20200910.2", "IDX_CONCEPT_MAP_URL"); trmConceptMap.addIndex("20200910.3", "IDX_CONCEPT_MAP_URL").unique(true).withColumns("URL", "VER"); @@ -155,15 +155,15 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { Builder.BuilderWithTableName trmCodeSystemVer = version.onTable("TRM_CODESYSTEM_VER"); trmCodeSystemVer.addIndex("20200923.1", "IDX_CODESYSTEM_AND_VER").unique(true).withColumns("CODESYSTEM_PID", "CS_VERSION_ID"); Builder.BuilderWithTableName trmValueSet = version.onTable("TRM_VALUESET"); - trmValueSet.addColumn("20200923.2", "VER").nullable().type(ColumnTypeEnum.STRING, TermValueSet.MAX_VER_LENGTH); + trmValueSet.addColumn("20200923.2", "VER").nullable().type(ColumnTypeEnum.STRING, 200); trmValueSet.dropIndex("20200923.3", "IDX_VALUESET_URL"); trmValueSet.addIndex("20200923.4", "IDX_VALUESET_URL").unique(true).withColumns("URL", "VER"); //Term ValueSet Component add system version Builder.BuilderWithTableName trmValueSetComp = version.onTable("TRM_VALUESET_CONCEPT"); - trmValueSetComp.addColumn("20201028.1", "SYSTEM_VER").nullable().type(ColumnTypeEnum.STRING, TermCodeSystemVersion.MAX_VERSION_LENGTH); + trmValueSetComp.addColumn("20201028.1", "SYSTEM_VER").nullable().type(ColumnTypeEnum.STRING, 200); trmValueSetComp.dropIndex("20201028.2", "IDX_VS_CONCEPT_CS_CD"); - trmValueSetComp.addIndex("20201028.3", "IDX_VS_CONCEPT_CS_CD").unique(true).withColumns("VALUESET_PID", "SYSTEM_URL", "SYSTEM_VER", "CODEVAL"); + trmValueSetComp.addIndex("20201028.3", "IDX_VS_CONCEPT_CS_CODE").unique(true).withColumns("VALUESET_PID", "SYSTEM_URL", "SYSTEM_VER", "CODEVAL"); } protected void init510_20200725() { 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 5ac6d30d2e2..eacc62ca757 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 @@ -202,6 +202,7 @@ public class JpaConstants { * URL for extension on a Phonetic String SearchParameter indicating that text values should be phonetically indexed with the named encoder */ public static final String EXT_SEARCHPARAM_PHONETIC_ENCODER = "http://hapifhir.io/fhir/StructureDefinition/searchparameter-phonetic-encoder"; + public static final String VALUESET_FILTER_DISPLAY = "display"; /** * Non-instantiable From ed953d82f811478ad30b4da013cbc3e4094e4a62 Mon Sep 17 00:00:00 2001 From: IanMMarshall <49525404+IanMMarshall@users.noreply.github.com> Date: Fri, 13 Nov 2020 14:12:25 -0500 Subject: [PATCH 05/10] Rename index that was recently changed. (#2173) * Restoring name of index that was changed in migration task. * Rename TermValueSetConcept index that was recently changed. Co-authored-by: ianmarshall --- .../main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e0d2f7326f7..ebcda85216e 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 @@ -40,7 +40,7 @@ import static org.apache.commons.lang3.StringUtils.length; * bork up migration tasks. */ @Table(name = "TRM_VALUESET_CONCEPT", uniqueConstraints = { - @UniqueConstraint(name = "IDX_VS_CONCEPT_CS_CD", columnNames = {"VALUESET_PID", "SYSTEM_URL", "SYSTEM_VER", "CODEVAL"}), + @UniqueConstraint(name = "IDX_VS_CONCEPT_CS_CODE", columnNames = {"VALUESET_PID", "SYSTEM_URL", "SYSTEM_VER", "CODEVAL"}), @UniqueConstraint(name = "IDX_VS_CONCEPT_ORDER", columnNames = {"VALUESET_PID", "VALUESET_ORDER"}) }) @Entity() From 16003162fd20b389a8399f8e9910fb4fe4810603 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Fri, 13 Nov 2020 15:27:58 -0500 Subject: [PATCH 06/10] Address #2172 --- .../ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md index 92028f2dfcb..4e2a9971cb6 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md @@ -389,7 +389,7 @@ Tags have very specific semantics, which may not be obvious simply by using the ## Accessing Tags in a Read / VRead / Search Method -Tags are stored within a resource object, in the Resource.meta element. +Tags are stored within a resource object, in the Resource.meta element. It is important to note that changing a resources tags will not cause a version update to that resource. In a server implementation, you may populate your tags into the returned resource(s) and HAPI will automatically place these tags into the response headers (for read/vread) or the bundle category tags (for search). The following example illustrates how to return tags from a server method. This example shows how to supply tags in a read method, but the same approach applies to vread and search operations as well. @@ -415,6 +415,11 @@ To work with tags in a create/update method, the pattern used in the read exampl {{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|createTags}} ``` +## Removing Tags + +In order to remove a tag, it does not suffice to remove it from the resource. Tags can be removed using the [Resource Operation Meta Delete](https://www.hl7.org/fhir/resource-operation-meta-delete.html), which takes a Parameter +definining which tags to delete. + # Handling _summary and _elements The `_summary` and `_elements` parameters are automatically handled by the server, so no coding is required to make this work. From 8f95ad4c0f5014526577cc6e1f839c9601e1fd60 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Fri, 13 Nov 2020 15:35:06 -0500 Subject: [PATCH 07/10] fix typo :) --- .../ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md index 4e2a9971cb6..8e20f8975e4 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md @@ -409,7 +409,7 @@ Within a [Type Create](#type_create) or [Instance Update](#instance_update) meth Note that FHIR specifies that in an update method, any tags supplied by the client are copied to the newly saved version, as well as any tags the existing version had. -To work with tags in a create/update method, the pattern used in the read examples above is simply revered. In a server, the resource which is passed in will be populated with any tags that the client supplied: +To work with tags in a create/update method, the pattern used in the read examples above is simply reversed. In a server, the resource which is passed in will be populated with any tags that the client supplied: ```java {{snippet:classpath:/ca/uhn/hapi/fhir/docs/RestfulPatientResourceProviderMore.java|createTags}} From 1048df4d872a7ae0cd19afdf37e600d06faf06ac Mon Sep 17 00:00:00 2001 From: Tadgh Date: Fri, 13 Nov 2020 15:54:43 -0500 Subject: [PATCH 08/10] Update rest_operations.md --- .../ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md index 8e20f8975e4..2b47e433c1f 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_plain/rest_operations.md @@ -389,7 +389,7 @@ Tags have very specific semantics, which may not be obvious simply by using the ## Accessing Tags in a Read / VRead / Search Method -Tags are stored within a resource object, in the Resource.meta element. It is important to note that changing a resources tags will not cause a version update to that resource. +Tags are stored within a resource object, in the Resource.meta element. It is important to note that changing a resource's tags will not cause a version update to that resource. In a server implementation, you may populate your tags into the returned resource(s) and HAPI will automatically place these tags into the response headers (for read/vread) or the bundle category tags (for search). The following example illustrates how to return tags from a server method. This example shows how to supply tags in a read method, but the same approach applies to vread and search operations as well. From 1db0944243c99bb3a4c01248f334c85c84bfc8d2 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Fri, 13 Nov 2020 17:25:14 -0500 Subject: [PATCH 09/10] Improve logging for terminology ingestion --- .../uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java index fda569ec77c..ac7a0f595e0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermDeferredStorageSvcImpl.java @@ -55,6 +55,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.concurrent.TimeUnit; public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc { @@ -157,7 +158,7 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc { StopWatch stopwatch = new StopWatch(); int count = Math.min(1000, myDeferredConcepts.size()); - ourLog.info("Saving {} deferred concepts...", count); + ourLog.debug("Saving {} deferred concepts...", count); while (codeCount < count && myDeferredConcepts.size() > 0) { TermConcept next = myDeferredConcepts.remove(0); if(myCodeSystemVersionDao.findById(next.getCodeSystemVersion().getPid()).isPresent()) { @@ -174,8 +175,8 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc { } if (codeCount > 0) { - ourLog.info("Saved {} deferred concepts ({} codes remain and {} relationships remain) in {}ms ({}ms / code)", - codeCount, myDeferredConcepts.size(), myConceptLinksToSaveLater.size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(codeCount)); + ourLog.info("Saved {} deferred concepts ({} codes remain and {} relationships remain) in {}ms ({} codes/sec)", + codeCount, myDeferredConcepts.size(), myConceptLinksToSaveLater.size(), stopwatch.getMillis(), stopwatch.formatThroughput(codeCount, TimeUnit.SECONDS)); } if (codeCount == 0) { @@ -198,8 +199,8 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc { } if (relCount > 0) { - ourLog.info("Saved {} deferred relationships ({} remain) in {}ms ({}ms / entry)", - relCount, myConceptLinksToSaveLater.size(), stopwatch.getMillis(), stopwatch.getMillisPerOperation(relCount)); + ourLog.info("Saved {} deferred relationships ({} remain) in {}ms ({} entries/sec)", + relCount, myConceptLinksToSaveLater.size(), stopwatch.getMillis(), stopwatch.formatThroughput(relCount, TimeUnit.SECONDS)); } if ((myDeferredConcepts.size() + myConceptLinksToSaveLater.size()) == 0) { From 7532313c0f356f577b16bebe91e8c6b21cc2df3f Mon Sep 17 00:00:00 2001 From: IanMMarshall <49525404+IanMMarshall@users.noreply.github.com> Date: Tue, 17 Nov 2020 07:46:55 -0500 Subject: [PATCH 10/10] Change to not set ValueSet expansion component parameter id HibernateSearch not enabled. (#2178) Co-authored-by: ianmarshall --- .../fhir/jpa/term/BaseTermReadSvcImpl.java | 12 +- ...eProviderR4ValueSetLuceneDisabledTest.java | 251 ++++++++++++++++++ 2 files changed, 257 insertions(+), 6 deletions(-) create mode 100644 hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetLuceneDisabledTest.java diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java index a8b244c2a2c..be6bf4d00b4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseTermReadSvcImpl.java @@ -141,7 +141,6 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.NoRollbackRuleAttribute; import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; -import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionTemplate; @@ -173,7 +172,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; @@ -428,10 +426,8 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { accumulator.setTimestamp(new Date()); accumulator.setOffset(offset); - if (theExpansionOptions != null) { + if (theExpansionOptions != null && isHibernateSearchEnabled()) { accumulator.addParameter().setName("offset").setValue(new IntegerType(offset)); - } - if (theExpansionOptions != null) { accumulator.addParameter().setName("count").setValue(new IntegerType(count)); } @@ -854,6 +850,10 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { } + private boolean isHibernateSearchEnabled() { + return myFulltextSearchSvc != null; + } + @Nonnull private Boolean expandValueSetHandleIncludeOrExcludeUsingDatabase(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, ValueSet.ConceptSetComponent theIncludeOrExclude, boolean theAdd, int theQueryIndex, @Nonnull ExpansionFilter theExpansionFilter, String theSystem, TermCodeSystem theCs) { String includeOrExcludeVersion = theIncludeOrExclude.getVersion(); @@ -869,7 +869,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc { * If FullText searching is not enabled, we can handle only basic expansions * since we're going to do it without the database. */ - if (myFulltextSearchSvc == null) { + if (!isHibernateSearchEnabled()) { expandWithoutHibernateSearch(theValueSetCodeAccumulator, csv, theAddedCodes, theIncludeOrExclude, theSystem, theAdd); return false; } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetLuceneDisabledTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetLuceneDisabledTest.java new file mode 100644 index 00000000000..d5ae8137f6b --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetLuceneDisabledTest.java @@ -0,0 +1,251 @@ +package ca.uhn.fhir.jpa.provider.r4; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem; +import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet; +import ca.uhn.fhir.jpa.config.TestR4WithLuceneDisabledConfig; +import ca.uhn.fhir.jpa.dao.BaseJpaTest; +import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest; +import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; +import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.parser.StrictErrorHandler; +import ca.uhn.fhir.rest.api.EncodingEnum; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; +import ca.uhn.fhir.rest.server.RestfulServer; +import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor; +import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; +import ca.uhn.fhir.test.utilities.JettyUtil; +import org.apache.commons.io.IOUtils; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.CodeableConcept; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.ValueSet; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.web.context.ContextLoader; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.servlet.DispatcherServlet; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.fail; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = {TestR4WithLuceneDisabledConfig.class}) +public class ResourceProviderR4ValueSetLuceneDisabledTest extends BaseJpaTest { + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4ValueSetLuceneDisabledTest.class); + + private static RestfulServer ourRestServer; + private static String ourServerBase; + private static Server ourServer; + private static DatabaseBackedPagingProvider ourPagingProvider; + + @Autowired + private FhirContext myFhirCtx; + @Autowired + private PlatformTransactionManager myTxManager; + @Autowired + @Qualifier("myCodeSystemDaoR4") + private IFhirResourceDaoCodeSystem myCodeSystemDao; + @Autowired + @Qualifier("myValueSetDaoR4") + private IFhirResourceDaoValueSet myValueSetDao; + @Autowired + @Qualifier("myResourceProvidersR4") + private ResourceProviderFactory myResourceProviders; + @Autowired + private ApplicationContext myAppCtx; + + + private IIdType myExtensionalCsId; + private IIdType myExtensionalVsId; + private IGenericClient myClient; + + private void loadAndPersistCodeSystemAndValueSet() throws IOException { + loadAndPersistCodeSystem(); + loadAndPersistValueSet(); + } + + private T loadResourceFromClasspath(Class type, String resourceName) throws IOException { + InputStream stream = FhirResourceDaoDstu2SearchNoFtTest.class.getResourceAsStream(resourceName); + if (stream == null) { + fail("Unable to load resource: " + resourceName); + } + String string = IOUtils.toString(stream, StandardCharsets.UTF_8); + IParser newJsonParser = EncodingEnum.detectEncodingNoDefault(string).newParser(myFhirCtx); + return newJsonParser.parseResource(type, string); + } + + private void loadAndPersistCodeSystem() throws IOException { + CodeSystem codeSystem = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); + codeSystem.setId("CodeSystem/cs"); + persistCodeSystem(codeSystem); + } + + private void persistCodeSystem(CodeSystem theCodeSystem) { + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) { + myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless(); + } + }); + myCodeSystemDao.readEntity(myExtensionalCsId, null).getId(); + } + + private void loadAndPersistValueSet() throws IOException { + ValueSet valueSet = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); + valueSet.setId("ValueSet/vs"); + persistValueSet(valueSet); + } + + private void persistValueSet(ValueSet theValueSet) { + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) { + myExtensionalVsId = myValueSetDao.create(theValueSet, mySrd).getId().toUnqualifiedVersionless(); + } + }); + myValueSetDao.readEntity(myExtensionalVsId, null).getId(); + } + + @Override + protected FhirContext getContext() { + return myFhirCtx; + } + + @Override + protected PlatformTransactionManager getTxManager() { + return myTxManager; + } + + + @Test + public void testExpandById() throws Exception { + loadAndPersistCodeSystemAndValueSet(); + + Parameters respParam = myClient + .operation() + .onInstance(myExtensionalVsId) + .named("expand") + .withNoParameters(Parameters.class) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + + } + + @BeforeEach + public void before() throws Exception { + myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + myFhirCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); + myFhirCtx.setParserErrorHandler(new StrictErrorHandler()); + + if (ourServer == null) { + ourRestServer = new RestfulServer(myFhirCtx); + ourRestServer.registerProviders(myResourceProviders.createProviders()); + ourRestServer.setDefaultResponseEncoding(EncodingEnum.XML); + + ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class); + + Server server = new Server(0); + + ServletContextHandler proxyHandler = new ServletContextHandler(); + proxyHandler.setContextPath("/"); + + ServletHolder servletHolder = new ServletHolder(); + servletHolder.setServlet(ourRestServer); + proxyHandler.addServlet(servletHolder, "/fhir/context/*"); + + GenericWebApplicationContext webApplicationContext = new GenericWebApplicationContext(); + webApplicationContext.setParent(myAppCtx); + webApplicationContext.refresh(); + proxyHandler.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext); + + DispatcherServlet dispatcherServlet = new DispatcherServlet(); + // dispatcherServlet.setApplicationContext(webApplicationContext); + dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class); + ServletHolder subsServletHolder = new ServletHolder(); + subsServletHolder.setServlet(dispatcherServlet); + subsServletHolder.setInitParameter( + ContextLoader.CONFIG_LOCATION_PARAM, + WebsocketDispatcherConfig.class.getName()); + proxyHandler.addServlet(subsServletHolder, "/*"); + + // Register a CORS filter + CorsConfiguration config = new CorsConfiguration(); + CorsInterceptor corsInterceptor = new CorsInterceptor(config); + config.addAllowedHeader("x-fhir-starter"); + config.addAllowedHeader("Origin"); + config.addAllowedHeader("Accept"); + config.addAllowedHeader("X-Requested-With"); + config.addAllowedHeader("Content-Type"); + config.addAllowedHeader("Access-Control-Request-Method"); + config.addAllowedHeader("Access-Control-Request-Headers"); + config.addAllowedOrigin("*"); + config.addExposedHeader("Location"); + config.addExposedHeader("Content-Location"); + config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); + ourRestServer.registerInterceptor(corsInterceptor); + + server.setHandler(proxyHandler); + JettyUtil.startServer(server); + int port = JettyUtil.getPortForStartedServer(server); + ourServerBase = "http://localhost:" + port + "/fhir/context"; + + myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + myFhirCtx.getRestfulClientFactory().setSocketTimeout(20000); + + ourServer = server; + } + + ourRestServer.setPagingProvider(ourPagingProvider); + + myClient = myFhirCtx.newRestfulGenericClient(ourServerBase); + } + + + +}