From a770d577cb121422b2c110060c112a8d4ff030df Mon Sep 17 00:00:00 2001 From: Tadgh Date: Tue, 29 Jun 2021 17:46:03 -0400 Subject: [PATCH 01/17] Initial quick implementation of paging with tests --- .../builder/sql/SearchQueryBuilder.java | 1 - .../uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java | 8 +- .../jpa/mdm/svc/MdmControllerSvcImpl.java | 9 +- .../fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java | 12 +-- .../provider/MdmProviderQueryLinkR4Test.java | 91 ++++++++++++++++++- .../uhn/fhir/mdm/api/IMdmControllerSvc.java | 4 +- .../ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java | 4 +- .../mdm/provider/MdmProviderDstu3Plus.java | 37 +++++++- 8 files changed, 141 insertions(+), 25 deletions(-) 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-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..0399bdcbc1b 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 @@ -33,6 +33,9 @@ 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.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -286,8 +289,9 @@ 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, int theOffset, int theCount) { + PageRequest of = PageRequest.of(theOffset / theCount, theCount); + return myMdmLinkDao.findAll(theExampleLink, of); } /** 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..97b6015320d 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 @@ -66,18 +66,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 Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext, int theOffset, int theCount) { 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, theOffset, theCount); } @Override - public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext) { - return myMdmLinkQuerySvc.getDuplicateGoldenResources(theMdmTransactionContext); + public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext, int theOffset, int theCount) { + return myMdmLinkQuerySvc.getDuplicateGoldenResources(theMdmTransactionContext, theOffset, theCount); } @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..7fd03fb26fd 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 @@ -33,6 +33,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; import java.util.stream.Stream; @@ -46,17 +47,16 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { MdmLinkDaoSvc myMdmLinkDaoSvc; @Override - public Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext) { + public Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, int theOffset, int theCount) { 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, theOffset, theCount); + return mdmLinkByExample.stream().map(this::toJson); } @Override - public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext) { + public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext, int theOffset, int theCount) { Example exampleLink = exampleLinkFromParameters(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null); - return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink).stream().map(this::toJson); + return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, theOffset, theCount).stream().map(this::toJson); } private MdmLinkJson toJson(MdmLink theLink) { 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..418d511538a 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,10 +1,15 @@ 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.IIdType; import org.hl7.fhir.r4.model.BooleanType; @@ -16,12 +21,16 @@ 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 +40,8 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { private StringType myLinkSource; private StringType myGoldenResource1Id; private StringType myGoldenResource2Id; + @Autowired + protected CircularQueueCaptureQueriesListener myCaptureQueriesListener; @Override @BeforeEach @@ -55,7 +66,7 @@ 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(); assertThat(list, hasSize(1)); @@ -63,6 +74,82 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { assertMdmLink(7, part, mySourcePatientId.getValue(), myPatientId.getValue(), MdmMatchResultEnum.POSSIBLE_MATCH, "false", "true", null); } + @Test + 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(); + 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); + offset += count; + assertThat(parameter.size(), is(lessThanOrEqualTo(2))); + + //We have stopped finding patients. + if (StringUtils.isEmpty(sourceResourceIds)) { + break; + } + } + } + + @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 testQueryLinkThreeMatches() { // Add a third patient @@ -71,7 +158,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { 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)); 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..5ff3c62570f 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 @@ -28,9 +28,9 @@ import java.util.stream.Stream; public interface IMdmControllerSvc { - Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext); + Stream queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext, int theOffset, int theCount); - Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext); + Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext, int theOffset, int theCount); 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..28aefbaf550 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 @@ -29,6 +29,6 @@ import java.util.stream.Stream; * 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); + Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, int theOffset, int theCount); + Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext, int theOffset, int theCount); } 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..df6fe73ffc5 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 @@ -29,9 +29,11 @@ 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.model.MdmTransactionContext; +import ca.uhn.fhir.model.api.annotation.Description; 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; @@ -39,6 +41,7 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.BundleBuilder; import ca.uhn.fhir.util.ParametersUtil; 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.IBase; import org.hl7.fhir.instance.model.api.IBaseBackboneElement; @@ -58,6 +61,9 @@ import java.util.List; import java.util.UUID; import java.util.stream.Stream; +import static ca.uhn.fhir.rest.api.Constants.PARAM_COUNT; +import static ca.uhn.fhir.rest.api.Constants.PARAM_OFFSET; + public class MdmProviderDstu3Plus extends BaseMdmProvider { private final IMdmControllerSvc myMdmControllerSvc; @@ -189,22 +195,43 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { 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, + @OperationParam(name = ProviderConstants.MDM_QUERY_LINKS_LINK_SOURCE, min = 0, max = 1, typeName = "string") + IPrimitiveType theLinkSource, + + @Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") + @OperationParam(name = PARAM_OFFSET) + UnsignedIntType 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) + UnsignedIntType theCount, + ServletRequestDetails theRequestDetails) { + validatePagingParameters(theOffset, theCount); Stream 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)) + getResourceType(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId)), theOffset.getValue(), theCount.getValue() ); return parametersFromMdmLinks(mdmLinkJson, true); } + private void validatePagingParameters(UnsignedIntType theOffset, UnsignedIntType theCount) { + String errorMessage = ""; + if (theOffset!= null && theOffset.getValue() < 0) { + errorMessage += PARAM_OFFSET + " must be greater than or equal to 0. "; + } + if (theCount != null && theCount.getValue() <= 0 ) { + errorMessage += PARAM_COUNT + " must be greater than 0."; + } + if (StringUtils.isNotEmpty(errorMessage)) { + throw new InvalidRequestException(errorMessage); + } + } + @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) - ); + Stream possibleDuplicates = myMdmControllerSvc.getDuplicateGoldenResources(createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.DUPLICATE_GOLDEN_RESOURCES, (String) null),0,10); return parametersFromMdmLinks(possibleDuplicates, false); } From 61260dd1b11768cdfa42c3bae7c7dcc5dc4c48f3 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 11:54:59 -0400 Subject: [PATCH 02/17] Slightly more portable solution for paging --- .../uhn/fhir/jpa/mdm/dao/MdmLinkDaoSvc.java | 8 +-- .../jpa/mdm/svc/MdmControllerSvcImpl.java | 11 +-- .../fhir/jpa/mdm/svc/MdmLinkQuerySvcImpl.java | 16 +++-- .../jpa/mdm/provider/BaseProviderR4Test.java | 5 +- .../provider/MdmProviderQueryLinkR4Test.java | 2 +- hapi-fhir-server-mdm/pom.xml | 5 ++ .../uhn/fhir/mdm/api/IMdmControllerSvc.java | 7 +- .../ca/uhn/fhir/mdm/api/IMdmLinkQuerySvc.java | 8 +-- .../mdm/api/paging/MdmPageLinkBuilder.java | 38 ++++++++++ .../fhir/mdm/api/paging/MdmPageLinkTuple.java | 36 ++++++++++ .../fhir/mdm/api/paging/MdmPageRequest.java | 69 +++++++++++++++++++ .../fhir/mdm/provider/BaseMdmProvider.java | 26 ++++++- .../mdm/provider/MdmProviderDstu3Plus.java | 58 ++++++++-------- .../fhir/mdm/provider/MdmProviderLoader.java | 5 +- .../fhir/rest/server/RestfulServerUtils.java | 25 ++++--- 15 files changed, 253 insertions(+), 66 deletions(-) create mode 100644 hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilder.java create mode 100644 hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkTuple.java create mode 100644 hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java 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 0399bdcbc1b..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,6 +27,7 @@ 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; @@ -34,8 +35,6 @@ 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.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -289,9 +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 Page findMdmLinkByExample(Example theExampleLink, int theOffset, int theCount) { - PageRequest of = PageRequest.of(theOffset / theCount, theCount); - return myMdmLinkDao.findAll(theExampleLink, of); + 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 97b6015320d..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,17 +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, int theOffset, int theCount) { + 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, theOffset, theCount); + return myMdmLinkQuerySvc.queryLinks(goldenResourceId, sourceId, matchResult, linkSource, theMdmTransactionContext, thePageRequest); } @Override - public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext, int theOffset, int theCount) { - return myMdmLinkQuerySvc.getDuplicateGoldenResources(theMdmTransactionContext, theOffset, theCount); + 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 7fd03fb26fd..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; @@ -35,8 +36,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; -import java.util.stream.Stream; - public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { private static final Logger ourLog = LoggerFactory.getLogger(MdmLinkQuerySvcImpl.class); @@ -47,16 +46,19 @@ public class MdmLinkQuerySvcImpl implements IMdmLinkQuerySvc { MdmLinkDaoSvc myMdmLinkDaoSvc; @Override - public Stream queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, int theOffset, int theCount) { + public Page queryLinks(IIdType theGoldenResourceId, IIdType theSourceResourceId, MdmMatchResultEnum theMatchResult, MdmLinkSourceEnum theLinkSource, MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest) { Example exampleLink = exampleLinkFromParameters(theGoldenResourceId, theSourceResourceId, theMatchResult, theLinkSource); - Page mdmLinkByExample = myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, theOffset, theCount); - return mdmLinkByExample.stream().map(this::toJson); + Page mdmLinkByExample = myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, thePageRequest); + Page map = mdmLinkByExample.map(this::toJson); + return map; } @Override - public Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext, int theOffset, int theCount) { + public Page getDuplicateGoldenResources(MdmTransactionContext theMdmContext, MdmPageRequest thePageRequest) { Example exampleLink = exampleLinkFromParameters(null, null, MdmMatchResultEnum.POSSIBLE_DUPLICATE, null); - return myMdmLinkDaoSvc.findMdmLinkByExample(exampleLink, theOffset, theCount).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/provider/BaseProviderR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/BaseProviderR4Test.java index fd2647bb304..c3794c183ab 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,7 @@ 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.IRestfulServerDefaults; import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterEach; @@ -29,6 +30,8 @@ public abstract class BaseProviderR4Test extends BaseMdmR4Test { private IMdmSubmitSvc myMdmSubmitSvc; @Autowired private MdmSettings myMdmSettings; + @Autowired + private IRestfulServerDefaults myRestfulServerDefaults; private String defaultScript; @@ -42,7 +45,7 @@ public abstract class BaseProviderR4Test extends BaseMdmR4Test { @BeforeEach public void before() { - myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc); + myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myRestfulServerDefaults); defaultScript = myMdmSettings.getScriptText(); } @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 418d511538a..35308e62402 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 @@ -90,7 +90,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { ourLog.warn("Search at offset {} took {}ms",offset, sw.getMillisAndRestart()); ourLog.warn("Found source resource IDs: {}", sourceResourceIds); offset += count; - assertThat(parameter.size(), is(lessThanOrEqualTo(2))); + assertThat(parameter.size(), is(lessThanOrEqualTo(3))); //We have stopped finding patients. if (StringUtils.isEmpty(sourceResourceIds)) { diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index bf1e50dd9e9..3e9be79e7f4 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/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 5ff3c62570f..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, int theOffset, int theCount); + Page queryLinks(@Nullable String theGoldenResourceId, @Nullable String theSourceResourceId, @Nullable String theMatchResult, @Nullable String theLinkSource, MdmTransactionContext theMdmTransactionContext, MdmPageRequest thePageRequest); - Stream getDuplicateGoldenResources(MdmTransactionContext theMdmTransactionContext, int theOffset, int theCount); + 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 28aefbaf550..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, int theOffset, int theCount); - Stream getDuplicateGoldenResources(MdmTransactionContext theMdmContext, int theOffset, int theCount); + 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..7940cd1eb02 --- /dev/null +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilder.java @@ -0,0 +1,38 @@ +package ca.uhn.fhir.mdm.api.paging; + +import ca.uhn.fhir.mdm.api.MdmLinkJson; +import ca.uhn.fhir.rest.server.RestfulServerUtils; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; +import ca.uhn.fhir.util.ParametersUtil; +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; + +public final class MdmPageLinkBuilder { + public static MdmPageLinkTuple buildMdmPageLinks(ServletRequestDetails theServletRequestDetails, Page theCurrentPage, MdmPageRequest thePageRequest) { + MdmPageLinkTuple tuple = new MdmPageLinkTuple(); + String urlWithoutPaging = RestfulServerUtils.createLinkSelfWithoutGivenParameters(theServletRequestDetails.getFhirServerBase(), theServletRequestDetails, Arrays.asList(PARAM_OFFSET, PARAM_COUNT)); + tuple.setSelfLink(buildLinkWithOffsetAndCount(urlWithoutPaging, thePageRequest.getCount(), thePageRequest.getOffset())); + if (theCurrentPage.hasNext()) { + tuple.setNextLink(buildLinkWithOffsetAndCount(urlWithoutPaging,thePageRequest.getCount(), thePageRequest.getNextOffset())); + } + if (theCurrentPage.hasPrevious()) { + tuple.setPreviousLink(buildLinkWithOffsetAndCount(urlWithoutPaging,thePageRequest.getCount(), thePageRequest.getPreviousOffset())); + } + return tuple; + + } + protected static String buildLinkWithOffsetAndCount(String theStartingUrl, int theCount, int theOffset) { + StringBuilder builder = new StringBuilder(); + builder.append(theStartingUrl); + if (!theStartingUrl.contains("?")) { + builder.append("?"); + } + builder.append(PARAM_OFFSET).append("=").append(theOffset); + 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..f6600f46eec --- /dev/null +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkTuple.java @@ -0,0 +1,36 @@ +package ca.uhn.fhir.mdm.api.paging; + +import java.util.Optional; + +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..a971641c22d --- /dev/null +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java @@ -0,0 +1,69 @@ +package ca.uhn.fhir.mdm.api.paging; + +import ca.uhn.fhir.rest.server.IRestfulServerDefaults; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.dstu3.model.UnsignedIntType; +import org.slf4j.Logger; +import org.springframework.data.domain.PageRequest; + +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; + +public class MdmPageRequest { + private static final Logger ourLog = getLogger(MdmPageRequest.class); + + private int myPage; + private int myOffset; + private int myCount; + private IRestfulServerDefaults myRestfulServerDefaults; + + public MdmPageRequest(UnsignedIntType theOffset, UnsignedIntType theCount, IRestfulServerDefaults theDefaults) { + myOffset = theOffset == null ? 0 : theOffset.getValue(); + myCount = theCount == null ? theDefaults.getDefaultPageSize() : theCount.getValue(); + validatePagingParameters(myOffset, myCount); + + this.myPage = myOffset / myCount; + } + + public PageRequest toPageRequest() { + return PageRequest.of(this.myPage, this.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 (myRestfulServerDefaults.getMaximumPageSize() != null && theCount > myRestfulServerDefaults.getMaximumPageSize() ) { + ourLog.debug("Shrinking page size down to {}, as this is the maximum allowed.", myRestfulServerDefaults.getMaximumPageSize()); + } + 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; + } +} 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..466011fc4f7 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,26 @@ 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.RestfulServerUtils; 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; +import java.util.Arrays; + +import static ca.uhn.fhir.rest.api.Constants.PARAM_COUNT; +import static ca.uhn.fhir.rest.api.Constants.PARAM_OFFSET; public abstract class BaseMdmProvider { @@ -92,9 +101,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 +120,15 @@ public abstract class BaseMdmProvider { return retval; } + protected void addPagingParameters(IBaseParameters theParameters, Page theCurrentPage, ServletRequestDetails theServletRequestDetails, MdmPageRequest thePageRequest) { + MdmPageLinkTuple mdmPageLinkTuple = MdmPageLinkBuilder.buildMdmPageLinks(theServletRequestDetails, theCurrentPage, thePageRequest); + ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "self", mdmPageLinkTuple.getSelfLink()); + + if (mdmPageLinkTuple.getNextLink().isPresent()) { + ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "next", mdmPageLinkTuple.getNextLink().get()); + } + if (mdmPageLinkTuple.getPreviousLink().isPresent()) { + ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "prev", mdmPageLinkTuple.getPreviousLink().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 df6fe73ffc5..4b06805c8f8 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,6 +28,7 @@ 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.rest.annotation.IdParam; @@ -35,6 +36,7 @@ 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.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; @@ -52,6 +54,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; @@ -59,17 +63,19 @@ 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_COUNT; 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; + private final IRestfulServerDefaults myRestfulServerDefaults; /** * Constructor @@ -77,12 +83,13 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { * Note that this is not a spring bean. Any necessary injections should * happen in the constructor */ - public MdmProviderDstu3Plus(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc, IMdmMatchFinderSvc theMdmMatchFinderSvc, IMdmExpungeSvc theMdmExpungeSvc, IMdmSubmitSvc theMdmSubmitSvc) { + public MdmProviderDstu3Plus(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc, IMdmMatchFinderSvc theMdmMatchFinderSvc, IMdmExpungeSvc theMdmExpungeSvc, IMdmSubmitSvc theMdmSubmitSvc, IRestfulServerDefaults theRestfulServerDefaults) { super(theFhirContext); myMdmControllerSvc = theMdmControllerSvc; myMdmMatchFinderSvc = theMdmMatchFinderSvc; myMdmExpungeSvc = theMdmExpungeSvc; myMdmSubmitSvc = theMdmSubmitSvc; + myRestfulServerDefaults = theRestfulServerDefaults; } @Operation(name = ProviderConstants.EMPI_MATCH, typeName = "Patient") @@ -199,40 +206,38 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { IPrimitiveType theLinkSource, @Description(formalDefinition="Results from this method are returned across multiple pages. This parameter controls the offset when fetching a page.") - @OperationParam(name = PARAM_OFFSET) + @OperationParam(name = PARAM_OFFSET, min = 0, max = 1) UnsignedIntType 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) + @OperationParam(name = Constants.PARAM_COUNT, min = 0, max = 1) UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - validatePagingParameters(theOffset, theCount); - - Stream mdmLinkJson = myMdmControllerSvc.queryLinks(extractStringOrNull(theGoldenResourceId), + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myRestfulServerDefaults); + 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)), theOffset.getValue(), theCount.getValue() - ); - return parametersFromMdmLinks(mdmLinkJson, true); + getResourceType(ProviderConstants.MDM_QUERY_LINKS_GOLDEN_RESOURCE_ID, theGoldenResourceId)), mdmPageRequest); + + return parametersFromMdmLinks(mdmLinkJson, true, theRequestDetails, mdmPageRequest); } - private void validatePagingParameters(UnsignedIntType theOffset, UnsignedIntType theCount) { - String errorMessage = ""; - if (theOffset!= null && theOffset.getValue() < 0) { - errorMessage += PARAM_OFFSET + " must be greater than or equal to 0. "; - } - if (theCount != null && theCount.getValue() <= 0 ) { - errorMessage += PARAM_COUNT + " must be greater than 0."; - } - if (StringUtils.isNotEmpty(errorMessage)) { - throw new InvalidRequestException(errorMessage); - } - } @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),0,10); - 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) + UnsignedIntType 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) + UnsignedIntType theCount, + ServletRequestDetails theRequestDetails) { + + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myRestfulServerDefaults); + + 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) @@ -260,7 +265,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..3ad3ee06e6a 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,7 @@ 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.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -46,6 +47,8 @@ public class MdmProviderLoader { private IMdmExpungeSvc myMdmExpungeSvc; @Autowired private IMdmSubmitSvc myMdmSubmitSvc; + @Autowired + private IRestfulServerDefaults myRestfulServerDefaults; private BaseMdmProvider myMdmProvider; @@ -54,7 +57,7 @@ public class MdmProviderLoader { case DSTU3: case R4: myResourceProviderFactory.addSupplier(() -> { - myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc); + myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myRestfulServerDefaults); return myMdmProvider; }); break; 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..e4ce660e2c7 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,10 @@ public class RestfulServerUtils { public static String createLinkSelf(String theServerBase, RequestDetails theRequest) { + return createLinkSelfWithoutGivenParameters(theServerBase, theRequest, null); + } + + public static String createLinkSelfWithoutGivenParameters(String theServerBase, RequestDetails theRequest, List excludedParameterNames) { StringBuilder b = new StringBuilder(); b.append(theServerBase); @@ -265,21 +269,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) { From 8f3cbb0a7f1c004522bdb7e890375272ed2501ff Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 14:48:13 -0400 Subject: [PATCH 03/17] Refactor docs --- .../java/ca/uhn/fhir/util/ParametersUtil.java | 1 - .../docs/server_jpa_mdm/mdm_operations.md | 116 +++++++++++++++++- .../ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java | 18 +++ .../jpa/mdm/config/BaseTestMdmConfig.java | 2 + .../jpa/mdm/provider/BaseProviderR4Test.java | 5 +- .../provider/MdmProviderQueryLinkR4Test.java | 39 ++++-- .../fhir/mdm/api/paging/MdmPageRequest.java | 16 ++- .../fhir/mdm/provider/BaseMdmProvider.java | 8 +- .../mdm/provider/MdmProviderDstu3Plus.java | 11 +- .../fhir/mdm/provider/MdmProviderLoader.java | 6 +- 10 files changed, 193 insertions(+), 29 deletions(-) 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-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..2c25378c45d 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,51 @@ 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 +``` +You could use request body +```json +{ + "resourceType": "Parameters", + "parameter": [ { + "name": "_offset", + "valueInt": 0 + }, { + "name": "_count", + "valueInt": 2 + } ] +} +``` + +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=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" + },...(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 +95,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 +119,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 +128,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 +149,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 +198,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`: @@ -583,3 +693,7 @@ This operation can also be done at the Instance level. When this is the case, th http://example.com/Patient/123/$mdm-submit http://example.com/Practitioner/456/$mdm-submit ``` + + + + 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 c3794c183ab..756168188cb 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,7 @@ 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; @@ -31,7 +32,7 @@ public abstract class BaseProviderR4Test extends BaseMdmR4Test { @Autowired private MdmSettings myMdmSettings; @Autowired - private IRestfulServerDefaults myRestfulServerDefaults; + private IPagingProvider myPagingProvider; private String defaultScript; @@ -45,7 +46,7 @@ public abstract class BaseProviderR4Test extends BaseMdmR4Test { @BeforeEach public void before() { - myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myRestfulServerDefaults); + myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myPagingProvider); defaultScript = myMdmSettings.getScriptText(); } @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 35308e62402..008c8e7c5f2 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 @@ -11,12 +11,14 @@ 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; @@ -86,19 +88,38 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { while (true) { Parameters result = (Parameters) myMdmProvider.queryLinks(null, null, null, myLinkSource, new UnsignedIntType(offset), new UnsignedIntType(count), myRequestDetails); List parameter = result.getParameter(); - 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); - offset += count; - assertThat(parameter.size(), is(lessThanOrEqualTo(3))); - //We have stopped finding patients. + + 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 @@ -168,7 +189,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { @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(); assertThat(list, hasSize(1)); @@ -179,7 +200,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { @Test public void testNotDuplicate() { { - Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(myRequestDetails); + Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); List list = result.getParameter(); assertThat(list, hasSize(1)); } @@ -190,7 +211,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { assertTrue(((BooleanType) (result.getParameterFirstRep().getValue())).booleanValue()); } - Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(myRequestDetails); + Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); List list = result.getParameter(); assertThat(list, hasSize(0)); } 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 index a971641c22d..8f3a04b5228 100644 --- 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 @@ -1,5 +1,6 @@ package ca.uhn.fhir.mdm.api.paging; +import ca.uhn.fhir.rest.server.IPagingProvider; import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import org.apache.commons.lang3.StringUtils; @@ -17,11 +18,17 @@ public class MdmPageRequest { private int myPage; private int myOffset; private int myCount; - private IRestfulServerDefaults myRestfulServerDefaults; + private IPagingProvider myPagingProvider; - public MdmPageRequest(UnsignedIntType theOffset, UnsignedIntType theCount, IRestfulServerDefaults theDefaults) { + public MdmPageRequest(UnsignedIntType theOffset, UnsignedIntType theCount, IPagingProvider thePagingProvider) { + myPagingProvider = thePagingProvider; myOffset = theOffset == null ? 0 : theOffset.getValue(); - myCount = theCount == null ? theDefaults.getDefaultPageSize() : theCount.getValue(); + myCount = theCount == null ? myPagingProvider.getDefaultPageSize() : theCount.getValue(); + + if (myCount > myPagingProvider.getMaximumPageSize()) { + ourLog.debug("Reducing count {} to paging provider's maximum of {}", theCount, myPagingProvider.getMaximumPageSize()); + myCount = myPagingProvider.getMaximumPageSize(); + } validatePagingParameters(myOffset, myCount); this.myPage = myOffset / myCount; @@ -40,9 +47,6 @@ public class MdmPageRequest { if (theCount <= 0 ) { errorMessage += PARAM_COUNT + " must be greater than 0."; } - if (myRestfulServerDefaults.getMaximumPageSize() != null && theCount > myRestfulServerDefaults.getMaximumPageSize() ) { - ourLog.debug("Shrinking page size down to {}, as this is the maximum allowed.", myRestfulServerDefaults.getMaximumPageSize()); - } if (StringUtils.isNotEmpty(errorMessage)) { throw new InvalidRequestException(errorMessage); } 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 466011fc4f7..239780fd69c 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 @@ -122,13 +122,15 @@ public abstract class BaseMdmProvider { 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()); } - if (mdmPageLinkTuple.getPreviousLink().isPresent()) { - ParametersUtil.addParameterToParametersUri(myFhirContext, theParameters, "prev", mdmPageLinkTuple.getPreviousLink().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 4b06805c8f8..e9e923a7dcc 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 @@ -36,6 +36,7 @@ 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.IPagingProvider; import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; @@ -75,7 +76,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { private final IMdmMatchFinderSvc myMdmMatchFinderSvc; private final IMdmExpungeSvc myMdmExpungeSvc; private final IMdmSubmitSvc myMdmSubmitSvc; - private final IRestfulServerDefaults myRestfulServerDefaults; + private final IPagingProvider myPagingProvider; /** * Constructor @@ -83,13 +84,13 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { * Note that this is not a spring bean. Any necessary injections should * happen in the constructor */ - public MdmProviderDstu3Plus(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc, IMdmMatchFinderSvc theMdmMatchFinderSvc, IMdmExpungeSvc theMdmExpungeSvc, IMdmSubmitSvc theMdmSubmitSvc, IRestfulServerDefaults theRestfulServerDefaults) { + public MdmProviderDstu3Plus(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc, IMdmMatchFinderSvc theMdmMatchFinderSvc, IMdmExpungeSvc theMdmExpungeSvc, IMdmSubmitSvc theMdmSubmitSvc, IPagingProvider thePagingProvider) { super(theFhirContext); myMdmControllerSvc = theMdmControllerSvc; myMdmMatchFinderSvc = theMdmMatchFinderSvc; myMdmExpungeSvc = theMdmExpungeSvc; myMdmSubmitSvc = theMdmSubmitSvc; - myRestfulServerDefaults = theRestfulServerDefaults; + myPagingProvider = thePagingProvider; } @Operation(name = ProviderConstants.EMPI_MATCH, typeName = "Patient") @@ -213,7 +214,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myRestfulServerDefaults); + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider); Page mdmLinkJson = myMdmControllerSvc.queryLinks(extractStringOrNull(theGoldenResourceId), extractStringOrNull(theResourceId), extractStringOrNull(theMatchResult), extractStringOrNull(theLinkSource), createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.QUERY_LINKS, @@ -233,7 +234,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myRestfulServerDefaults); + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider); Page possibleDuplicates = myMdmControllerSvc.getDuplicateGoldenResources(createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.DUPLICATE_GOLDEN_RESOURCES, (String) null), mdmPageRequest); 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 3ad3ee06e6a..27637899b8e 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,7 +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; @@ -48,7 +50,7 @@ public class MdmProviderLoader { @Autowired private IMdmSubmitSvc myMdmSubmitSvc; @Autowired - private IRestfulServerDefaults myRestfulServerDefaults; + private IPagingProvider myPagingProvider; private BaseMdmProvider myMdmProvider; @@ -57,7 +59,7 @@ public class MdmProviderLoader { case DSTU3: case R4: myResourceProviderFactory.addSupplier(() -> { - myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myRestfulServerDefaults); + myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myPagingProvider); return myMdmProvider; }); break; From 91dee5527999d2b3714903396deef600b6612c63 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 14:49:37 -0400 Subject: [PATCH 04/17] Correct docs --- .../uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 2c25378c45d..1d03c7a13e2 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 @@ -18,16 +18,18 @@ Or if you are making a POST request ```http request POST http://example.com/$mdm-query-links ``` -You could use request body + +With request body: + ```json { "resourceType": "Parameters", "parameter": [ { "name": "_offset", - "valueInt": 0 + "valueInteger": 0 }, { "name": "_count", - "valueInt": 2 + "valueInteger": 2 } ] } ``` From 883337a9f4b71dd9c6a8f5aca0702a8fbfc2f9ae Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 14:55:57 -0400 Subject: [PATCH 05/17] Tidying --- .../fhir/docs/server_jpa_mdm/mdm_operations.md | 4 ---- .../mdm/api/paging/MdmPageLinkBuilder.java | 18 +++++++++++++++--- .../fhir/mdm/api/paging/MdmPageRequest.java | 15 ++++++++++----- 3 files changed, 25 insertions(+), 12 deletions(-) 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 1d03c7a13e2..3b191a26e6d 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 @@ -695,7 +695,3 @@ This operation can also be done at the Instance level. When this is the case, th http://example.com/Patient/123/$mdm-submit http://example.com/Practitioner/456/$mdm-submit ``` - - - - 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 index 7940cd1eb02..7aa82a5f3f4 100644 --- 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 @@ -3,7 +3,6 @@ package ca.uhn.fhir.mdm.api.paging; import ca.uhn.fhir.mdm.api.MdmLinkJson; import ca.uhn.fhir.rest.server.RestfulServerUtils; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; -import ca.uhn.fhir.util.ParametersUtil; import org.springframework.data.domain.Page; import java.util.Arrays; @@ -11,7 +10,20 @@ 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) { MdmPageLinkTuple tuple = new MdmPageLinkTuple(); String urlWithoutPaging = RestfulServerUtils.createLinkSelfWithoutGivenParameters(theServletRequestDetails.getFhirServerBase(), theServletRequestDetails, Arrays.asList(PARAM_OFFSET, PARAM_COUNT)); @@ -23,9 +35,9 @@ public final class MdmPageLinkBuilder { tuple.setPreviousLink(buildLinkWithOffsetAndCount(urlWithoutPaging,thePageRequest.getCount(), thePageRequest.getPreviousOffset())); } return tuple; - } - protected static String buildLinkWithOffsetAndCount(String theStartingUrl, int theCount, int theOffset) { + + private static String buildLinkWithOffsetAndCount(String theStartingUrl, int theCount, int theOffset) { StringBuilder builder = new StringBuilder(); builder.append(theStartingUrl); if (!theStartingUrl.contains("?")) { 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 index 8f3a04b5228..b79c8d6c05b 100644 --- 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 @@ -1,7 +1,6 @@ package ca.uhn.fhir.mdm.api.paging; import ca.uhn.fhir.rest.server.IPagingProvider; -import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.dstu3.model.UnsignedIntType; @@ -12,6 +11,11 @@ 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 static final Logger ourLog = getLogger(MdmPageRequest.class); @@ -34,10 +38,6 @@ public class MdmPageRequest { this.myPage = myOffset / myCount; } - public PageRequest toPageRequest() { - return PageRequest.of(this.myPage, this.myCount); - } - private void validatePagingParameters(int theOffset, int theCount) { String errorMessage = ""; @@ -67,7 +67,12 @@ public class MdmPageRequest { public int getNextOffset() { return myOffset + myCount; } + public int getPreviousOffset() { return myOffset - myCount; } + + public PageRequest toPageRequest() { + return PageRequest.of(this.myPage, this.myCount); + } } From d407501071754bd32a871969143953ef52c7c92f Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 15:04:05 -0400 Subject: [PATCH 06/17] More docs --- .../fhir/mdm/api/paging/MdmPageLinkTuple.java | 6 ++++-- .../fhir/mdm/api/paging/MdmPageRequest.java | 21 ++++++++----------- .../mdm/provider/MdmProviderDstu3Plus.java | 1 - .../fhir/rest/server/RestfulServerUtils.java | 3 +++ 4 files changed, 16 insertions(+), 15 deletions(-) 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 index f6600f46eec..c881dd518c4 100644 --- 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 @@ -2,13 +2,15 @@ package ca.uhn.fhir.mdm.api.paging; 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() { - } + MdmPageLinkTuple() {} public Optional getPreviousLink() { return Optional.ofNullable(myPreviousLink); 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 index b79c8d6c05b..92f01e1360e 100644 --- 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 @@ -7,6 +7,8 @@ import org.hl7.fhir.dstu3.model.UnsignedIntType; 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; @@ -17,22 +19,17 @@ import static org.slf4j.LoggerFactory.getLogger; * but we are using `offset` and `count` which requires some minor translation. */ public class MdmPageRequest { - private static final Logger ourLog = getLogger(MdmPageRequest.class); - private int myPage; - private int myOffset; - private int myCount; - private IPagingProvider myPagingProvider; + private final int myPage; + private final int myOffset; + private final int myCount; - public MdmPageRequest(UnsignedIntType theOffset, UnsignedIntType theCount, IPagingProvider thePagingProvider) { - myPagingProvider = thePagingProvider; + public MdmPageRequest(@Nullable UnsignedIntType theOffset, @Nullable UnsignedIntType theCount, IPagingProvider thePagingProvider) { myOffset = theOffset == null ? 0 : theOffset.getValue(); - myCount = theCount == null ? myPagingProvider.getDefaultPageSize() : theCount.getValue(); + myCount = theCount == null + ? thePagingProvider.getDefaultPageSize() : theCount.getValue() > thePagingProvider.getMaximumPageSize() + ? thePagingProvider.getMaximumPageSize() : theCount.getValue(); - if (myCount > myPagingProvider.getMaximumPageSize()) { - ourLog.debug("Reducing count {} to paging provider's maximum of {}", theCount, myPagingProvider.getMaximumPageSize()); - myCount = myPagingProvider.getMaximumPageSize(); - } validatePagingParameters(myOffset, myCount); this.myPage = myOffset / myCount; 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 e9e923a7dcc..abdb331f50e 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 @@ -198,7 +198,6 @@ 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, 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 e4ce660e2c7..a213fb5f76e 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 @@ -252,6 +252,9 @@ public class RestfulServerUtils { 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); From f33696a165f54cb24657e7a475576577266cdd2e Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 15:24:29 -0400 Subject: [PATCH 07/17] Add changelog --- .../hapi/fhir/changelog/5_5_0/2767-mdm-query-paging.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_5_0/2767-mdm-query-paging.yaml 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)." + From f66f9b992e4557d93a5a1cb1dc08f6a88846cf7a Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 15:37:19 -0400 Subject: [PATCH 08/17] Bump pre-version as this will break downstream implementations --- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- hapi-fhir-bom/pom.xml | 4 ++-- hapi-fhir-cli/hapi-fhir-cli-api/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-jpaserver/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- hapi-fhir-converter/pom.xml | 2 +- hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-docs/pom.xml | 2 +- hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jaxrsserver-example/pom.xml | 2 +- hapi-fhir-jpaserver-api/pom.xml | 2 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- hapi-fhir-jpaserver-batch/pom.xml | 2 +- hapi-fhir-jpaserver-cql/pom.xml | 2 +- hapi-fhir-jpaserver-mdm/pom.xml | 2 +- hapi-fhir-jpaserver-migrate/pom.xml | 2 +- hapi-fhir-jpaserver-model/pom.xml | 2 +- hapi-fhir-jpaserver-searchparam/pom.xml | 2 +- hapi-fhir-jpaserver-subscription/pom.xml | 2 +- hapi-fhir-jpaserver-test-utilities/pom.xml | 2 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 2 +- hapi-fhir-server-mdm/pom.xml | 2 +- hapi-fhir-server-openapi/pom.xml | 2 +- hapi-fhir-server/pom.xml | 2 +- .../hapi-fhir-spring-boot-autoconfigure/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../hapi-fhir-spring-boot-samples/pom.xml | 2 +- .../hapi-fhir-spring-boot-starter/pom.xml | 2 +- hapi-fhir-spring-boot/pom.xml | 2 +- hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- hapi-fhir-structures-dstu3/pom.xml | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- hapi-fhir-structures-r5/pom.xml | 2 +- hapi-fhir-test-utilities/pom.xml | 2 +- hapi-fhir-testpage-overlay/pom.xml | 2 +- hapi-fhir-validation-resources-dstu2.1/pom.xml | 2 +- hapi-fhir-validation-resources-dstu2/pom.xml | 2 +- hapi-fhir-validation-resources-dstu3/pom.xml | 2 +- hapi-fhir-validation-resources-r4/pom.xml | 2 +- hapi-fhir-validation-resources-r5/pom.xml | 2 +- hapi-fhir-validation/pom.xml | 2 +- hapi-tinder-plugin/pom.xml | 16 ++++++++-------- hapi-tinder-test/pom.xml | 2 +- pom.xml | 2 +- restful-server-example/pom.xml | 2 +- .../pom.xml | 2 +- tests/hapi-fhir-base-test-mindeps-client/pom.xml | 2 +- tests/hapi-fhir-base-test-mindeps-server/pom.xml | 2 +- 58 files changed, 66 insertions(+), 66 deletions(-) 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-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-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-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-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 3e9be79e7f4..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 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-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 From 9f3b262d6d303d5bfb7570973110299c8b1af063 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 17:54:09 -0400 Subject: [PATCH 09/17] Add alternate caller methods --- .../mdm/api/paging/MdmPageLinkBuilder.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) 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 index 7aa82a5f3f4..aac24db86d9 100644 --- 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 @@ -25,22 +25,27 @@ public final class MdmPageLinkBuilder { * @return the {@link MdmPageLinkTuple} */ public static MdmPageLinkTuple buildMdmPageLinks(ServletRequestDetails theServletRequestDetails, Page theCurrentPage, MdmPageRequest thePageRequest) { - MdmPageLinkTuple tuple = new MdmPageLinkTuple(); String urlWithoutPaging = RestfulServerUtils.createLinkSelfWithoutGivenParameters(theServletRequestDetails.getFhirServerBase(), theServletRequestDetails, Arrays.asList(PARAM_OFFSET, PARAM_COUNT)); - tuple.setSelfLink(buildLinkWithOffsetAndCount(urlWithoutPaging, thePageRequest.getCount(), thePageRequest.getOffset())); - if (theCurrentPage.hasNext()) { - tuple.setNextLink(buildLinkWithOffsetAndCount(urlWithoutPaging,thePageRequest.getCount(), thePageRequest.getNextOffset())); - } - if (theCurrentPage.hasPrevious()) { - tuple.setPreviousLink(buildLinkWithOffsetAndCount(urlWithoutPaging,thePageRequest.getCount(), thePageRequest.getPreviousOffset())); - } - return tuple; + return buildMdmPageLinks(urlWithoutPaging, theCurrentPage, thePageRequest); } - private static String buildLinkWithOffsetAndCount(String theStartingUrl, int theCount, int theOffset) { + 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(theStartingUrl); - if (!theStartingUrl.contains("?")) { + builder.append(theBaseUrl); + if (!theBaseUrl.contains("?")) { builder.append("?"); } builder.append(PARAM_OFFSET).append("=").append(theOffset); From 950096d42fcaf94a8561ecb9204b461071b8ed84 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 18:21:08 -0400 Subject: [PATCH 10/17] remove demand for paging provider --- .../ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java | 13 +++++++++---- .../uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) 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 index 92f01e1360e..6e401a58b0e 100644 --- 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 @@ -24,12 +24,17 @@ public class MdmPageRequest { private final int myOffset; private final int myCount; - public MdmPageRequest(@Nullable UnsignedIntType theOffset, @Nullable UnsignedIntType theCount, IPagingProvider thePagingProvider) { + public MdmPageRequest(@Nullable UnsignedIntType theOffset, @Nullable UnsignedIntType theCount, int theDefaultPageSize, int theMaximumPageSize) { myOffset = theOffset == null ? 0 : theOffset.getValue(); - myCount = theCount == null - ? thePagingProvider.getDefaultPageSize() : theCount.getValue() > thePagingProvider.getMaximumPageSize() - ? thePagingProvider.getMaximumPageSize() : theCount.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; 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 abdb331f50e..b1b4081fb3a 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 @@ -213,7 +213,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider); + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider.getDefaultPageSize(), myPagingProvider.getMaximumPageSize()); Page mdmLinkJson = myMdmControllerSvc.queryLinks(extractStringOrNull(theGoldenResourceId), extractStringOrNull(theResourceId), extractStringOrNull(theMatchResult), extractStringOrNull(theLinkSource), createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.QUERY_LINKS, @@ -233,7 +233,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider); + MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider.getDefaultPageSize(), myPagingProvider.getMaximumPageSize()); Page possibleDuplicates = myMdmControllerSvc.getDuplicateGoldenResources(createMdmContext(theRequestDetails, MdmTransactionContext.OperationType.DUPLICATE_GOLDEN_RESOURCES, (String) null), mdmPageRequest); From 1eb82d633d71467b2b2eeb0b5b4df80e3204848c Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 18:41:18 -0400 Subject: [PATCH 11/17] Rip out pagingprovider requirement --- .../uhn/fhir/jpa/mdm/provider/BaseProviderR4Test.java | 4 +--- .../ca/uhn/fhir/mdm/provider/BaseMdmProvider.java | 5 ----- .../uhn/fhir/mdm/provider/MdmProviderDstu3Plus.java | 11 ++++++----- .../ca/uhn/fhir/mdm/provider/MdmProviderLoader.java | 4 +--- 4 files changed, 8 insertions(+), 16 deletions(-) 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 756168188cb..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 @@ -31,8 +31,6 @@ public abstract class BaseProviderR4Test extends BaseMdmR4Test { private IMdmSubmitSvc myMdmSubmitSvc; @Autowired private MdmSettings myMdmSettings; - @Autowired - private IPagingProvider myPagingProvider; private String defaultScript; @@ -46,7 +44,7 @@ public abstract class BaseProviderR4Test extends BaseMdmR4Test { @BeforeEach public void before() { - myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myPagingProvider); + myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc); defaultScript = myMdmSettings.getScriptText(); } @AfterEach 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 239780fd69c..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 @@ -28,7 +28,6 @@ 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.RestfulServerUtils; import ca.uhn.fhir.rest.server.TransactionLogMessages; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.provider.ProviderConstants; @@ -39,10 +38,6 @@ 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.Arrays; - -import static ca.uhn.fhir.rest.api.Constants.PARAM_COUNT; -import static ca.uhn.fhir.rest.api.Constants.PARAM_OFFSET; public abstract class BaseMdmProvider { 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 b1b4081fb3a..7ea63838fb5 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 @@ -76,7 +76,9 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { private final IMdmMatchFinderSvc myMdmMatchFinderSvc; private final IMdmExpungeSvc myMdmExpungeSvc; private final IMdmSubmitSvc myMdmSubmitSvc; - private final IPagingProvider myPagingProvider; + + public static final int DEFAULT_PAGE_SIZE = 20; + public static final int MAX_PAGE_SIZE = 100; /** * Constructor @@ -84,13 +86,12 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { * Note that this is not a spring bean. Any necessary injections should * happen in the constructor */ - public MdmProviderDstu3Plus(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc, IMdmMatchFinderSvc theMdmMatchFinderSvc, IMdmExpungeSvc theMdmExpungeSvc, IMdmSubmitSvc theMdmSubmitSvc, IPagingProvider thePagingProvider) { + public MdmProviderDstu3Plus(FhirContext theFhirContext, IMdmControllerSvc theMdmControllerSvc, IMdmMatchFinderSvc theMdmMatchFinderSvc, IMdmExpungeSvc theMdmExpungeSvc, IMdmSubmitSvc theMdmSubmitSvc) { super(theFhirContext); myMdmControllerSvc = theMdmControllerSvc; myMdmMatchFinderSvc = theMdmMatchFinderSvc; myMdmExpungeSvc = theMdmExpungeSvc; myMdmSubmitSvc = theMdmSubmitSvc; - myPagingProvider = thePagingProvider; } @Operation(name = ProviderConstants.EMPI_MATCH, typeName = "Patient") @@ -213,7 +214,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider.getDefaultPageSize(), myPagingProvider.getMaximumPageSize()); + 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, @@ -233,7 +234,7 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { UnsignedIntType theCount, ServletRequestDetails theRequestDetails) { - MdmPageRequest mdmPageRequest = new MdmPageRequest(theOffset, theCount, myPagingProvider.getDefaultPageSize(), myPagingProvider.getMaximumPageSize()); + 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); 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 27637899b8e..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 @@ -49,8 +49,6 @@ public class MdmProviderLoader { private IMdmExpungeSvc myMdmExpungeSvc; @Autowired private IMdmSubmitSvc myMdmSubmitSvc; - @Autowired - private IPagingProvider myPagingProvider; private BaseMdmProvider myMdmProvider; @@ -59,7 +57,7 @@ public class MdmProviderLoader { case DSTU3: case R4: myResourceProviderFactory.addSupplier(() -> { - myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc, myPagingProvider); + myMdmProvider = new MdmProviderDstu3Plus(myFhirContext, myMdmControllerSvc, myMdmMatchFinderSvc, myMdmExpungeSvc, myMdmSubmitSvc); return myMdmProvider; }); break; From 0893ba00395a677ae227474923480d72e0108864 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 30 Jun 2021 23:17:04 -0400 Subject: [PATCH 12/17] Fix up operation param types, fix bug in link builder --- .../mdm/api/paging/MdmPageLinkBuilder.java | 1 + .../fhir/mdm/api/paging/MdmPageRequest.java | 3 ++- .../mdm/provider/MdmProviderDstu3Plus.java | 21 ++++++++----------- 3 files changed, 12 insertions(+), 13 deletions(-) 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 index aac24db86d9..6d63aa0df48 100644 --- 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 @@ -49,6 +49,7 @@ public final class MdmPageLinkBuilder { 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/MdmPageRequest.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/api/paging/MdmPageRequest.java index 6e401a58b0e..91eb5db3f3d 100644 --- 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 @@ -4,6 +4,7 @@ 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; @@ -24,7 +25,7 @@ public class MdmPageRequest { private final int myOffset; private final int myCount; - public MdmPageRequest(@Nullable UnsignedIntType theOffset, @Nullable UnsignedIntType theCount, int theDefaultPageSize, int theMaximumPageSize) { + 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); 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 7ea63838fb5..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 @@ -31,20 +31,18 @@ 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.IPagingProvider; -import ca.uhn.fhir.rest.server.IRestfulServerDefaults; 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.BundleBuilder; import ca.uhn.fhir.util.ParametersUtil; 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.IBase; import org.hl7.fhir.instance.model.api.IBaseBackboneElement; @@ -207,11 +205,11 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { IPrimitiveType theLinkSource, @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) - UnsignedIntType theOffset, + @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) - UnsignedIntType theCount, + @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); @@ -223,15 +221,14 @@ public class MdmProviderDstu3Plus extends BaseMdmProvider { return parametersFromMdmLinks(mdmLinkJson, true, theRequestDetails, mdmPageRequest); } - @Operation(name = ProviderConstants.MDM_DUPLICATE_GOLDEN_RESOURCES, idempotent = true) 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) - UnsignedIntType theOffset, + @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) - UnsignedIntType theCount, + @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); From b963520c9860e980cf3e28198a78b6b8f1c1d693 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 1 Jul 2021 09:33:19 -0400 Subject: [PATCH 13/17] Fix bug in link builder --- .../java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilder.java | 2 ++ 1 file changed, 2 insertions(+) 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 index 6d63aa0df48..86fb039d5c2 100644 --- 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 @@ -47,6 +47,8 @@ public final class MdmPageLinkBuilder { builder.append(theBaseUrl); if (!theBaseUrl.contains("?")) { builder.append("?"); + } else { + builder.append("&"); } builder.append(PARAM_OFFSET).append("=").append(theOffset); builder.append("&"); From 86519a892abc50db86338cab1f5835e99e2d2581 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 1 Jul 2021 09:43:53 -0400 Subject: [PATCH 14/17] Add tests for link builder --- .../api/paging/MdmPageLinkBuilderTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/api/paging/MdmPageLinkBuilderTest.java 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))); + } +} From de84e3f98d7cfce0c537dcf663bbcd460a26567b Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 1 Jul 2021 17:02:44 -0400 Subject: [PATCH 15/17] add test for restfulserverutil link generation --- .../fhir/rest/server/RestfulServerUtils.java | 2 +- .../rest/server/RestfulServerUtilsTest.java | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) 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 a213fb5f76e..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 @@ -272,7 +272,7 @@ public class RestfulServerUtils { boolean first = true; Map parameters = theRequest.getParameters(); for (String nextParamName : new TreeSet<>(parameters.keySet())) { - if (excludedParameterNames != null && !excludedParameterNames.contains(nextParamName)) { + if (excludedParameterNames == null || !excludedParameterNames.contains(nextParamName)) { for (String nextParamValue : parameters.get(nextParamName)) { if (first) { b.append('?'); 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"))); + + } } From 0a4a50f0a8f6ba787ada5e3964bf3d248885aeda Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 1 Jul 2021 17:05:14 -0400 Subject: [PATCH 16/17] update docs --- .../hapi/fhir/docs/server_jpa_mdm/mdm_operations.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 3b191a26e6d..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 @@ -26,10 +26,10 @@ With request body: "resourceType": "Parameters", "parameter": [ { "name": "_offset", - "valueInteger": 0 + "valueInteger": 10 }, { "name": "_count", - "valueInteger": 2 + "valueInteger": 10 } ] } ``` @@ -41,13 +41,13 @@ The returning response will contain links to the current, next, and previous pag "resourceType": "Parameters", "parameter": [ { "name": "prev", - "valueUri": "http://example.com/$mdm-query-links?_offset=8_count=2" + "valueUri": "http://example.com/$mdm-query-links?_offset=0&_count=10" }, { "name": "self", - "valueUri": "http://example.com/$mdm-query-links?_offset=10_count=2" + "valueUri": "http://example.com/$mdm-query-links?_offset=10&_count=10" }, { "name": "next", - "valueUri": "http://example.com/$mdm-query-links?_offset=12_count=2" + "valueUri": "http://example.com/$mdm-query-links?_offset=20&_count=10" },...(truncated) ``` From cfcc939caa4397c18217a1956ce1692b7b69d57b Mon Sep 17 00:00:00 2001 From: Tadgh Date: Thu, 1 Jul 2021 18:28:29 -0400 Subject: [PATCH 17/17] Fix broken tests, add license --- .../provider/MdmProviderQueryLinkR4Test.java | 17 ++++++++-------- .../mdm/api/paging/MdmPageLinkBuilder.java | 20 +++++++++++++++++++ .../fhir/mdm/api/paging/MdmPageLinkTuple.java | 20 +++++++++++++++++++ .../fhir/mdm/api/paging/MdmPageRequest.java | 20 +++++++++++++++++++ .../server/interceptor/auth/RuleTarget.java | 20 +++++++++++++++++++ 5 files changed, 89 insertions(+), 8 deletions(-) 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 008c8e7c5f2..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 @@ -70,7 +70,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { public void testQueryLinkOneMatch() { 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); @@ -172,7 +172,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { } @Test - public void testQueryLinkThreeMatches() { + public void testQueryLnkThreeMatches() { // Add a third patient Patient patient = createPatientAndUpdateLinks(buildJanePatient()); IdType patientId = patient.getIdElement().toVersionless(); @@ -181,9 +181,9 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { 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"); } @@ -191,7 +191,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { public void testQueryPossibleDuplicates() { 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); @@ -201,7 +201,8 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { public void testNotDuplicate() { { Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); - List list = result.getParameter(); + List list = getParametersByName(result, "link"); + assertThat(list, hasSize(1)); } { @@ -212,7 +213,7 @@ public class MdmProviderQueryLinkR4Test extends BaseLinkR4Test { } Parameters result = (Parameters) myMdmProvider.getDuplicateGoldenResources(new UnsignedIntType(0), new UnsignedIntType(10),myRequestDetails); - List list = result.getParameter(); + List list = getParametersByName(result, "link"); assertThat(list, hasSize(0)); } 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 index 86fb039d5c2..32629bc3604 100644 --- 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 @@ -1,5 +1,25 @@ 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; 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 index c881dd518c4..fd8d30859ee 100644 --- 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 @@ -1,5 +1,25 @@ 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; /** 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 index 91eb5db3f3d..a91f189e0e6 100644 --- 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 @@ -1,5 +1,25 @@ 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; 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;