diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index a341c9477b1..bfe99e051b0 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index eac71d52182..824f780f5fc 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index af2f200f083..86a97c9e48c 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java index 5c873c94114..629b0a92dff 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java @@ -350,7 +350,6 @@ public class ParametersUtil { } else { partChildElem.getChildByName("value[x]").getMutator().addValue(part, theValue); } - } public static void addPartResource(FhirContext theContext, IBase theParameter, String theName, IBaseResource theValue) { diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 5115fc49cdc..81c1588e76f 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -3,14 +3,14 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT pom HAPI FHIR BOM ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index 0526bb76355..1097f5600e7 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index 3c4f732f362..3085ccc4114 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml index e91a6006e27..0720e557706 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../hapi-deployable-pom diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index bf256b18666..eec2c53e1e0 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index a764a8338dc..16aa0ef24d0 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index ce79a788494..64c0cc41683 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 117c40e5d8f..6ecc1015468 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index c80e074b76a..7f6bcfd4800 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index 180d2bcc00d..04637b93b09 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_5_0/2767-mdm-query-paging.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_5_0/2767-mdm-query-paging.yaml new file mode 100644 index 00000000000..2843c256bfc --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_5_0/2767-mdm-query-paging.yaml @@ -0,0 +1,6 @@ +--- +type: add +issue: 2767 +title: "`$mdm-query-links` and `$mdm-duplicate-golden-resources` now enforce paging via parameters `_offset` and `_count`. More +details can be found in the [MDM Operations documentation](/hapi-fhir/docs/server_jpa_mdm/mdm_operations.html)." + diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md index 7a33d073473..b946438ebcb 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md @@ -4,6 +4,53 @@ MDM links are managed by MDM Operations. These operations are supplied by a [pla In cases where the operation changes data, if a resource id parameter contains a version (e.g. `Patient/123/_history/1`), then the operation will fail with a 409 CONFLICT if that is not the latest version of that resource. This feature can be used to prevent update conflicts in an environment where multiple users are working on the same set of mdm links. +## Pagination + +In both the `$query-links` operation, and the `$mdm-duplicate-golden-resources` paging is supported via `_count` and `_offset` parameters. By default, if you omit page information from your query, default pagination values will be used. +The response will return you the next/self/previous links as part of the parameters response. Here are examples of pagination in these MDM queries. + +```http request +GET http://example.com/$mdm-query-links?_offset=0&_count=2 +``` + +Or if you are making a POST request + +```http request +POST http://example.com/$mdm-query-links +``` + +With request body: + +```json +{ + "resourceType": "Parameters", + "parameter": [ { + "name": "_offset", + "valueInteger": 10 + }, { + "name": "_count", + "valueInteger": 10 + } ] +} +``` + +The returning response will contain links to the current, next, and previous pages. If there is no previous/next link, it means there is no previous/next page of data available. + +```text +{ + "resourceType": "Parameters", + "parameter": [ { + "name": "prev", + "valueUri": "http://example.com/$mdm-query-links?_offset=0&_count=10" + }, { + "name": "self", + "valueUri": "http://example.com/$mdm-query-links?_offset=10&_count=10" + }, { + "name": "next", + "valueUri": "http://example.com/$mdm-query-links?_offset=20&_count=10" + },...(truncated) +``` + ## Query links Use the `$mdm-query-links` operation to view MDM links. The results returned are based on the parameters provided. All parameters are optional. This operation takes the following parameters: @@ -50,6 +97,22 @@ Use the `$mdm-query-links` operation to view MDM links. The results returned are AUTO, MANUAL. + + _offset + int + 0..1 + + the offset to begin returning records at. + + + + _count + int + 0..1 + + The number of links to be returned in a page. + + @@ -58,7 +121,7 @@ Use the `$mdm-query-links` operation to view MDM links. The results returned are Use an HTTP GET like `http://example.com/$mdm-query-links?matchResult=POSSIBLE_MATCH` or an HTTP POST to the following URL to invoke this operation: ```url -http://example.com/$mdm-query-links +http://example.com/$mdm-query-links?_offset=10&_count=2 ``` The following request body could be used to find all POSSIBLE_MATCH links in the system: @@ -67,6 +130,15 @@ The following request body could be used to find all POSSIBLE_MATCH links in the { "resourceType": "Parameters", "parameter": [ { + "name": "prev", + "valueUri": "http://example.com/$mdm-query-links?_offset=8_count=2" + }, { + "name": "self", + "valueUri": "http://example.com/$mdm-query-links?_offset=10_count=2" + }, { + "name": "next", + "valueUri": "http://example.com/$mdm-query-links?_offset=12_count=2" + }, { "name": "matchResult", "valueString": "POSSIBLE_MATCH" } ] @@ -79,6 +151,15 @@ This operation returns a `Parameters` resource that looks like the following: { "resourceType": "Parameters", "parameter": [ { + "name": "prev", + "valueUri": "http://example.com$mdm-query-links?_offset=8_count=2" + }, { + "name": "self", + "valueUri": "http://example.com$mdm-query-links?_offset=10_count=10" + }, { + "name": "next", + "valueUri": "http://example.com$mdm-query-links?_offset=20_count=10" + }, { "name": "link", "part": [ { "name": "goldenResourceId", @@ -119,6 +200,37 @@ Use an HTTP GET to the following URL to invoke this operation: http://example.com/$mdm-duplicate-golden-resources ``` +The following is a table of the request parameters supported by this GET operation. + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeCardinalityDescription
_offsetint0..1 + the offset to begin returning records at. +
_countint0..1 + The number of links to be returned in a page. +
+ This operation returns `Parameters` similar to `$mdm-query-links`: diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index dbf55d3c96c..cfd2e0c8cd7 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index c0bc2a89836..c2d87484e25 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-example/pom.xml b/hapi-fhir-jaxrsserver-example/pom.xml index 0869d53877f..a8098598dc3 100644 --- a/hapi-fhir-jaxrsserver-example/pom.xml +++ b/hapi-fhir-jaxrsserver-example/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-jpaserver-api/pom.xml b/hapi-fhir-jpaserver-api/pom.xml index 97307edbc5f..d326afc4010 100644 --- a/hapi-fhir-jpaserver-api/pom.xml +++ b/hapi-fhir-jpaserver-api/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index b57f03e094c..ba176a91bfd 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/sql/SearchQueryBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/sql/SearchQueryBuilder.java index 06058baed6d..c974f8a3bac 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/sql/SearchQueryBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/sql/SearchQueryBuilder.java @@ -428,7 +428,6 @@ public class SearchQueryBuilder { startOfQueryParameterIndex = bindOffsetParameter(bindVariables, offset, limitHandler, startOfQueryParameterIndex, bindLimitParametersFirst); bindCountParameter(bindVariables, maxResultsToFetch, limitHandler, startOfQueryParameterIndex, bindLimitParametersFirst); } - } } diff --git a/hapi-fhir-jpaserver-batch/pom.xml b/hapi-fhir-jpaserver-batch/pom.xml index a4b3209addc..8ca2d1c072a 100644 --- a/hapi-fhir-jpaserver-batch/pom.xml +++ b/hapi-fhir-jpaserver-batch/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-cql/pom.xml b/hapi-fhir-jpaserver-cql/pom.xml index b0546558bba..781bcd0d3a8 100644 --- a/hapi-fhir-jpaserver-cql/pom.xml +++ b/hapi-fhir-jpaserver-cql/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 8dec0d074d2..4b811ba92db 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java index 0573e95ffaf..45df193ddeb 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java @@ -27,12 +27,14 @@ import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.api.MdmMatchOutcome; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.log.Logs; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import org.hl7.fhir.instance.model.api.IBaseResource; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -286,8 +288,8 @@ public class MdmLinkDaoSvc { * @param theExampleLink The MDM link containing the data we would like to search for. * @return a list of {@link MdmLink} entities which match the example. */ - public List findMdmLinkByExample(Example theExampleLink) { - return myMdmLinkDao.findAll(theExampleLink); + public Page findMdmLinkByExample(Example theExampleLink, MdmPageRequest thePageRequest) { + return myMdmLinkDao.findAll(theExampleLink, thePageRequest.toPageRequest()); } /** diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java index bc02474ac35..9c7a149b261 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmControllerSvcImpl.java @@ -27,6 +27,7 @@ import ca.uhn.fhir.mdm.api.IMdmLinkUpdaterSvc; import ca.uhn.fhir.mdm.api.MdmLinkJson; import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import ca.uhn.fhir.mdm.provider.MdmControllerHelper; import ca.uhn.fhir.mdm.provider.MdmControllerUtil; @@ -34,10 +35,10 @@ import ca.uhn.fhir.rest.server.provider.ProviderConstants; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IIdType; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import javax.annotation.Nullable; -import java.util.stream.Stream; /** * This class acts as a layer between MdmProviders and MDM services to support a REST API that's not a FHIR Operation API. @@ -66,18 +67,17 @@ public class MdmControllerSvcImpl implements IMdmControllerSvc { } @Override - public Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext) { + public Page queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext, MdmPageRequest thePageRequest) { IIdType goldenResourceId = MdmControllerUtil.extractGoldenResourceIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId); IIdType sourceId = MdmControllerUtil.extractSourceIdDtOrNull(ProviderConstants.MDM_QUERY_LINKS_RESOURCE_ID, theSourceResourceId); MdmMatchResultEnum matchResult = MdmControllerUtil.extractMatchResultOrNull(theMatchResult); MdmLinkSourceEnum linkSource = MdmControllerUtil.extractLinkSourceOrNull(theLinkSource); - - return myMdmLinkQuerySvc.queryLinks(goldenResourceId, sourceId, matchResult, linkSource, theMdmTransactionContext); + return myMdmLinkQuerySvc.queryLinks(goldenResourceId, sourceId, matchResult, linkSource, theMdmTransactionContext, thePageRequest); } @Override - public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext) { - return myMdmLinkQuerySvc.getDuplicateGoldenResources(theMdmTransactionContext); + public Page getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext, MdmPageRequest thePageRequest) { + return myMdmLinkQuerySvc.getDuplicateGoldenResources(theMdmTransactionContext, thePageRequest); } @Override diff --git a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java index d191482a7ed..ea00e81ec4d 100644 --- a/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java +++ b/hapi-fhir-jpaserver-mdm/src/main/java/ca/uhn/fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java @@ -24,6 +24,7 @@ import ca.uhn.fhir.mdm.api.MdmLinkJson; import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; import ca.uhn.fhir.mdm.api.IMdmLinkQuerySvc; +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import ca.uhn.fhir.jpa.dao.index.IdHelperService; import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; @@ -33,8 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; - -import java.util.stream.Stream; +import org.springframework.data.domain.Page; public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { @@ -46,17 +46,19 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { MdmLinkDaoSvc myMdmLinkDaoSvc; @Override - public Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext) { + public Page queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest) { Example exampleLink = exampleLinkFromParameters(theGoldenResourceId, theSourceResourceId, theMatchResult, theLinkSource); - return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink).stream() - .filter(mdmLink -> mdmLink.getMatchResult() != MdmMatchResultEnum.POSSIBLE_DUPLICATE) - .map(this::toJson); + Page mdmLinkByExample = myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, thePageRequest); + Page map = mdmLinkByExample.map(this::toJson); + return map; } @Override - public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext) { + public Page getDuplicateGoldenResources(MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest) { Example exampleLink = exampleLinkFromParameters(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null); - return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink).stream().map(this::toJson); + Page mdmLinkPage = myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, thePageRequest); + Page map = mdmLinkPage.map(this::toJson); + return map; } private MdmLinkJson toJson(MdmLink theLink) { diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java index dae0782cccb..9608fa44353 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java @@ -1,7 +1,9 @@ package ca.uhn.fhir.jpa.mdm; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.api.AddProfileTagEnum; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; +import ca.uhn.fhir.interceptor.api.IInterceptorService; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; @@ -32,9 +34,19 @@ import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc; import ca.uhn.fhir.mdm.util.EIDHelper; import ca.uhn.fhir.mdm.util.MdmResourceUtil; import ca.uhn.fhir.model.api.TemporalPrecisionEnum; +import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.param.TokenParam; +import ca.uhn.fhir.rest.server.BasePagingProvider; +import ca.uhn.fhir.rest.server.ETagSupportEnum; +import ca.uhn.fhir.rest.server.ElementsSupportEnum; +import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider; +import ca.uhn.fhir.rest.server.IPagingProvider; +import ca.uhn.fhir.rest.server.IRestfulServerDefaults; +import ca.uhn.fhir.rest.server.RestfulServer; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import org.apache.commons.lang3.StringUtils; import org.hamcrest.Matcher; @@ -49,11 +61,15 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.Reference; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -71,6 +87,8 @@ import static org.slf4j.LoggerFactory.getLogger; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = {MdmSubmitterConfig.class, MdmConsumerConfig.class, TestMdmConfigR4.class, SubscriptionProcessorConfig.class}) abstract public class BaseMdmR4Test extends BaseJpaR4Test { + + private static final Logger ourLog = getLogger(BaseMdmR4Test.class); public static final String NAME_GIVEN_JANE = "Jane"; diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/config/BaseTestMdmConfig.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/config/BaseTestMdmConfig.java index 5b02acb4570..0af4ba1aba7 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/config/BaseTestMdmConfig.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/config/BaseTestMdmConfig.java @@ -4,6 +4,8 @@ import ca.uhn.fhir.mdm.api.IMdmSettings; import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator; import ca.uhn.fhir.mdm.rules.config.MdmSettings; import ca.uhn.fhir.jpa.mdm.helper.MdmLinkHelper; +import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider; +import ca.uhn.fhir.rest.server.IPagingProvider; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Value; diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseProviderR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseProviderR4Test.java index fd2647bb304..5cbec2e45af 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseProviderR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseProviderR4Test.java @@ -7,6 +7,8 @@ import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc; import ca.uhn.fhir.mdm.api.IMdmSubmitSvc; import ca.uhn.fhir.mdm.provider.MdmProviderDstu3Plus; import ca.uhn.fhir.mdm.rules.config.MdmSettings; +import ca.uhn.fhir.rest.server.IPagingProvider; +import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterEach; diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java index a41dc5e99cb..dc72acce1d5 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderQueryLinkR4Test.java @@ -1,27 +1,38 @@ package ca.uhn.fhir.jpa.mdm.provider; import ca.uhn.fhir.jpa.entity.MdmLink; +import ca.uhn.fhir.jpa.util.CircularQueueCaptureQueriesListener; import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; +import ca.uhn.fhir.util.StopWatch; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.dstu3.model.UnsignedIntType; import org.hl7.fhir.instance.model.api.IAnyResource; +import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.BooleanType; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Type; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import java.util.List; +import java.util.stream.Collectors; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -31,6 +42,8 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { private StringType myLinkSource; private StringType myGoldenResource1Id; private StringType myGoldenResource2Id; + @Autowired + protected CircularQueueCaptureQueriesListener myCaptureQueriesListener; @Override @BeforeEach @@ -55,35 +68,130 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { @Test public void testQueryLinkOneMatch() { - Parameters result = (Parameters) myMdmProvider.queryLinks(mySourcePatientId, myPatientId, null, null, myRequestDetails); + Parameters result = (Parameters) myMdmProvider.queryLinks(mySourcePatientId, myPatientId, null, null, new UnsignedIntType(0), new UnsignedIntType(10), myRequestDetails); ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(result)); - List list = result.getParameter(); + List list = getParametersByName(result, "link"); assertThat(list, hasSize(1)); List part = list.get(0).getPart(); assertMdmLink(7, part, mySourcePatientId.getValue(), myPatientId.getValue(), MdmMatchResultEnum.POSSIBLE_MATCH, "false", "true", null); } @Test - public void testQueryLinkThreeMatches() { + public void testQueryLinkPages() { + for (int i = 0; i < 10; i++) { + createPatientAndUpdateLinks(buildJanePatient()); + } + + int offset = 0; + int count = 2; + StopWatch sw = new StopWatch(); + while (true) { + Parameters result = (Parameters) myMdmProvider.queryLinks(null, null, null, myLinkSource, new UnsignedIntType(offset), new UnsignedIntType(count), myRequestDetails); + List parameter = result.getParameter(); + + + ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(result)); + List previousUrl = getParametersByName(result, "prev"); + if (offset == 0) { + assertThat(previousUrl, hasSize(0)); + } else { + assertThat(previousUrl, hasSize(1)); + } + + String sourceResourceIds = parameter.stream().flatMap(p -> p.getPart().stream()).filter(part -> part.getName().equals("sourceResourceId")).map(part -> part.getValue().toString()).collect(Collectors.joining(",")); + ourLog.warn("Search at offset {} took {} ms",offset, sw.getMillisAndRestart()); + ourLog.warn("Found source resource IDs: {}", sourceResourceIds); + List mdmLink = getParametersByName(result, "link"); + assertThat(mdmLink.size(), is(lessThanOrEqualTo(2))); + + List selfUrl = getParametersByName(result, "self"); + assertThat(selfUrl.size(), is(equalTo(1))); + //We have stopped finding patients, make sure theres no next page + if (StringUtils.isEmpty(sourceResourceIds)) { + List nextUrl= getParametersByName(result, "next"); + assertThat(nextUrl.size(), is(equalTo(0))); + break; + } + offset += count; + } + } + + private List getParametersByName(Parameters theParams, String theName) { + return theParams.getParameter().stream().filter(p -> p.getName().equals(theName)).collect(Collectors.toList()); + } + + @Test + public void testQueryWithIllegalPagingValuesFails() { + //Given + int count = 0; + int offset = 0; + try { + //When + myMdmProvider.queryLinks( + null, null, + null, myLinkSource, + new UnsignedIntType(offset), + new UnsignedIntType(count), + myRequestDetails); + } catch (InvalidRequestException e) { + //Then + assertThat(e.getMessage(), is(equalTo("_count must be greater than 0."))); + } + + //Given + count = 1; + offset= -1; + try { + //When + myMdmProvider.queryLinks( + null, null, + null, myLinkSource, + new UnsignedIntType(offset), + new UnsignedIntType(count), + myRequestDetails); + } catch (InvalidRequestException e) { + //Then + assertThat(e.getMessage(), is(equalTo("_offset must be greater than or equal to 0. "))); + } + + //Given + count = 0; + offset= -1; + try { + //When + myMdmProvider.queryLinks( + null, null, + null, myLinkSource, + new UnsignedIntType(offset), + new UnsignedIntType(count), + myRequestDetails); + } catch (InvalidRequestException e) { + //Then + assertThat(e.getMessage(), is(equalTo("_offset must be greater than or equal to 0. _count must be greater than 0."))); + } + } + + @Test + public void testQueryLnkThreeMatches() { // Add a third patient Patient patient = createPatientAndUpdateLinks(buildJanePatient()); IdType patientId = patient.getIdElement().toVersionless(); IAnyResource goldenResource = getGoldenResourceFromTargetResource(patient); IIdType goldenResourceId = goldenResource.getIdElement().toVersionless(); - Parameters result = (Parameters) myMdmProvider.queryLinks(null, null, null, myLinkSource, myRequestDetails); + Parameters result = (Parameters) myMdmProvider.queryLinks(null, null, null, myLinkSource, new UnsignedIntType(0), new UnsignedIntType(10), myRequestDetails); ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(result)); - List list = result.getParameter(); - assertThat(list, hasSize(3)); - List part = list.get(2).getPart(); + List list = getParametersByName(result, "link"); + assertThat(list, hasSize(4)); + List part = list.get(3).getPart(); assertMdmLink(7, part, goldenResourceId.getValue(), patientId.getValue(), MdmMatchResultEnum.MATCH, "false", "false", "2"); } @Test public void testQueryPossibleDuplicates() { - Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(myRequestDetails); + Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(result)); - List list = result.getParameter(); + List list = getParametersByName(result, "link"); assertThat(list, hasSize(1)); List part = list.get(0).getPart(); assertMdmLink(2, part, myGoldenResource1Id.getValue(), myGoldenResource2Id.getValue(), MdmMatchResultEnum.POSSIBLE_DUPLICATE, "false", "false", null); @@ -92,8 +200,9 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { @Test public void testNotDuplicate() { { - Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(myRequestDetails); - List list = result.getParameter(); + Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); + List list = getParametersByName(result, "link"); + assertThat(list, hasSize(1)); } { @@ -103,8 +212,8 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { assertTrue(((BooleanType) (result.getParameterFirstRep().getValue())).booleanValue()); } - Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(myRequestDetails); - List list = result.getParameter(); + Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); + List list = getParametersByName(result, "link"); assertThat(list, hasSize(0)); } diff --git a/hapi-fhir-jpaserver-migrate/pom.xml b/hapi-fhir-jpaserver-migrate/pom.xml index a64c35e1897..1f9c07fa37c 100644 --- a/hapi-fhir-jpaserver-migrate/pom.xml +++ b/hapi-fhir-jpaserver-migrate/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index e1990391db6..ff100b79b66 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 27cbd49dc0b..ea5ca903fd9 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index 537b12ba6d9..dadf2bd854c 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 5018f4db8f0..35f517defdd 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index 5a1f3d439a0..80f352f1735 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index bf1e50dd9e9..687f2cabe02 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml @@ -27,6 +27,11 @@ hapi-fhir-server ${project.version} + + org.springframework.data + spring-data-commons + ${spring_data_version} + ca.uhn.hapi.fhir hapi-fhir-structures-dstu3 diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java index fb0e9ebe981..67a3dc64a53 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmControllerSvc.java @@ -20,17 +20,18 @@ package ca.uhn.fhir.mdm.api; * #L% */ +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import org.hl7.fhir.instance.model.api.IAnyResource; +import org.springframework.data.domain.Page; import javax.annotation.Nullable; -import java.util.stream.Stream; public interface IMdmControllerSvc { - Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext); + Page queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext, MdmPageRequest thePageRequest); - Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext); + Page getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext, MdmPageRequest thePageRequest); void notDuplicateGoldenResource(String theGoldenResourceId, String theTargetGoldenResourceId, MdmTransactionContext theMdmTransactionContext); diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java index 8d5fe42e254..a1ffc27e495 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java @@ -20,15 +20,15 @@ package ca.uhn.fhir.mdm.api; * #L% */ +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import org.hl7.fhir.instance.model.api.IIdType; - -import java.util.stream.Stream; +import org.springframework.data.domain.Page; /** * This service supports the MDM operation providers for those services that return multiple MDM links. */ public interface IMdmLinkQuerySvc { - Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext); - Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext); + Page queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest); + Page getDuplicateGoldenResources(MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilder.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilder.java new file mode 100644 index 00000000000..32629bc3604 --- /dev/null +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilder.java @@ -0,0 +1,78 @@ +package ca.uhn.fhir.mdm.api.paging; + +/*- + * #%L + * HAPI FHIR - Master Data Management + * %% + * Copyright (C) 2014 - 2021 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import ca.uhn.fhir.mdm.api.MdmLinkJson; +import ca.uhn.fhir.rest.server.RestfulServerUtils; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; +import org.springframework.data.domain.Page; + +import java.util.Arrays; + +import static ca.uhn.fhir.rest.api.Constants.PARAM_COUNT; +import static ca.uhn.fhir.rest.api.Constants.PARAM_OFFSET; + +/** + * Builder to generate {@link MdmPageLinkTuple} objects, based on a given page of data and the incoming page request. + */ +public final class MdmPageLinkBuilder { + + /** + * Generates an {@link MdmPageLinkTuple} which contains previous/self/next links for pagination purposes. + * + * @param theServletRequestDetails the incoming request details. Used to determine server base. + * @param theCurrentPage the page of MDM link data. Used for determining if there are next/previous pages available. + * @param thePageRequest the incoming Page request, containing requested offset and count. Used for building offset for outgoing URLs. + * + * @return the {@link MdmPageLinkTuple} + */ + public static MdmPageLinkTuple buildMdmPageLinks(ServletRequestDetails theServletRequestDetails, Page theCurrentPage, MdmPageRequest thePageRequest) { + String urlWithoutPaging = RestfulServerUtils.createLinkSelfWithoutGivenParameters(theServletRequestDetails.getFhirServerBase(), theServletRequestDetails, Arrays.asList(PARAM_OFFSET, PARAM_COUNT)); + return buildMdmPageLinks(urlWithoutPaging, theCurrentPage, thePageRequest); + } + + public static MdmPageLinkTuple buildMdmPageLinks(String theUrlWithoutPaging, Page theCurrentPage, MdmPageRequest thePageRequest) { + MdmPageLinkTuple tuple = new MdmPageLinkTuple(); + tuple.setSelfLink(buildLinkWithOffsetAndCount(theUrlWithoutPaging, thePageRequest.getCount(), thePageRequest.getOffset())); + if (theCurrentPage.hasNext()) { + tuple.setNextLink(buildLinkWithOffsetAndCount(theUrlWithoutPaging,thePageRequest.getCount(), thePageRequest.getNextOffset())); + } + if (theCurrentPage.hasPrevious()) { + tuple.setPreviousLink(buildLinkWithOffsetAndCount(theUrlWithoutPaging,thePageRequest.getCount(), thePageRequest.getPreviousOffset())); + } + return tuple; + + } + + public static String buildLinkWithOffsetAndCount(String theBaseUrl, int theCount, int theOffset) { + StringBuilder builder = new StringBuilder(); + builder.append(theBaseUrl); + if (!theBaseUrl.contains("?")) { + builder.append("?"); + } else { + builder.append("&"); + } + builder.append(PARAM_OFFSET).append("=").append(theOffset); + builder.append("&"); + builder.append(PARAM_COUNT).append("=").append(theCount); + return builder.toString(); + } +} diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkTuple.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkTuple.java new file mode 100644 index 00000000000..fd8d30859ee --- /dev/null +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkTuple.java @@ -0,0 +1,58 @@ +package ca.uhn.fhir.mdm.api.paging; + +/*- + * #%L + * HAPI FHIR - Master Data Management + * %% + * Copyright (C) 2014 - 2021 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.util.Optional; + +/** + * Data clump class to keep the relevant paging URLs together for MDM. + */ +public class MdmPageLinkTuple { + private String myPreviousLink = null; + private String mySelfLink = null; + private String myNextLink = null; + + MdmPageLinkTuple() {} + + public Optional getPreviousLink() { + return Optional.ofNullable(myPreviousLink); + } + + public void setPreviousLink(String thePreviousLink) { + this.myPreviousLink = thePreviousLink; + } + + public String getSelfLink() { + return mySelfLink; + } + + public void setSelfLink(String theSelfLink) { + this.mySelfLink = theSelfLink; + } + + public Optional getNextLink() { + return Optional.ofNullable(myNextLink); + } + + public void setNextLink(String theNextLink) { + this.myNextLink = theNextLink; + } +} diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java new file mode 100644 index 00000000000..a91f189e0e6 --- /dev/null +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java @@ -0,0 +1,101 @@ +package ca.uhn.fhir.mdm.api.paging; + +/*- + * #%L + * HAPI FHIR - Master Data Management + * %% + * Copyright (C) 2014 - 2021 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import ca.uhn.fhir.rest.server.IPagingProvider; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.dstu3.model.UnsignedIntType; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.slf4j.Logger; +import org.springframework.data.domain.PageRequest; + +import javax.annotation.Nullable; + +import static ca.uhn.fhir.rest.api.Constants.PARAM_COUNT; +import static ca.uhn.fhir.rest.api.Constants.PARAM_OFFSET; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * This class is essentially just a data clump of offset + count, as well as the ability to convert itself into a standard + * {@link PageRequest} for spring data to use. The reason we don't use PageRequest natively is because it is concerned with `pages` and `counts`, + * but we are using `offset` and `count` which requires some minor translation. + */ +public class MdmPageRequest { + + private final int myPage; + private final int myOffset; + private final int myCount; + + public MdmPageRequest(@Nullable IPrimitiveType theOffset, @Nullable IPrimitiveType theCount, int theDefaultPageSize, int theMaximumPageSize) { + myOffset = theOffset == null ? 0 : theOffset.getValue(); + myCount = theCount == null ? theDefaultPageSize : Math.min(theCount.getValue(), theMaximumPageSize); + validatePagingParameters(myOffset, myCount); + + this.myPage = myOffset / myCount; + } + + public MdmPageRequest(@Nullable Integer theOffset, @Nullable Integer theCount, int theDefaultPageSize, int theMaximumPageSize) { + myOffset = theOffset == null ? 0 : theOffset; + myCount = theCount == null ? theDefaultPageSize : Math.min(theCount, theMaximumPageSize); + validatePagingParameters(myOffset, myCount); + + this.myPage = myOffset / myCount; + } + + private void validatePagingParameters(int theOffset, int theCount) { + String errorMessage = ""; + + if (theOffset < 0) { + errorMessage += PARAM_OFFSET + " must be greater than or equal to 0. "; + } + if (theCount <= 0 ) { + errorMessage += PARAM_COUNT + " must be greater than 0."; + } + if (StringUtils.isNotEmpty(errorMessage)) { + throw new InvalidRequestException(errorMessage); + } + } + + public int getOffset() { + return myOffset; + } + + public int getPage() { + return myPage; + } + + public int getCount() { + return myCount; + } + + public int getNextOffset() { + return myOffset + myCount; + } + + public int getPreviousOffset() { + return myOffset - myCount; + } + + public PageRequest toPageRequest() { + return PageRequest.of(this.myPage, this.myCount); + } +} diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java index e9bdb713959..b20e790d2be 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/BaseMdmProvider.java @@ -23,17 +23,21 @@ package ca.uhn.fhir.mdm.provider; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.mdm.api.MdmLinkJson; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; +import ca.uhn.fhir.mdm.api.paging.MdmPageLinkBuilder; +import ca.uhn.fhir.mdm.api.paging.MdmPageLinkTuple; +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.model.MdmTransactionContext; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.TransactionLogMessages; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.ParametersUtil; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.springframework.data.domain.Page; -import java.util.stream.Stream; public abstract class BaseMdmProvider { @@ -92,9 +96,9 @@ public abstract class BaseMdmProvider { return theString.getValue(); } - protected IBaseParameters parametersFromMdmLinks(Stream theMdmLinkStream, boolean includeResultAndSource) { + protected IBaseParameters parametersFromMdmLinks(Page theMdmLinkStream, boolean includeResultAndSource, ServletRequestDetails theServletRequestDetails, MdmPageRequest thePageRequest) { IBaseParameters retval = ParametersUtil.newInstance(myFhirContext); - + addPagingParameters(retval, theMdmLinkStream, theServletRequestDetails, thePageRequest); theMdmLinkStream.forEach(mdmLink -> { IBase resultPart = ParametersUtil.addParameterToParameters(myFhirContext, retval, "link"); ParametersUtil.addPartString(myFhirContext, resultPart, "goldenResourceId", mdmLink.getGoldenResourceId()); @@ -111,4 +115,17 @@ public abstract class BaseMdmProvider { return retval; } + protected void addPagingParameters(IBaseParameters theParameters, Page theCurrentPage, ServletRequestDetails theServletRequestDetails, MdmPageRequest thePageRequest) { + MdmPageLinkTuple mdmPageLinkTuple = MdmPageLinkBuilder.buildMdmPageLinks(theServletRequestDetails, theCurrentPage, thePageRequest); + + if (mdmPageLinkTuple.getPreviousLink().isPresent()) { + ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "prev", mdmPageLinkTuple.getPreviousLink().get()); + } + + ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "self", mdmPageLinkTuple.getSelfLink()); + + if (mdmPageLinkTuple.getNextLink().isPresent()) { + ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "next", mdmPageLinkTuple.getNextLink().get()); + } + } } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java index 45f9d2031a4..28aa52c69b5 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java @@ -28,10 +28,14 @@ import ca.uhn.fhir.mdm.api.IMdmSubmitSvc; import ca.uhn.fhir.mdm.api.MatchedTarget; import ca.uhn.fhir.mdm.api.MdmConstants; import ca.uhn.fhir.mdm.api.MdmLinkJson; +import ca.uhn.fhir.mdm.api.paging.MdmPageRequest; import ca.uhn.fhir.mdm.model.MdmTransactionContext; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.primitive.IntegerDt; import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; +import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; @@ -49,6 +53,8 @@ import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.slf4j.Logger; +import org.springframework.data.domain.Page; import javax.annotation.Nonnull; import java.math.BigDecimal; @@ -56,15 +62,22 @@ import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.UUID; -import java.util.stream.Stream; + +import static ca.uhn.fhir.rest.api.Constants.PARAM_OFFSET; +import static org.slf4j.LoggerFactory.getLogger; public class MdmProviderDstu3Plus extends BaseMdmProvider { + private static final Logger ourLog = getLogger(MdmProviderDstu3Plus.class); + private final IMdmControllerSvc myMdmControllerSvc; private final IMdmMatchFinderSvc myMdmMatchFinderSvc; private final IMdmExpungeSvc myMdmExpungeSvc; private final IMdmSubmitSvc myMdmSubmitSvc; + public static final int DEFAULT_PAGE_SIZE = 20; + public static final int MAX_PAGE_SIZE = 100; + /** * Constructor *

@@ -184,28 +197,45 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { return retval; } - @Operation(name = ProviderConstants.MDM_QUERY_LINKS, idempotent = true) public IBaseParameters queryLinks(@OperationParam(name = ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, min = 0, max = 1, typeName = "string") IPrimitiveType theGoldenResourceId, @OperationParam(name = ProviderConstants.MDM_QUERY_LINKS_RESOURCE_ID, min = 0, max = 1, typeName = "string") IPrimitiveType theResourceId, @OperationParam(name = ProviderConstants.MDM_QUERY_LINKS_MATCH_RESULT, min = 0, max = 1, typeName = "string") IPrimitiveType theMatchResult, - @OperationParam(name = ProviderConstants.MDM_QUERY_LINKS_LINK_SOURCE, min = 0, max = 1, typeName = "string") IPrimitiveType theLinkSource, - ServletRequestDetails theRequestDetails) { + @OperationParam(name = ProviderConstants.MDM_QUERY_LINKS_LINK_SOURCE, min = 0, max = 1, typeName = "string") + IPrimitiveType theLinkSource, - Stream mdmLinkJson = myMdmControllerSvc.queryLinks(extractStringOrNull(theGoldenResourceId), + @Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") + @OperationParam(name = PARAM_OFFSET, min = 0, max = 1, typeName = "integer") + IPrimitiveType theOffset, + @Description(formalDefinition = "Results from this method are returned across multiple pages. This parameter controls the size of those pages.") + @OperationParam(name = Constants.PARAM_COUNT, min = 0, max = 1, typeName = "integer") + IPrimitiveType theCount, + + ServletRequestDetails theRequestDetails) { + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE); + Page mdmLinkJson = myMdmControllerSvc.queryLinks(extractStringOrNull(theGoldenResourceId), extractStringOrNull(theResourceId), extractStringOrNull(theMatchResult), extractStringOrNull(theLinkSource), createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.QUERY_LINKS, - getResourceType(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId)) - ); - return parametersFromMdmLinks(mdmLinkJson, true); + getResourceType(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId)), mdmPageRequest); + + return parametersFromMdmLinks(mdmLinkJson, true, theRequestDetails, mdmPageRequest); } @Operation(name = ProviderConstants.MDM_DUPLICATE_GOLDEN_RESOURCES, idempotent = true) - public IBaseParameters getDuplicateGoldenResources(ServletRequestDetails theRequestDetails) { - Stream possibleDuplicates = myMdmControllerSvc.getDuplicateGoldenResources( - createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.DUPLICATE_GOLDEN_RESOURCES, (String) null) - ); - return parametersFromMdmLinks(possibleDuplicates, false); + public IBaseParameters getDuplicateGoldenResources( + @Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") + @OperationParam(name = PARAM_OFFSET, min = 0, max = 1, typeName = "integer") + IPrimitiveType theOffset, + @Description(formalDefinition = "Results from this method are returned across multiple pages. This parameter controls the size of those pages.") + @OperationParam(name = Constants.PARAM_COUNT, min = 0, max = 1, typeName = "integer") + IPrimitiveType theCount, + ServletRequestDetails theRequestDetails) { + + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE); + + Page possibleDuplicates = myMdmControllerSvc.getDuplicateGoldenResources(createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.DUPLICATE_GOLDEN_RESOURCES, (String) null), mdmPageRequest); + + return parametersFromMdmLinks(possibleDuplicates, false, theRequestDetails, mdmPageRequest); } @Operation(name = ProviderConstants.MDM_NOT_DUPLICATE) @@ -233,7 +263,6 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { ServletRequestDetails theRequestDetails) { String criteria = convertStringTypeToString(theCriteria); String resourceType = convertStringTypeToString(theResourceType); - long submittedCount; if (resourceType != null) { submittedCount = myMdmSubmitSvc.submitSourceResourceTypeToMdm(resourceType, criteria); diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderLoader.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderLoader.java index a0defeda0a6..e63e6b17d50 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderLoader.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/provider/MdmProviderLoader.java @@ -26,6 +26,9 @@ import ca.uhn.fhir.mdm.api.IMdmControllerSvc; import ca.uhn.fhir.mdm.api.IMdmExpungeSvc; import ca.uhn.fhir.mdm.api.IMdmMatchFinderSvc; import ca.uhn.fhir.mdm.api.IMdmSubmitSvc; +import ca.uhn.fhir.rest.server.IPagingProvider; +import ca.uhn.fhir.rest.server.IRestfulServerDefaults; +import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilderTest.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilderTest.java new file mode 100644 index 00000000000..e57bec65a94 --- /dev/null +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilderTest.java @@ -0,0 +1,37 @@ +package ca.uhn.fhir.mdm.api.paging; + +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.*; + +class MdmPageLinkBuilderTest { + + @Test + void buildLinkWithExistingParameters() { + //Given + String expected = "http://localhost:8000/$mdm-query-links?sourceResourceId=Patient/123&_offset=1&_count=1"; + String baseUrl = "http://localhost:8000/$mdm-query-links?sourceResourceId=Patient/123"; + + //When + String builtUrl = MdmPageLinkBuilder.buildLinkWithOffsetAndCount(baseUrl, 1, 1); + + //Then + assertThat(builtUrl, is(equalTo(expected))); + } + + @Test + void buildLinkWithoutExistingParameters() { + //Given + String expected = "http://localhost:8000/$mdm-query-links?_offset=1&_count=1"; + String baseUrl = "http://localhost:8000/$mdm-query-links"; + + //When + String builtUrl = MdmPageLinkBuilder.buildLinkWithOffsetAndCount(baseUrl, 1, 1); + + //Then + assertThat(builtUrl, is(equalTo(expected))); + } +} diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index 6dbd96f48be..4e7425aabb1 100644 --- a/hapi-fhir-server-openapi/pom.xml +++ b/hapi-fhir-server-openapi/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index 50ca33467f1..aeba9dd69b6 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java index 07d4b8c41cc..53358593948 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerUtils.java @@ -249,6 +249,13 @@ public class RestfulServerUtils { public static String createLinkSelf(String theServerBase, RequestDetails theRequest) { + return createLinkSelfWithoutGivenParameters(theServerBase, theRequest, null); + } + + /** + * This function will create a self link but omit any parameters passed in via the excludedParameterNames list. + */ + public static String createLinkSelfWithoutGivenParameters(String theServerBase, RequestDetails theRequest, List excludedParameterNames) { StringBuilder b = new StringBuilder(); b.append(theServerBase); @@ -265,21 +272,24 @@ public class RestfulServerUtils { boolean first = true; Map parameters = theRequest.getParameters(); for (String nextParamName : new TreeSet<>(parameters.keySet())) { - for (String nextParamValue : parameters.get(nextParamName)) { - if (first) { - b.append('?'); - first = false; - } else { - b.append('&'); + if (excludedParameterNames == null || !excludedParameterNames.contains(nextParamName)) { + for (String nextParamValue : parameters.get(nextParamName)) { + if (first) { + b.append('?'); + first = false; + } else { + b.append('&'); + } + b.append(UrlUtil.escapeUrlParam(nextParamName)); + b.append('='); + b.append(UrlUtil.escapeUrlParam(nextParamValue)); } - b.append(UrlUtil.escapeUrlParam(nextParamName)); - b.append('='); - b.append(UrlUtil.escapeUrlParam(nextParamValue)); } } } return b.toString(); + } public static String createOffsetPagingLink(BundleLinks theBundleLinks, String requestPath, String tenantId, Integer theOffset, Integer theCount, Map theRequestParameters) { diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleTarget.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleTarget.java index 1d31f2acc21..bc75b118459 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleTarget.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleTarget.java @@ -1,5 +1,25 @@ package ca.uhn.fhir.rest.server.interceptor.auth; +/*- + * #%L + * HAPI FHIR - Server Framework + * %% + * Copyright (C) 2014 - 2021 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.server.RequestDetails; import org.hl7.fhir.instance.model.api.IBaseResource; diff --git a/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerUtilsTest.java b/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerUtilsTest.java index 6e22f74fb6c..1d215bf29aa 100644 --- a/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerUtilsTest.java +++ b/hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/RestfulServerUtilsTest.java @@ -3,8 +3,19 @@ package ca.uhn.fhir.rest.server; import ca.uhn.fhir.rest.api.PreferHandlingEnum; import ca.uhn.fhir.rest.api.PreferHeader; import ca.uhn.fhir.rest.api.PreferReturnEnum; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static ca.uhn.fhir.rest.api.RequestTypeEnum.GET; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.*; public class RestfulServerUtilsTest{ @@ -53,4 +64,37 @@ public class RestfulServerUtilsTest{ assertFalse(header.getRespondAsync()); assertEquals(PreferHandlingEnum.LENIENT, header.getHanding()); } + + @Test + public void testCreateSelfLinks() { + //Given + String baseUrl = "http://localhost:8000"; + Map parameters = new HashMap<>(); + parameters.put("_format", new String[]{"json"}); + parameters.put("_count", new String[]{"10"}); + parameters.put("_offset", new String[]{"100"}); + List paramsToRemove = Arrays.asList("_count", "_offset"); + + ServletRequestDetails servletRequestDetails = new ServletRequestDetails(); + servletRequestDetails.setFhirServerBase("http://localhost:8000"); + servletRequestDetails.setRequestPath("$my-operation"); + servletRequestDetails.setRequestType(GET); + servletRequestDetails.setParameters(parameters); + + //When + String linkSelf = RestfulServerUtils.createLinkSelf(baseUrl, servletRequestDetails); + //Then + assertThat(linkSelf, is(containsString("http://localhost:8000/$my-operation?"))); + assertThat(linkSelf, is(containsString("_format=json"))); + assertThat(linkSelf, is(containsString("_count=10"))); + assertThat(linkSelf, is(containsString("_offset=100"))); + + + //When + String linkSelfWithoutGivenParameters = RestfulServerUtils.createLinkSelfWithoutGivenParameters(baseUrl, servletRequestDetails, paramsToRemove); + //Then + assertThat(linkSelfWithoutGivenParameters, is(containsString("http://localhost:8000/$my-operation?"))); + assertThat(linkSelfWithoutGivenParameters, is(containsString("_format=json"))); + + } } diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index ddddf2f6945..e020964d26b 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index bc8b52dda18..2b83cf773ab 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index 6648b8bfa16..8e831918720 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT hapi-fhir-spring-boot-sample-client-okhttp diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index 63013992f4b..1aa380f6db1 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT hapi-fhir-spring-boot-sample-server-jersey diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index f81e0914b05..ee96476f745 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT hapi-fhir-spring-boot-samples diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index 7e8c6140e02..70db9f63833 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 2b6d680a11d..5f539d55ba5 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index edb8a60d62b..2a9755f1e3e 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 0857d2ad25c..89772c9c5d2 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 2e33baf3495..0d20d066c62 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index 397925bccf6..cd00acad071 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index 349894dc928..c7d11fae560 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index d656094f02a..2c0fd98a493 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index c43cc47ccd8..157e5ae09cf 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 0a6d845d572..e3037a91c04 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index a58fc372368..631c5e84ac6 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 52125a86ff3..807b881d5a6 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 640ad528800..a933f20d9b1 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index 0631cd45e38..aa4e30aac23 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index 3d92ecb11f3..2ac45e333fa 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 40728163aac..5601f452255 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 6fb6706789a..b59764872f4 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml @@ -58,37 +58,37 @@ ca.uhn.hapi.fhir hapi-fhir-structures-dstu3 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-hl7org-dstu2 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-r4 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-structures-r5 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-dstu2 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-dstu3 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ca.uhn.hapi.fhir hapi-fhir-validation-resources-r4 - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT org.apache.velocity diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index c51d1816e68..433091d2fcc 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 932c871db04..6359f2b9f31 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. https://hapifhir.io diff --git a/restful-server-example/pom.xml b/restful-server-example/pom.xml index 17b9a02b40c..0542b16a584 100644 --- a/restful-server-example/pom.xml +++ b/restful-server-example/pom.xml @@ -8,7 +8,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../pom.xml diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index ea34beb93b4..b683cec8202 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index ed069dbf27a..b0d088507d0 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index 5ad0f2d0a38..bbfc4708d61 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 5.5.0-PRE5-SNAPSHOT + 5.5.0-PRE6-SNAPSHOT ../../pom.xml