Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
This commit is contained in:
TipzCM 2022-09-26 09:43:11 -04:00 committed by GitHub
parent 917cf8d062
commit 389bdce372
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 17 deletions

3
.gitignore vendored
View File

@ -162,3 +162,6 @@ Snap.*
# VS Code # VS Code
.vscode .vscode
/database/

View File

@ -0,0 +1,6 @@
---
type: fix
issue: 4067
jira: SMILE-5186
title: "Fixed a bug where /Patient/$export would fail if _type=Patient parameter
was not included."

View File

@ -12,6 +12,7 @@ import ca.uhn.fhir.jpa.bulk.export.model.BulkExportJobStatusEnum;
import ca.uhn.fhir.jpa.bulk.export.model.BulkExportResponseJson; import ca.uhn.fhir.jpa.bulk.export.model.BulkExportResponseJson;
import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider; import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.apache.ResourceEntity; import ca.uhn.fhir.rest.client.apache.ResourceEntity;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
@ -43,6 +44,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
@ -641,6 +643,32 @@ public class BulkDataExportProviderTest {
assertThat(bp.getFilters(), containsInAnyOrder("Patient?gender=male", "Patient?gender=female")); assertThat(bp.getFilters(), containsInAnyOrder("Patient?gender=male", "Patient?gender=female"));
} }
@Test
public void testInitiateBulkExportOnPatient_noTypeParam_addsTypeBeforeBulkExport() throws IOException {
// when
when(myJobRunner.startNewJob(any()))
.thenReturn(createJobStartResponse());
Parameters input = new Parameters();
input.addParameter(JpaConstants.PARAM_EXPORT_OUTPUT_FORMAT, new StringType(Constants.CT_FHIR_NDJSON));
// call
HttpPost post = new HttpPost("http://localhost:" + myPort + "/Patient/" + JpaConstants.OPERATION_EXPORT);
post.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC);
post.setEntity(new ResourceEntity(myCtx, input));
ourLog.info("Request: {}", post);
try (CloseableHttpResponse response = myClient.execute(post)) {
ourLog.info("Response: {}", response.toString());
assertEquals(202, response.getStatusLine().getStatusCode());
assertEquals("Accepted", response.getStatusLine().getReasonPhrase());
assertEquals("http://localhost:" + myPort + "/$export-poll-status?_jobId=" + A_JOB_ID, response.getFirstHeader(Constants.HEADER_CONTENT_LOCATION).getValue());
}
BulkExportParameters bp = verifyJobStart();
assertEquals(Constants.CT_FHIR_NDJSON, bp.getOutputFormat());
assertThat(bp.getResourceTypes(), containsInAnyOrder("Patient"));
}
@Test @Test
public void testInitiatePatientExportRequest() throws IOException { public void testInitiatePatientExportRequest() throws IOException {
// when // when

View File

@ -268,7 +268,6 @@ public class BulkDataExportTest extends BaseResourceProviderR4Test {
verifyBulkExportResults(options, List.of("\"P1\"", "\"" + obsId + "\"", "\"" + encId + "\"", "\"P2\"", "\"" + obsId2 + "\"", "\"" + encId2 + "\""), List.of("\"P3\"", "\"" + obsId3 + "\"", "\"" + encId3 + "\"")); verifyBulkExportResults(options, List.of("\"P1\"", "\"" + obsId + "\"", "\"" + encId + "\"", "\"P2\"", "\"" + obsId2 + "\"", "\"" + encId2 + "\""), List.of("\"P3\"", "\"" + obsId3 + "\"", "\"" + encId3 + "\""));
} }
private void verifyBulkExportResults(BulkDataExportOptions theOptions, List<String> theContainedList, List<String> theExcludedList) { private void verifyBulkExportResults(BulkDataExportOptions theOptions, List<String> theContainedList, List<String> theExcludedList) {
Batch2JobStartResponse startResponse = myJobRunner.startNewJob(BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions)); Batch2JobStartResponse startResponse = myJobRunner.startNewJob(BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions));

View File

@ -100,12 +100,13 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
} }
} }
} }
@Nested @Nested
public class SystemBulkExportTests { public class SystemBulkExportTests {
@Test @Test
public void testBinariesAreStreamedWithRespectToAcceptHeader() throws IOException { public void testBinariesAreStreamedWithRespectToAcceptHeader() throws IOException {
int patientCount = 5; int patientCount = 5;
for (int i=0; i<patientCount; i++) { for (int i = 0; i < patientCount; i++) {
Patient patient = new Patient(); Patient patient = new Patient();
patient.setId("pat-" + i); patient.setId("pat-" + i);
myPatientDao.update(patient); myPatientDao.update(patient);
@ -161,7 +162,7 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
assertThat(headers[0].getValue(), containsString(Constants.CT_FHIR_JSON)); assertThat(headers[0].getValue(), containsString(Constants.CT_FHIR_JSON));
assertThat(response, is(not(containsString("\n")))); assertThat(response, is(not(containsString("\n"))));
Binary binary= myFhirContext.newJsonParser().parseResource(Binary.class, response); Binary binary = myFhirContext.newJsonParser().parseResource(Binary.class, response);
assertThat(binary.getIdElement().getValue(), is(equalTo(patientBinaryId))); assertThat(binary.getIdElement().getValue(), is(equalTo(patientBinaryId)));
} }
} }
@ -197,7 +198,6 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
@Test @Test
public void testPatientExportIgnoresResourcesNotInPatientCompartment() { public void testPatientExportIgnoresResourcesNotInPatientCompartment() {
Patient patient = new Patient(); Patient patient = new Patient();
patient.setId("pat-1"); patient.setId("pat-1");
myPatientDao.update(patient); myPatientDao.update(patient);
@ -220,11 +220,9 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
Map<String, String> typeToContents = convertJobResultsToStringContents(bulkExportJobResults); Map<String, String> typeToContents = convertJobResultsToStringContents(bulkExportJobResults);
assertThat(typeToContents.get("Observation"), containsString("obs-included")); assertThat(typeToContents.get("Observation"), containsString("obs-included"));
assertThat(typeToContents.get("Observation"), not(containsString("obs-excluded"))); assertThat(typeToContents.get("Observation"), not(containsString("obs-excluded")));
} }
} }
@Nested @Nested
public class GroupBulkExportTests { public class GroupBulkExportTests {
@Test @Test
@ -257,8 +255,6 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
assertThat(firstMap.get("Group"), hasSize(1)); assertThat(firstMap.get("Group"), hasSize(1));
assertThat(firstMap.get("Patient"), hasSize(600)); assertThat(firstMap.get("Patient"), hasSize(600));
assertThat(firstMap.get("Observation"), hasSize(600)); assertThat(firstMap.get("Observation"), hasSize(600));
} }
@Test @Test
@ -293,8 +289,6 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
Map<String, List<IBaseResource>> firstMap = convertJobResultsToResources(bulkExportJobResults); Map<String, List<IBaseResource>> firstMap = convertJobResultsToResources(bulkExportJobResults);
assertThat(firstMap.get("Patient"), hasSize(1)); assertThat(firstMap.get("Patient"), hasSize(1));
assertThat(firstMap.get("Group"), hasSize(1)); assertThat(firstMap.get("Group"), hasSize(1));
} }
@Test @Test
@ -703,6 +697,7 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
String contents = new String(binary.getContent(), Constants.CHARSET_UTF8); String contents = new String(binary.getContent(), Constants.CHARSET_UTF8);
return contents; return contents;
} }
BulkExportJobResults startGroupBulkExportJobAndAwaitCompletion(HashSet<String> theResourceTypes, HashSet<String> theFilters, String theGroupId) { BulkExportJobResults startGroupBulkExportJobAndAwaitCompletion(HashSet<String> theResourceTypes, HashSet<String> theFilters, String theGroupId) {
return startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle.GROUP, theResourceTypes, theFilters, theGroupId); return startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle.GROUP, theResourceTypes, theFilters, theGroupId);
} }
@ -710,8 +705,8 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
BulkExportJobResults startSystemBulkExportJobAndAwaitCompletion(HashSet<String> theResourceTypes, HashSet<String> theFilters) { BulkExportJobResults startSystemBulkExportJobAndAwaitCompletion(HashSet<String> theResourceTypes, HashSet<String> theFilters) {
return startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle.SYSTEM, theResourceTypes, theFilters, null); return startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle.SYSTEM, theResourceTypes, theFilters, null);
} }
BulkExportJobResults startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle theExportStyle, HashSet<String> theResourceTypes, HashSet<String> theFilters, String theGroupOrPatientId) {
BulkExportJobResults startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle theExportStyle, HashSet<String> theResourceTypes, HashSet<String> theFilters, String theGroupOrPatientId) {
BulkDataExportOptions options = new BulkDataExportOptions(); BulkDataExportOptions options = new BulkDataExportOptions();
options.setResourceTypes(theResourceTypes); options.setResourceTypes(theResourceTypes);
options.setFilters(theFilters); options.setFilters(theFilters);
@ -736,7 +731,6 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
String report = myJobRunner.getJobInfo(startResponse.getJobId()).getReport(); String report = myJobRunner.getJobInfo(startResponse.getJobId()).getReport();
BulkExportJobResults results = JsonUtil.deserialize(report, BulkExportJobResults.class); BulkExportJobResults results = JsonUtil.deserialize(report, BulkExportJobResults.class);
return results; return results;
} }
private void verifyBulkExportResults(String theGroupId, HashSet<String> theFilters, List<String> theContainedList, List<String> theExcludedList) { private void verifyBulkExportResults(String theGroupId, HashSet<String> theFilters, List<String> theContainedList, List<String> theExcludedList) {
@ -781,6 +775,4 @@ public class BulkExportUseCaseTest extends BaseResourceProviderR4Test {
private BulkExportJobResults startPatientBulkExportJobAndAwaitResults(HashSet<String> theTypes, HashSet<String> theFilters, String thePatientId) { private BulkExportJobResults startPatientBulkExportJobAndAwaitResults(HashSet<String> theTypes, HashSet<String> theFilters, String thePatientId) {
return startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle.PATIENT, theTypes, theFilters, thePatientId); return startBulkExportJobAndAwaitCompletion(BulkDataExportOptions.ExportStyle.PATIENT, theTypes, theFilters, thePatientId);
} }
} }

View File

@ -35,6 +35,7 @@ import ca.uhn.fhir.jpa.bulk.export.model.BulkExportJobStatusEnum;
import ca.uhn.fhir.jpa.bulk.export.model.BulkExportResponseJson; import ca.uhn.fhir.jpa.bulk.export.model.BulkExportResponseJson;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.util.BulkExportUtils; import ca.uhn.fhir.jpa.util.BulkExportUtils;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.OperationParam;
@ -124,7 +125,6 @@ public class BulkDataExportProvider {
// get cache boolean // get cache boolean
boolean useCache = shouldUseCache(theRequestDetails); boolean useCache = shouldUseCache(theRequestDetails);
BulkExportParameters parameters = BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions); BulkExportParameters parameters = BulkExportUtils.createBulkExportJobParametersFromExportOptions(theOptions);
parameters.setUseExistingJobsFirst(useCache); parameters.setUseExistingJobsFirst(useCache);
@ -391,7 +391,12 @@ public class BulkDataExportProvider {
} }
private BulkDataExportOptions buildPatientBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, List<IPrimitiveType<String>> theTypeFilter, List<IPrimitiveType<String>> thePatientIds) { private BulkDataExportOptions buildPatientBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, List<IPrimitiveType<String>> theTypeFilter, List<IPrimitiveType<String>> thePatientIds) {
BulkDataExportOptions bulkDataExportOptions = buildBulkDataExportOptions(theOutputFormat, theType, theSince, theTypeFilter, BulkDataExportOptions.ExportStyle.PATIENT); IPrimitiveType<String> type = theType;
if (type == null) {
// Type is optional, but the job requires it
type = new StringDt("Patient");
}
BulkDataExportOptions bulkDataExportOptions = buildBulkDataExportOptions(theOutputFormat, type, theSince, theTypeFilter, BulkDataExportOptions.ExportStyle.PATIENT);
if (thePatientIds != null) { if (thePatientIds != null) {
bulkDataExportOptions.setPatientIds(thePatientIds.stream().map((pid) -> new IdType(pid.getValueAsString())).collect(Collectors.toSet())); bulkDataExportOptions.setPatientIds(thePatientIds.stream().map((pid) -> new IdType(pid.getValueAsString())).collect(Collectors.toSet()));
} }