Skip to content

Commit

Permalink
Add support for pagination of list entries
Browse files Browse the repository at this point in the history
fixes #29
  • Loading branch information
lincmba committed Feb 1, 2024
1 parent 4e6da94 commit 9b0e0ef
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public Bundle createEmptyBundle(String requestURL) {
Bundle responseBundle = new Bundle();
responseBundle.setId(UUID.randomUUID().toString());
Bundle.BundleLinkComponent linkComponent = new Bundle.BundleLinkComponent();
linkComponent.setRelation(Bundle.LINK_PREV);
linkComponent.setRelation(Bundle.LINK_SELF);
linkComponent.setRelation(Bundle.LINK_NEXT);
linkComponent.setUrl(requestURL);
responseBundle.setLink(Collections.singletonList(linkComponent));
responseBundle.setType(Bundle.BundleType.SEARCHSET);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public String postProcess(RequestDetailsReader request, HttpResponse response)

switch (gatewayMode) {
case SyncAccessDecisionConstants.LIST_ENTRIES:
resultContentBundle = postProcessModeListEntries(responseResource);
resultContentBundle = postProcessModeListEntries(responseResource, request);
break;

default:
Expand Down Expand Up @@ -216,11 +216,29 @@ private static OperationOutcome createOperationOutcome(String exception) {

@NotNull
private static Bundle processListEntriesGatewayModeByListResource(
ListResource responseListResource) {
ListResource responseListResource, RequestDetailsReader request) {
Bundle requestBundle = new Bundle();
requestBundle.setType(Bundle.BundleType.BATCH);

for (ListResource.ListEntryComponent listEntryComponent : responseListResource.getEntry()) {
String[] pageSize = request.getParameters().get("_count");
String[] pageNumber = request.getParameters().get("_page");

int count =
pageSize != null && pageSize.length > 0
? Integer.parseInt(pageSize[0])
: 20; // Default page size to 20 if not provided
int page =
pageNumber != null && pageNumber.length > 0
? Integer.parseInt(pageNumber[0])
: 1; // Default page number to 1 if not provided

int start = Math.max(0, (page - 1)) * count;
int end = start + count;

List<ListResource.ListEntryComponent> entries = responseListResource.getEntry();

for (int i = start; i < Math.min(end, entries.size()); i++) {
ListResource.ListEntryComponent listEntryComponent = entries.get(i);
requestBundle.addEntry(
createBundleEntryComponent(
Bundle.HTTPVerb.GET,
Expand Down Expand Up @@ -271,18 +289,20 @@ static Bundle.BundleEntryComponent createBundleEntryComponent(
* Generates a Bundle result from making a batch search request with the contained entries in
* the List as parameters
*
* @param responseResource FHIR Resource result returned byt the HTTPResponse
* @param responseResource FHIR Resource result returned by the HTTPResponse
* @return String content of the result Bundle
*/
private Bundle postProcessModeListEntries(IBaseResource responseResource) {
private Bundle postProcessModeListEntries(
IBaseResource responseResource, RequestDetailsReader request) {

Bundle requestBundle = null;

if (responseResource instanceof ListResource
&& ((ListResource) responseResource).hasEntry()) {

requestBundle =
processListEntriesGatewayModeByListResource((ListResource) responseResource);
processListEntriesGatewayModeByListResource(
(ListResource) responseResource, request);

} else if (responseResource instanceof Bundle) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,80 @@ public void testPostProcessWithListModeHeaderSearchByTagShouldFetchListEntriesBu
resultContent);
}

@Test
public void testPostProcessWithListModePaginateEntriesBundle() throws IOException {
locationIds.add("Location-1");
testInstance = Mockito.spy(createSyncAccessDecisionTestInstance(Constants.LOCATION));

FhirContext fhirR4Context = mock(FhirContext.class);
IGenericClient iGenericClient = mock(IGenericClient.class);
ITransaction iTransaction = mock(ITransaction.class);
ITransactionTyped<Bundle> iClientExecutable = mock(ITransactionTyped.class);
testInstance.setFhirR4Client(iGenericClient);
testInstance.setFhirR4Context(fhirR4Context);

Mockito.when(iGenericClient.transaction()).thenReturn(iTransaction);
Mockito.when(iTransaction.withBundle(any(Bundle.class))).thenReturn(iClientExecutable);

Bundle resultBundle = new Bundle();
resultBundle.setType(Bundle.BundleType.BATCHRESPONSE);
resultBundle.setId("bundle-result-id");

Mockito.when(iClientExecutable.execute()).thenReturn(resultBundle);

ArgumentCaptor<Bundle> bundleArgumentCaptor = ArgumentCaptor.forClass(Bundle.class);

testInstance.setFhirR4Context(fhirR4Context);

RequestDetailsReader requestDetailsSpy = Mockito.mock(RequestDetailsReader.class);

Mockito.when(
requestDetailsSpy.getHeader(
SyncAccessDecision.SyncAccessDecisionConstants.FHIR_GATEWAY_MODE))
.thenReturn(SyncAccessDecision.SyncAccessDecisionConstants.LIST_ENTRIES);

Map<String, String[]> params = new HashMap<>();
params.put("_count", new String[] {"1"});
params.put("_page", new String[] {"1"});

Mockito.when(requestDetailsSpy.getParameters()).thenReturn(params);

URL listUrl = Resources.getResource("test_list_resource.json");
String testListJson = Resources.toString(listUrl, StandardCharsets.UTF_8);

HttpResponse fhirResponseMock =
Mockito.mock(HttpResponse.class, Answers.RETURNS_DEEP_STUBS);

TestUtil.setUpFhirResponseMock(fhirResponseMock, testListJson);

String resultContent = testInstance.postProcess(requestDetailsSpy, fhirResponseMock);

Mockito.verify(iTransaction).withBundle(bundleArgumentCaptor.capture());
Bundle requestBundle = bundleArgumentCaptor.getValue();

// Verify modified request to the server
Assert.assertNotNull(requestBundle);
Assert.assertEquals(Bundle.BundleType.BATCH, requestBundle.getType());
List<Bundle.BundleEntryComponent> requestBundleEntries = requestBundle.getEntry();

// Only one returned one _page = 1 and _count = 1
Assert.assertEquals(1, requestBundleEntries.size());

Assert.assertEquals(
Bundle.HTTPVerb.GET, requestBundleEntries.get(0).getRequest().getMethod());
Assert.assertEquals(
"Group/proxy-list-entry-id-1", requestBundleEntries.get(0).getRequest().getUrl());

Assert.assertEquals(
Bundle.HTTPVerb.GET, requestBundleEntries.get(0).getRequest().getMethod());

// Verify returned result content from the server request
Assert.assertNotNull(resultContent);
Assert.assertEquals(
"{\"resourceType\":\"Bundle\",\"id\":\"bundle-result-id\",\"type\":\"batch-response\"}",
resultContent);
}

@After
public void cleanUp() {
locationIds.clear();
Expand Down

0 comments on commit 9b0e0ef

Please sign in to comment.