diff --git a/src/main/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadController.java b/src/main/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadController.java index 9d07bf79c..85f3d3311 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadController.java @@ -16,10 +16,13 @@ */ package org.breedinginsight.api.v1.controller.geno; +import io.micronaut.http.HttpHeaders; import io.micronaut.http.HttpResponse; +import io.micronaut.http.HttpStatus; import io.micronaut.http.MediaType; import io.micronaut.http.annotation.*; import io.micronaut.http.multipart.CompletedFileUpload; +import io.micronaut.http.server.types.files.StreamedFile; import lombok.extern.slf4j.Slf4j; import org.brapi.client.v2.model.exceptions.ApiException; import org.breedinginsight.api.auth.*; @@ -30,6 +33,7 @@ import org.breedinginsight.api.model.v1.validators.QueryValid; import org.breedinginsight.api.v1.controller.metadata.AddMetadata; import org.breedinginsight.brapps.importer.model.response.ImportResponse; +import org.breedinginsight.model.DownloadFile; import org.breedinginsight.model.GenotypeImportDetails; import org.breedinginsight.model.Program; import org.breedinginsight.services.ProgramService; @@ -41,6 +45,7 @@ import javax.inject.Inject; import javax.validation.Valid; +import java.io.IOException; import java.util.Optional; import java.util.UUID; @@ -83,6 +88,30 @@ public HttpResponse>> getGenotypeIm ); } + @Get("programs/{programId}/geno/imports/{genotypeImportId}/download") + @ProgramSecured(roleGroups = ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES) + @Produces(value = {"application/octet-stream"}) + public HttpResponse downloadGenotypeImport(@PathVariable UUID programId, @PathVariable UUID genotypeImportId) { + Optional program = programService.getById(programId); + if (program.isEmpty()) { + log.info("programId not found: {}", programId.toString()); + return HttpResponse.notFound(); + } + + try { + Optional downloadFile = genoService.downloadGenotypeImport(programId, genotypeImportId); + if (downloadFile.isEmpty()) { + return HttpResponse.notFound(); + } + + return HttpResponse.ok(downloadFile.get().getStreamedFile()) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + downloadFile.get().getFileName()); + } catch (IOException e) { + log.error("Error downloading genotype import", e); + return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, "Error downloading genotype import"); + } + } + @Post("programs/{programId}/submissions/{submissionId}/geno/import") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) diff --git a/src/main/java/org/breedinginsight/daos/GenotypeImportDAO.java b/src/main/java/org/breedinginsight/daos/GenotypeImportDAO.java index c34f7baae..8bf4dd5ac 100644 --- a/src/main/java/org/breedinginsight/daos/GenotypeImportDAO.java +++ b/src/main/java/org/breedinginsight/daos/GenotypeImportDAO.java @@ -21,6 +21,7 @@ import org.breedinginsight.dao.db.tables.daos.GenotypeImportDao; import org.breedinginsight.dao.db.tables.pojos.GenotypeImportEntity; import org.breedinginsight.model.GenotypeImportDetails; +import org.breedinginsight.model.GenotypeImportDownloadDetails; import org.jooq.Configuration; import org.jooq.DSLContext; @@ -28,6 +29,7 @@ import javax.inject.Singleton; import java.time.OffsetDateTime; import java.util.List; +import java.util.Optional; import java.util.UUID; import static org.breedinginsight.dao.db.Tables.*; @@ -62,6 +64,7 @@ public List getGenotypeImportsByProgramId(UUID programId) BiUserTable genotypingImportByUser = BI_USER.as("genotypingImportByUser"); return dsl.select( + GENOTYPE_IMPORT.ID, SAMPLE_SUBMISSION.ID, SAMPLE_SUBMISSION.NAME, sampleSubmissionCreatedByUser.NAME, @@ -82,4 +85,19 @@ public List getGenotypeImportsByProgramId(UUID programId) .parseSqlRecord(record, sampleSubmissionCreatedByUser, genotypingImportByUser)); } + public Optional getDownloadableGenotypeImportById(UUID programId, UUID genotypeImportId) { + return dsl.select( + GENOTYPE_IMPORT.SAMPLE_SUBMISSION_ID, + GENOTYPE_IMPORT.IMPORTER_IMPORT_ID, + IMPORTER_IMPORT.UPLOAD_FILE_NAME) + .from(GENOTYPE_IMPORT) + .join(SAMPLE_SUBMISSION).on(GENOTYPE_IMPORT.SAMPLE_SUBMISSION_ID.eq(SAMPLE_SUBMISSION.ID)) + .join(IMPORTER_IMPORT).on(GENOTYPE_IMPORT.IMPORTER_IMPORT_ID.eq(IMPORTER_IMPORT.ID)) + .join(IMPORTER_PROGRESS).on(IMPORTER_IMPORT.IMPORTER_PROGRESS_ID.eq(IMPORTER_PROGRESS.ID)) + .where(GENOTYPE_IMPORT.ID.eq(genotypeImportId)) + .and(SAMPLE_SUBMISSION.PROGRAM_ID.eq(programId)) + .and(IMPORTER_IMPORT.PROGRAM_ID.eq(programId)) + .and(IMPORTER_PROGRESS.STATUSCODE.eq((short) HttpStatus.OK.getCode())) + .fetchOptional(GenotypeImportDownloadDetails::parseSqlRecord); + } } \ No newline at end of file diff --git a/src/main/java/org/breedinginsight/model/GenotypeImportDetails.java b/src/main/java/org/breedinginsight/model/GenotypeImportDetails.java index 9082750ed..f9ad900f3 100644 --- a/src/main/java/org/breedinginsight/model/GenotypeImportDetails.java +++ b/src/main/java/org/breedinginsight/model/GenotypeImportDetails.java @@ -33,6 +33,7 @@ import static org.breedinginsight.dao.db.Tables.IMPORTER_IMPORT; import static org.breedinginsight.dao.db.Tables.SAMPLE_SUBMISSION; +import static org.breedinginsight.dao.db.Tables.GENOTYPE_IMPORT; @Getter @Setter @@ -43,6 +44,7 @@ @Introspected @Jacksonized public class GenotypeImportDetails { + private UUID genotypeImportId; private UUID sampleSubmissionId; private String projectNameForSampleSubmission; private String sampleSubmissionCreatedBy; @@ -54,6 +56,7 @@ public static GenotypeImportDetails parseSqlRecord(Record record, BiUserTable sampleSubmissionCreatedByUser, BiUserTable genotypingImportByUser) { return GenotypeImportDetails.builder() + .genotypeImportId(record.get(GENOTYPE_IMPORT.ID)) .sampleSubmissionId(record.get(SAMPLE_SUBMISSION.ID)) .projectNameForSampleSubmission(record.get(SAMPLE_SUBMISSION.NAME)) .sampleSubmissionCreatedBy(record.get(sampleSubmissionCreatedByUser.NAME)) diff --git a/src/main/java/org/breedinginsight/model/GenotypeImportDownloadDetails.java b/src/main/java/org/breedinginsight/model/GenotypeImportDownloadDetails.java new file mode 100644 index 000000000..7fe874be0 --- /dev/null +++ b/src/main/java/org/breedinginsight/model/GenotypeImportDownloadDetails.java @@ -0,0 +1,54 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * 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. + */ +package org.breedinginsight.model; + +import io.micronaut.core.annotation.Introspected; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; +import lombok.extern.jackson.Jacksonized; +import org.jooq.Record; + +import java.util.UUID; + +import static org.breedinginsight.dao.db.Tables.GENOTYPE_IMPORT; +import static org.breedinginsight.dao.db.Tables.IMPORTER_IMPORT; + +@Getter +@Setter +@Accessors(chain = true) +@ToString +@SuperBuilder +@NoArgsConstructor +@Introspected +@Jacksonized +public class GenotypeImportDownloadDetails { + private UUID sampleSubmissionId; + private UUID importerImportId; + private String genotypeFileName; + + public static GenotypeImportDownloadDetails parseSqlRecord(Record record) { + return GenotypeImportDownloadDetails.builder() + .sampleSubmissionId(record.get(GENOTYPE_IMPORT.SAMPLE_SUBMISSION_ID)) + .importerImportId(record.get(GENOTYPE_IMPORT.IMPORTER_IMPORT_ID)) + .genotypeFileName(record.get(IMPORTER_IMPORT.UPLOAD_FILE_NAME)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/org/breedinginsight/services/geno/GenotypeService.java b/src/main/java/org/breedinginsight/services/geno/GenotypeService.java index 3ed088137..f54e1be93 100644 --- a/src/main/java/org/breedinginsight/services/geno/GenotypeService.java +++ b/src/main/java/org/breedinginsight/services/geno/GenotypeService.java @@ -19,12 +19,15 @@ import io.micronaut.http.multipart.CompletedFileUpload; import org.brapi.client.v2.model.exceptions.ApiException; import org.breedinginsight.brapps.importer.model.response.ImportResponse; +import org.breedinginsight.model.DownloadFile; import org.breedinginsight.model.GermplasmGenotype; import org.breedinginsight.services.exceptions.AuthorizationException; import org.breedinginsight.services.exceptions.DoesNotExistException; import org.breedinginsight.model.GenotypeImportDetails; +import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.UUID; public interface GenotypeService { @@ -33,4 +36,6 @@ public interface GenotypeService { GermplasmGenotype retrieveGenotypeData(UUID programId, UUID germplasmId) throws DoesNotExistException, AuthorizationException, ApiException; List getGenotypeImports(UUID programId); + + Optional downloadGenotypeImport(UUID programId, UUID genotypeImportId)throws IOException; } diff --git a/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java b/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java index 562ec57bc..534043dc1 100644 --- a/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java +++ b/src/main/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImpl.java @@ -8,6 +8,7 @@ import io.micronaut.http.HttpStatus; import io.micronaut.http.multipart.CompletedFileUpload; import io.micronaut.http.server.exceptions.InternalServerException; +import io.micronaut.http.server.types.files.StreamedFile; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.apache.commons.lang3.tuple.Pair; @@ -46,10 +47,7 @@ import org.breedinginsight.daos.ProgramDAO; import org.breedinginsight.daos.SampleSubmissionDAO; import org.breedinginsight.daos.UserDAO; -import org.breedinginsight.model.GenotypeImportDetails; -import org.breedinginsight.model.GermplasmGenotype; -import org.breedinginsight.model.Program; -import org.breedinginsight.model.User; +import org.breedinginsight.model.*; import org.breedinginsight.services.brapi.BrAPIEndpointProvider; import org.breedinginsight.services.exceptions.AuthorizationException; import org.breedinginsight.services.exceptions.DoesNotExistException; @@ -66,6 +64,7 @@ import javax.inject.Singleton; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.util.*; @@ -276,6 +275,52 @@ public List getGenotypeImports(UUID programId) { return genotypeImportDAO.getGenotypeImportsByProgramId(programId); } + @Override + public Optional downloadGenotypeImport(UUID programId, UUID genotypeImportId) { + Optional genotypeImportDownloadDetails = genotypeImportDAO + .getDownloadableGenotypeImportById(programId, genotypeImportId); + + if (genotypeImportDownloadDetails.isEmpty()) { + return Optional.empty(); + } + + UUID submissionId = genotypeImportDownloadDetails.get().getSampleSubmissionId(); + UUID importerImportId = genotypeImportDownloadDetails.get().getImporterImportId(); + String originalFileName = genotypeImportDownloadDetails.get().getGenotypeFileName(); + + Optional storedKey = findStoredGenotypeImportKey(programId, submissionId, importerImportId); + if (storedKey.isEmpty()) { + return Optional.empty(); + } + + InputStream inputStream = s3Client.getObject(GetObjectRequest.builder() + .bucket(storageService.getDefaultBucketName()) + .key(storedKey.get()) + .build()); + + return Optional.of(new DownloadFile( + originalFileName, + new StreamedFile( + inputStream, + new io.micronaut.http.MediaType(io.micronaut.http.MediaType.APPLICATION_OCTET_STREAM) + ) + )); + } + + private Optional findStoredGenotypeImportKey(UUID programId, UUID submissionId, UUID importerImportId) { + String prefix = programId + "/" + submissionId + "/" + importerImportId; + + ListObjectsV2Response response = s3Client.listObjectsV2(ListObjectsV2Request.builder() + .bucket(storageService.getDefaultBucketName()) + .prefix(prefix) + .maxKeys(1) + .build()); + + return response.contents().stream() + .map(S3Object::key) + .findFirst(); + } + private boolean validateSamples(Program program, UUID submissionId, byte[] fileContents, ImportUpload upload) throws DoesNotExistException, ApiException { log.debug("Validating samples in submitted VCF file for submission: " + submissionId); diff --git a/src/test/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadControllerIntegrationTest.java b/src/test/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadControllerIntegrationTest.java index a25118a57..eebb2191e 100644 --- a/src/test/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadControllerIntegrationTest.java +++ b/src/test/java/org/breedinginsight/api/v1/controller/geno/GenotypeDataUploadControllerIntegrationTest.java @@ -21,6 +21,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import io.kowalski.fannypack.FannyPack; +import io.micronaut.http.HttpHeaders; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; import io.micronaut.http.MediaType; @@ -30,6 +31,7 @@ import io.micronaut.http.client.multipart.MultipartBody; import io.micronaut.http.multipart.CompletedFileUpload; import io.micronaut.http.netty.cookies.NettyCookie; +import io.micronaut.http.server.types.files.StreamedFile; import io.micronaut.test.annotation.MockBean; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.breedinginsight.DatabaseTest; @@ -38,10 +40,7 @@ import org.breedinginsight.brapps.importer.model.response.ImportResponse; import org.breedinginsight.daos.ProgramDAO; import org.breedinginsight.daos.UserDAO; -import org.breedinginsight.model.GenotypeImportDetails; -import org.breedinginsight.model.Program; -import org.breedinginsight.model.ProgramBrAPIEndpoints; -import org.breedinginsight.model.User; +import org.breedinginsight.model.*; import org.breedinginsight.services.ProgramService; import org.breedinginsight.services.exceptions.DoesNotExistException; import org.breedinginsight.services.geno.GenotypeService; @@ -52,7 +51,9 @@ import org.junit.jupiter.api.TestInstance; import javax.inject.Inject; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.OffsetDateTime; @@ -167,6 +168,7 @@ void getGenotypeImportsReturnsPagedAndSortedResponse() throws DoesNotExistExcept doReturn(Optional.of(program)).when(programService).getById(program.getId()); GenotypeImportDetails older = GenotypeImportDetails.builder() + .genotypeImportId(UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")) .sampleSubmissionId(UUID.fromString("11111111-1111-1111-1111-111111111111")) .projectNameForSampleSubmission("Older Submission") .sampleSubmissionCreatedBy("Test User") @@ -176,6 +178,7 @@ void getGenotypeImportsReturnsPagedAndSortedResponse() throws DoesNotExistExcept .build(); GenotypeImportDetails newer = GenotypeImportDetails.builder() + .genotypeImportId(UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb")) .sampleSubmissionId(UUID.fromString("22222222-2222-2222-2222-222222222222")) .projectNameForSampleSubmission("Newer Submission") .sampleSubmissionCreatedBy("Test User") @@ -207,6 +210,7 @@ void getGenotypeImportsReturnsPagedAndSortedResponse() throws DoesNotExistExcept assertEquals(1, data.size()); JsonObject firstRow = data.get(0).getAsJsonObject(); + assertEquals("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", firstRow.get("genotypeImportId").getAsString()); assertEquals("22222222-2222-2222-2222-222222222222", firstRow.get("sampleSubmissionId").getAsString()); assertEquals("Newer Submission", firstRow.get("projectNameForSampleSubmission").getAsString()); assertEquals("Test User", firstRow.get("sampleSubmissionCreatedBy").getAsString()); @@ -349,6 +353,80 @@ void getGenotypeImportsReturnsEmptyDataWhenFiltersDoNotMatch() throws DoesNotExi verify(genotypeService, times(1)).getGenotypeImports(program.getId()); } + @Test + void downloadGenotypeImportReturnsAttachmentWhenServiceReturnsFile() throws Exception { + UUID genotypeImportId = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"); + + doReturn(getBrAPIEndpoints()).when(programService).getBrapiEndpoints(program.getId()); + doReturn(Optional.of(program)).when(programService).getById(program.getId()); + + DownloadFile downloadFile = new DownloadFile( + "sample.vcf", + new StreamedFile( + new ByteArrayInputStream("vcf-data".getBytes(StandardCharsets.UTF_8)), + new io.micronaut.http.MediaType(io.micronaut.http.MediaType.APPLICATION_OCTET_STREAM) + ) + ); + + doReturn(Optional.of(downloadFile)).when(genotypeService) + .downloadGenotypeImport(program.getId(), genotypeImportId); + + HttpResponse response = client.exchange( + GET(String.format("/programs/%s/geno/imports/%s/download", program.getId(), genotypeImportId)) + .cookie(new NettyCookie("phylo-token", "test-registered-user")), + byte[].class + ).blockingFirst(); + + assertEquals(HttpStatus.OK, response.getStatus()); + assertEquals("attachment;filename=sample.vcf", response.header(HttpHeaders.CONTENT_DISPOSITION)); + + verify(programService).getBrapiEndpoints(program.getId()); + verify(programService).getById(program.getId()); + verify(genotypeService, times(1)).downloadGenotypeImport(program.getId(), genotypeImportId); + } + + @Test + void downloadGenotypeImportReturnsNotFoundWhenServiceReturnsEmpty() throws IOException, DoesNotExistException { + UUID genotypeImportId = UUID.fromString("cccccccc-cccc-cccc-cccc-cccccccccccc"); + + doReturn(getBrAPIEndpoints()).when(programService).getBrapiEndpoints(program.getId()); + doReturn(Optional.of(program)).when(programService).getById(program.getId()); + doReturn(Optional.empty()).when(genotypeService) + .downloadGenotypeImport(program.getId(), genotypeImportId); + + HttpClientResponseException exception = assertThrows(HttpClientResponseException.class, () -> client.exchange( + GET(String.format("/programs/%s/geno/imports/%s/download", program.getId(), genotypeImportId)) + .cookie(new NettyCookie("phylo-token", "test-registered-user")), + byte[].class + ).blockingFirst()); + + assertEquals(HttpStatus.NOT_FOUND, exception.getStatus()); + + verify(programService).getBrapiEndpoints(program.getId()); + verify(programService).getById(program.getId()); + verify(genotypeService, times(1)).downloadGenotypeImport(program.getId(), genotypeImportId); + } + + @Test + void downloadGenotypeImportReturnsNotFoundWhenProgramLookupFails() throws DoesNotExistException { + UUID genotypeImportId = UUID.fromString("dddddddd-dddd-dddd-dddd-dddddddddddd"); + + doReturn(getBrAPIEndpoints()).when(programService).getBrapiEndpoints(program.getId()); + doReturn(Optional.empty()).when(programService).getById(program.getId()); + + HttpClientResponseException exception = assertThrows(HttpClientResponseException.class, () -> client.exchange( + GET(String.format("/programs/%s/geno/imports/%s/download", program.getId(), genotypeImportId)) + .cookie(new NettyCookie("phylo-token", "test-registered-user")), + byte[].class + ).blockingFirst()); + + assertEquals(HttpStatus.NOT_FOUND, exception.getStatus()); + + verify(programService).getBrapiEndpoints(program.getId()); + verify(programService).getById(program.getId()); + verifyNoInteractions(genotypeService); + } + private MultipartBody multipartBody() { return MultipartBody.builder() .addPart("file", new File("src/test/resources/files/geno/sample.vcf")) diff --git a/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java b/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java index 7acf51a28..d3c7c7415 100644 --- a/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java +++ b/src/test/java/org/breedinginsight/services/geno/impl/GigwaGenotypeServiceImplIntegrationTest.java @@ -443,8 +443,11 @@ public void testGetGenotypeImportsReturnsRowsIncludingSampleSubmissionId() { UUID programId = UUID.randomUUID(); UUID olderSubmissionId = UUID.randomUUID(); UUID newerSubmissionId = UUID.randomUUID(); + UUID genotypeImportId1 = UUID.randomUUID(); + UUID genotypeImportId2 = UUID.randomUUID(); GenotypeImportDetails older = GenotypeImportDetails.builder() + .genotypeImportId(genotypeImportId1) .sampleSubmissionId(olderSubmissionId) .projectNameForSampleSubmission("Submission " + olderSubmissionId) .sampleSubmissionCreatedBy("system") @@ -454,6 +457,7 @@ public void testGetGenotypeImportsReturnsRowsIncludingSampleSubmissionId() { .build(); GenotypeImportDetails newer = GenotypeImportDetails.builder() + .genotypeImportId(genotypeImportId2) .sampleSubmissionId(newerSubmissionId) .projectNameForSampleSubmission("Submission " + newerSubmissionId) .sampleSubmissionCreatedBy("system") @@ -469,6 +473,7 @@ public void testGetGenotypeImportsReturnsRowsIncludingSampleSubmissionId() { assertNotNull(rows); assertEquals(2, rows.size()); + assertEquals(genotypeImportId2, rows.get(0).getGenotypeImportId()); assertEquals(newerSubmissionId, rows.get(0).getSampleSubmissionId()); assertEquals("Submission " + newerSubmissionId, rows.get(0).getProjectNameForSampleSubmission()); assertEquals("sample.vcf", rows.get(0).getGenotypingFileName()); @@ -476,6 +481,7 @@ public void testGetGenotypeImportsReturnsRowsIncludingSampleSubmissionId() { assertEquals("system", rows.get(0).getSampleSubmissionCreatedBy()); assertEquals("system", rows.get(0).getGenotypingImportBy()); + assertEquals(genotypeImportId1, rows.get(1).getGenotypeImportId()); assertEquals(olderSubmissionId, rows.get(1).getSampleSubmissionId()); assertEquals("Submission " + olderSubmissionId, rows.get(1).getProjectNameForSampleSubmission()); assertEquals("sample.vcf", rows.get(1).getGenotypingFileName()); @@ -498,6 +504,47 @@ public void testGetGenotypeImportsReturnsEmptyListWhenNoImportsExist() { verify(genotypeImportDAO).getGenotypeImportsByProgramId(programId); } + @Test + public void testDownloadGenotypeImportReturnsOriginalUploadedFile() throws Exception { + UUID programId = UUID.randomUUID(); + String programKey = "TESTDOWNLOADGENOIMPORT"; + UUID submissionId = UUID.randomUUID(); + UUID importerImportId = UUID.randomUUID(); + UUID genotypeImportId = UUID.randomUUID(); + + uploadGenoData(programId, programKey, submissionId, importerImportId); + doReturn(Optional.of(GenotypeImportDownloadDetails.builder() + .sampleSubmissionId(submissionId) + .importerImportId(importerImportId) + .genotypeFileName("sample.vcf") + .build())) + .when(genotypeImportDAO).getDownloadableGenotypeImportById(programId, genotypeImportId); + + Optional downloadFile = gigwaGenoStorageService.downloadGenotypeImport(programId, genotypeImportId); + + verify(genotypeImportDAO, times(1)).getDownloadableGenotypeImportById(programId, genotypeImportId); + assertTrue(downloadFile.isPresent()); + assertEquals("sample.vcf", downloadFile.get().getFileName()); + assertArrayEquals( + new TestFileUpload("src/test/resources/files/geno/sample.vcf", MediaType.of("application/vcard")).getBytes(), + downloadFile.get().getStreamedFile().getInputStream().readAllBytes() + ); + } + + @Test + public void testDownloadGenotypeImportReturnsEmptyWhenDaoReturnsEmpty() { + UUID programId = UUID.randomUUID(); + UUID genotypeImportId = UUID.randomUUID(); + + doReturn(Optional.empty()).when(genotypeImportDAO) + .getDownloadableGenotypeImportById(programId, genotypeImportId); + + Optional downloadFile = gigwaGenoStorageService.downloadGenotypeImport(programId, genotypeImportId); + + assertTrue(downloadFile.isEmpty()); + verify(genotypeImportDAO, times(1)).getDownloadableGenotypeImportById(programId, genotypeImportId); + } + @Test public void testSubmitInvalidHeader() throws ApiException { UUID programId = UUID.fromString("29162e85-e739-4f19-9fd0-0c377ed59956");