diff --git a/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepository.java b/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepository.java index 739feea02d0acd41ceb53c0fac02a5fd2ec0775f..7c12185204b63e1ed9a3ccd6e6c9da7092a91dca 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepository.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepository.java @@ -12,6 +12,7 @@ import fr.inra.urgi.faidare.domain.response.PaginatedList; import fr.inra.urgi.faidare.elasticsearch.repository.ESFindRepository; import java.util.Iterator; +import java.util.Set; public interface GermplasmRepository extends ESFindRepository<GermplasmSearchCriteria, GermplasmVO> { @@ -52,6 +53,11 @@ public interface GermplasmRepository */ Iterator<GermplasmMcpdVO> scrollAllGermplasmMcpd(FaidareGermplasmPOSTShearchCriteria criteria); + /** + * Scroll through all germplasmMcpd having one of the given IDs. + */ + Iterator<GermplasmMcpdVO> scrollGermplasmMcpdsByIds(Set<String> ids, int fetchSize); + /** * Find pedigree for germplasm by id. */ diff --git a/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java b/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java index 360087ce79e69f48685b4c2c3480b6de51766171..733d1da9794950b689b43cd95ae465823f45778c 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java @@ -45,6 +45,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Set; import static org.elasticsearch.search.aggregations.AggregationBuilders.filter; import static org.elasticsearch.search.aggregations.AggregationBuilders.terms; @@ -118,6 +119,12 @@ public class GermplasmRepositoryImpl implements GermplasmRepository { return new ESScrollIterator<>(client, requestFactory, parser, GermplasmMcpdVO.class, query, fetchSize); } + @Override + public Iterator<GermplasmMcpdVO> scrollGermplasmMcpdsByIds(Set<String> ids, int fetchSize) { + QueryBuilder query = QueryBuilders.idsQuery().addIds(ids.toArray(new String[0])); + return new ESScrollIterator<>(client, requestFactory, parser, GermplasmMcpdVO.class, query, fetchSize); + } + @Override public GermplasmVO getById(String germplasmDbId) { return getByIdRepository.getById(germplasmDbId); diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java index 9c126964ee66645fca5c16fbe572519caef4cf77..84da94f897426a8b78c7bc6a3dc2c62b74d4a4c3 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java @@ -6,14 +6,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.Spliterators; import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import javax.servlet.http.HttpServletRequest; - -import com.google.common.collect.Streams; import fr.inra.urgi.faidare.api.NotFoundException; import fr.inra.urgi.faidare.config.FaidareProperties; import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiGermplasmAttributeValue; @@ -25,6 +19,7 @@ import fr.inra.urgi.faidare.domain.data.germplasm.DonorVO; import fr.inra.urgi.faidare.domain.data.germplasm.GenealogyVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmAttributeValueVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmInstituteVO; +import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmMcpdVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmSitemapVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO; import fr.inra.urgi.faidare.domain.data.germplasm.InstituteVO; @@ -34,7 +29,6 @@ import fr.inra.urgi.faidare.domain.data.germplasm.PuiNameValueVO; import fr.inra.urgi.faidare.domain.data.germplasm.SiblingVO; import fr.inra.urgi.faidare.domain.data.germplasm.SiteVO; import fr.inra.urgi.faidare.domain.data.germplasm.TaxonSourceVO; -import fr.inra.urgi.faidare.domain.xref.XRefDocumentSearchCriteria; import fr.inra.urgi.faidare.domain.xref.XRefDocumentVO; import fr.inra.urgi.faidare.repository.es.GermplasmAttributeRepository; import fr.inra.urgi.faidare.repository.es.GermplasmRepository; @@ -43,8 +37,11 @@ import fr.inra.urgi.faidare.utils.Sitemaps; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @@ -63,15 +60,18 @@ public class GermplasmController { private final FaidareProperties faidareProperties; private final XRefDocumentRepository xRefDocumentRepository; private final GermplasmAttributeRepository germplasmAttributeRepository; + private final GermplasmExportService germplasmExportService; public GermplasmController(GermplasmRepository germplasmRepository, FaidareProperties faidareProperties, XRefDocumentRepository xRefDocumentRepository, - GermplasmAttributeRepository germplasmAttributeRepository) { + GermplasmAttributeRepository germplasmAttributeRepository, + GermplasmExportService germplasmExportService) { this.germplasmRepository = germplasmRepository; this.faidareProperties = faidareProperties; this.xRefDocumentRepository = xRefDocumentRepository; this.germplasmAttributeRepository = germplasmAttributeRepository; + this.germplasmExportService = germplasmExportService; } @GetMapping("/{germplasmId}") @@ -100,8 +100,19 @@ public class GermplasmController { return toModelAndView(germplasms.get(0)); } + @PostMapping("/exports") + @ResponseBody + public ResponseEntity<StreamingResponseBody> export(@Validated @RequestBody GermplasmExportCommand command) { + List<GermplasmExportableField> fields = getFieldsToExport(command); - @GetMapping(value = "/sitemap-{index}.txt") + StreamingResponseBody body = out -> { + Iterator<GermplasmMcpdVO> iterator = germplasmRepository.scrollGermplasmMcpdsByIds(command.getIds(), 1000); + germplasmExportService.export(out, iterator, fields); + }; + return ResponseEntity.ok().contentType(MediaType.parseMediaType("text/csv")).body(body); + } + + @GetMapping("/sitemap-{index}.txt") @ResponseBody public ResponseEntity<StreamingResponseBody> sitemap(@PathVariable("index") int index) { if (index < 0 || index >= Sitemaps.BUCKET_COUNT) { @@ -440,4 +451,12 @@ public class GermplasmController { xref.setEntryType("type " + name); return xref; } + + private List<GermplasmExportableField> getFieldsToExport(GermplasmExportCommand command) { + List<GermplasmExportableField> fields = command.getFields(); + if (fields.isEmpty()) { + fields = Arrays.asList(GermplasmExportableField.values()); + } + return fields; + } } diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportCommand.java b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..2ae02bdf4f7fdab3a8bf66ef35d583b863ef39f0 --- /dev/null +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportCommand.java @@ -0,0 +1,39 @@ +package fr.inra.urgi.faidare.web.germplasm; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import javax.validation.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Command sent to export a list of germplasm IDs + * @author JB Nizet + */ +public class GermplasmExportCommand { + + @NotEmpty + private final Set<String> ids; + + /** + * The ordered list of fields to export. If empty, all fields are exported + */ + private final List<GermplasmExportableField> fields; + + @JsonCreator + public GermplasmExportCommand(@JsonProperty("ids") Set<String> ids, + @JsonProperty("fields") List<GermplasmExportableField> fields) { + this.ids = ids; + this.fields = fields == null ? Collections.emptyList() : fields; + } + + public Set<String> getIds() { + return ids; + } + + public List<GermplasmExportableField> getFields() { + return fields; + } +} diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportService.java b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportService.java new file mode 100644 index 0000000000000000000000000000000000000000..1158bdf341b229e7c3779483fbfacc2e1467c395 --- /dev/null +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportService.java @@ -0,0 +1,176 @@ +package fr.inra.urgi.faidare.web.germplasm; + +import static fr.inra.urgi.faidare.web.germplasm.GermplasmExportableField.*; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.opencsv.CSVWriter; +import fr.inra.urgi.faidare.domain.data.germplasm.DonorInfoVO; +import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmMcpdVO; +import fr.inra.urgi.faidare.domain.data.germplasm.InstituteVO; +import org.springframework.stereotype.Component; + +/** + * Service allowing to export germplasms as CSV + * @author JB Nizet + */ +@Component +public class GermplasmExportService { + + private final Map<GermplasmExportableField, GermplasmExportableFieldDescriptor> descriptors; + + public GermplasmExportService() { + Map<GermplasmExportableField, GermplasmExportableFieldDescriptor> map = new HashMap<>(); + + map.put(PUID, withFieldAsHeader(PUID, vo -> vo.getGermplasmPUI())); + map.put(INSTCODE, withFieldAsHeader(INSTCODE, vo -> vo.getInstituteCode())); + map.put(ACCENUMB, withFieldAsHeader(ACCENUMB, vo -> vo.getAccessionNumber())); + map.put(COLLNUMB, withFieldAsHeader(COLLNUMB, vo -> vo.getCollectingInfo().getCollectingNumber())); + map.put(COLLCODE, withFieldAsHeader(COLLCODE, vo -> + vo.getCollectingInfo() + .getCollectingInstitutes() + .stream() + .map(InstituteVO::getInstituteCode).collect(Collectors.joining(";")))); + map.put(COLLNAME, withFieldAsHeader(COLLNAME, vo -> + vo.getCollectingInfo() + .getCollectingInstitutes() + .stream() + .map(InstituteVO::getInstituteName) + .collect(Collectors.joining(";")))); + map.put(COLLINSTADDRESS, withFieldAsHeader(COLLINSTADDRESS, vo -> + vo.getCollectingInfo() + .getCollectingInstitutes() + .stream() + .map(InstituteVO::getAddress) + .collect(Collectors.joining(";")))); + map.put(COLLMISSID, withFieldAsHeader(COLLMISSID, vo -> vo.getCollectingInfo().getCollectingMissionIdentifier())); + map.put(GENUS, withFieldAsHeader(GENUS, vo -> vo.getGenus())); + map.put(SPECIES, withFieldAsHeader(SPECIES, vo -> vo.getSpecies())); + map.put(SPAUTHOR, withFieldAsHeader(SPAUTHOR, vo -> vo.getSpeciesAuthority())); + map.put(SUBTAXA, withFieldAsHeader(SUBTAXA, vo -> vo.getSubtaxon())); + map.put(SUBTAUTHOR, withFieldAsHeader(SUBTAUTHOR, vo -> vo.getSubtaxonAuthority())); + map.put(CROPNAME, withFieldAsHeader(CROPNAME, vo -> vo.getCommonCropName())); + map.put(ACCENAME, withFieldAsHeader(ACCENAME, vo -> String.join(";", vo.getAccessionNames()))); + map.put(ACQDATE, withFieldAsHeader(ACQDATE, vo -> vo.getAcquisitionDate())); + map.put(ORIGCTY, withFieldAsHeader(ORIGCTY, vo -> vo.getCountryOfOriginCode())); + map.put(COLLSITE, withFieldAsHeader(COLLSITE, vo -> vo.getCollectingInfo().getCollectingSite().getSiteName())); + map.put(DECLATITUDE, withFieldAsHeader(DECLATITUDE, vo -> vo.getCollectingInfo().getCollectingSite().getLatitudeDecimal())); + map.put(LATITUDE, withFieldAsHeader(LATITUDE, vo -> vo.getCollectingInfo().getCollectingSite().getLatitudeDegrees())); + map.put(DECLONGITUDE, withFieldAsHeader(DECLONGITUDE, vo -> vo.getCollectingInfo().getCollectingSite().getLongitudeDecimal())); + map.put(LONGITUDE, withFieldAsHeader(LONGITUDE, vo -> vo.getCollectingInfo().getCollectingSite().getLongitudeDegrees())); + map.put(COORDUNCERT, withFieldAsHeader(COORDUNCERT, vo -> vo.getCollectingInfo().getCollectingSite().getCoordinateUncertainty())); + map.put(COORDDATUM, withFieldAsHeader(COORDDATUM, vo -> vo.getCollectingInfo().getCollectingSite().getSpatialReferenceSystem())); + map.put(GEOREFMETH, withFieldAsHeader(GEOREFMETH, vo -> vo.getCollectingInfo().getCollectingSite().getGeoreferencingMethod())); + map.put(ELEVATION, withFieldAsHeader(ELEVATION, vo -> vo.getCollectingInfo().getCollectingSite().getElevation())); + map.put(COLLDATE, withFieldAsHeader(COLLDATE, vo -> vo.getCollectingInfo().getCollectingDate())); + map.put(BREDCODE, withFieldAsHeader(BREDCODE, vo -> + vo.getBreedingInstitutes() + .stream() + .map(InstituteVO::getInstituteCode) + .collect(Collectors.joining(";")))); + map.put(BREDNAME, withFieldAsHeader(BREDNAME, vo -> + vo.getBreedingInstitutes() + .stream() + .map(InstituteVO::getInstituteName) + .collect(Collectors.joining(";")))); + map.put(SAMPSTAT, withFieldAsHeader(SAMPSTAT, vo -> vo.getBiologicalStatusOfAccessionCode())); + map.put(ANCEST, withFieldAsHeader(ANCEST, vo -> vo.getAncestralData())); + map.put(COLLSRC, withFieldAsHeader(COLLSRC, vo -> vo.getAcquisitionSourceCode())); + map.put(DONORCODE, withFieldAsHeader(DONORCODE, vo -> + vo.getDonorInfo() + .stream() + .map(donorInfoVO -> donorInfoVO.getDonorInstitute().getInstituteCode()) + .collect(Collectors.joining(";")))); + map.put(DONORNAME, withFieldAsHeader(DONORNAME, vo -> + vo.getDonorInfo() + .stream() + .map(donorInfoVO -> donorInfoVO.getDonorInstitute().getInstituteName()) + .collect(Collectors.joining(";")))); + map.put(DONORNUMB, withFieldAsHeader(DONORNUMB, vo -> + vo.getDonorInfo() + .stream() + .map(DonorInfoVO::getDonorAccessionNumber) + .collect(Collectors.joining(";")))); + map.put(OTHERNUMB, withFieldAsHeader(OTHERNUMB, vo -> String.join(";", vo.getAlternateIDs()))); + map.put(DUPLSITE, withFieldAsHeader(DUPLSITE, vo -> + vo.getSafetyDuplicateInstitutes() + .stream() + .map(InstituteVO::getInstituteCode) + .collect(Collectors.joining(";")))); + map.put(DUPLINSTNAME, withFieldAsHeader(DUPLINSTNAME, vo -> + vo.getSafetyDuplicateInstitutes() + .stream() + .map(InstituteVO::getInstituteName) + .collect(Collectors.joining(";")))); + map.put(STORAGE, withFieldAsHeader(STORAGE, vo -> String.join(";", vo.getStorageTypeCodes()))); + map.put(MLSSTAT, withFieldAsHeader(MLSSTAT, vo -> vo.getMlsStatus())); + map.put(REMARKS, withFieldAsHeader(REMARKS, vo -> vo.getRemarks())); + + this.descriptors = Collections.unmodifiableMap(map); + if (map.size() != GermplasmExportableField.values().length) { + throw new IllegalStateException("Missing field descriptor"); + } + } + + public void export(OutputStream out, Iterator<GermplasmMcpdVO> germplasms, List<GermplasmExportableField> fields) { + try { + CSVWriter csvWriter = new CSVWriter(new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)), ';', '"', '\\', "\n"); + String[] header = fields.stream() + .map(descriptors::get) + .map(GermplasmExportableFieldDescriptor::getHeader) + .toArray(String[]::new); + csvWriter.writeNext(header); + + while (germplasms.hasNext()) { + GermplasmMcpdVO vo = germplasms.next(); + String[] line = + fields.stream() + .map(descriptors::get) + .map(descriptor -> descriptor.export(vo)) + .toArray(String[]::new); + csvWriter.writeNext(line); + } + csvWriter.flush(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private GermplasmExportableFieldDescriptor withFieldAsHeader(GermplasmExportableField field, + Function<GermplasmMcpdVO, String> exporter) { + return new GermplasmExportableFieldDescriptor(field.name(), exporter); + } + + private static class GermplasmExportableFieldDescriptor { + private final String header; + private final Function<GermplasmMcpdVO, String> exporter; + + public GermplasmExportableFieldDescriptor(String header, + Function<GermplasmMcpdVO, String> exporter) { + this.header = header; + this.exporter = exporter; + } + + public String getHeader() { + return this.header; + } + + public String export(GermplasmMcpdVO germplasm) { + return this.exporter.apply(germplasm); + } + } +} + + diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportableField.java b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportableField.java new file mode 100644 index 0000000000000000000000000000000000000000..5835bf3aedbf98b67d7d1a0eff4d49f0348b86e7 --- /dev/null +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmExportableField.java @@ -0,0 +1,52 @@ +package fr.inra.urgi.faidare.web.germplasm; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * The fields of a germplasm that can be exported + * + * @author JB Nizet + */ +public enum GermplasmExportableField { + PUID, + INSTCODE, + ACCENUMB, + COLLNUMB, + COLLCODE, + COLLNAME, + COLLINSTADDRESS, + COLLMISSID, + GENUS, + SPECIES, + SPAUTHOR, + SUBTAXA, + SUBTAUTHOR, + CROPNAME, + ACCENAME, + ACQDATE, + ORIGCTY, + COLLSITE, + DECLATITUDE, + LATITUDE, + DECLONGITUDE, + LONGITUDE, + COORDUNCERT, + COORDDATUM, + GEOREFMETH, + ELEVATION, + COLLDATE, + BREDCODE, + BREDNAME, + SAMPSTAT, + ANCEST, + COLLSRC, + DONORCODE, + DONORNAME, + DONORNUMB, + OTHERNUMB, + DUPLSITE, + DUPLINSTNAME, + STORAGE, + MLSSTAT, + REMARKS +} diff --git a/backend/src/test/java/fr/inra/urgi/faidare/web/Fixtures.java b/backend/src/test/java/fr/inra/urgi/faidare/web/Fixtures.java index ea15e50aa6c909c466ae6f1f090d6c0e9d414f26..fb746865de7e9f6581ccca286360f4e89ccf4633 100644 --- a/backend/src/test/java/fr/inra/urgi/faidare/web/Fixtures.java +++ b/backend/src/test/java/fr/inra/urgi/faidare/web/Fixtures.java @@ -20,6 +20,7 @@ import fr.inra.urgi.faidare.domain.data.germplasm.GenealogyVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmAttributeValueListVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmAttributeValueVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmInstituteVO; +import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmMcpdVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO; import fr.inra.urgi.faidare.domain.data.germplasm.InstituteVO; import fr.inra.urgi.faidare.domain.data.germplasm.PedigreeVO; @@ -384,4 +385,11 @@ public class Fixtures { variable.setTrait(trait); return variable; } + + public static GermplasmMcpdVO createGermplasmMcpd() { + GermplasmMcpdVO result = new GermplasmMcpdVO(); + result.setGermplasmPUI("PUI1"); + result.setInstituteCode("Inst1"); + return result; + } } diff --git a/backend/src/test/java/fr/inra/urgi/faidare/web/germplasm/GermplasmControllerTest.java b/backend/src/test/java/fr/inra/urgi/faidare/web/germplasm/GermplasmControllerTest.java index 1fbe843db8013edb9b88e9418674891ca68fa3f6..47695c75fe427ea226d278736d0ed05fd7c1e38b 100644 --- a/backend/src/test/java/fr/inra/urgi/faidare/web/germplasm/GermplasmControllerTest.java +++ b/backend/src/test/java/fr/inra/urgi/faidare/web/germplasm/GermplasmControllerTest.java @@ -1,35 +1,30 @@ package fr.inra.urgi.faidare.web.germplasm; import static fr.inra.urgi.faidare.web.Fixtures.htmlContent; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Sets; import fr.inra.urgi.faidare.config.FaidareProperties; -import fr.inra.urgi.faidare.domain.brapi.v1.data.BrapiGermplasmAttributeValue; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmAttributeValueListVO; +import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmMcpdVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmSitemapVO; import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO; -import fr.inra.urgi.faidare.domain.data.study.StudySitemapVO; import fr.inra.urgi.faidare.domain.datadiscovery.data.DataSource; import fr.inra.urgi.faidare.domain.response.PaginatedList; -import fr.inra.urgi.faidare.domain.xref.XRefDocumentSearchCriteria; import fr.inra.urgi.faidare.domain.xref.XRefDocumentVO; import fr.inra.urgi.faidare.repository.es.GermplasmAttributeRepository; import fr.inra.urgi.faidare.repository.es.GermplasmRepository; import fr.inra.urgi.faidare.repository.es.XRefDocumentRepository; -import fr.inra.urgi.faidare.utils.Sitemaps; import fr.inra.urgi.faidare.web.Fixtures; -import fr.inra.urgi.faidare.web.study.StudyController; -import fr.inra.urgi.faidare.web.thymeleaf.CoordinatesDialect; -import fr.inra.urgi.faidare.web.thymeleaf.FaidareDialect; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -45,11 +40,15 @@ import org.springframework.test.web.servlet.MvcResult; * @author JB Nizet */ @WebMvcTest(GermplasmController.class) +@Import(GermplasmExportService.class) public class GermplasmControllerTest { @Autowired private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + @MockBean private GermplasmRepository mockGermplasmRepository; @@ -131,6 +130,35 @@ public class GermplasmControllerTest { .andExpect(status().isNotFound()); } + @Test + void shouldExportGermplasms() throws Exception { + List<GermplasmMcpdVO> germplasms = Arrays.asList( + Fixtures.createGermplasmMcpd(), + Fixtures.createGermplasmMcpd() + ); + + GermplasmExportCommand command = new GermplasmExportCommand( + Sets.newHashSet("g1", "g2"), + Arrays.asList(GermplasmExportableField.PUID, GermplasmExportableField.INSTCODE)); + + when(mockGermplasmRepository.scrollGermplasmMcpdsByIds(eq(command.getIds()), anyInt())) + .thenAnswer(invocation -> germplasms.iterator()); + + MvcResult mvcResult = mockMvc.perform(post("/germplasms/exports") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsBytes( + command))) + .andExpect(request().asyncStarted()) + .andReturn(); + + this.mockMvc.perform(asyncDispatch(mvcResult)) + .andExpect(status().isOk()) + .andExpect(content().contentType("text/csv")) + .andExpect(content().string("\"PUID\";\"INSTCODE\"\n" + + "\"PUI1\";\"Inst1\"\n" + + "\"PUI1\";\"Inst1\"\n")); + } + private void testSitemap(int index, String expectedContent) throws Exception { MvcResult mvcResult = mockMvc.perform(get("/faidare/germplasms/sitemap-" + index + ".txt") .contextPath("/faidare"))