diff --git a/src/main/java/org/breedinginsight/brapi/v2/GermplasmController.java b/src/main/java/org/breedinginsight/brapi/v2/GermplasmController.java index 0141fa3db..188d10fa0 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/GermplasmController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/GermplasmController.java @@ -106,10 +106,10 @@ public HttpResponse>>> getGermplasm( @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) public HttpResponse>>> getGermplasmListRecords( @PathVariable("programId") UUID programId, - @PathVariable("listDbId") String listId, + @PathVariable("listDbId") String listDbId, @QueryValue @QueryValid(using = GermplasmQueryMapper.class) @Valid GermplasmQuery queryParams) { try { - List germplasm = germplasmService.getGermplasmByList(programId, listId); + List germplasm = germplasmService.getGermplasmByList(programId, listDbId); SearchRequest searchRequest = queryParams.constructSearchRequest(); return ResponseUtils.getBrapiQueryResponse(germplasm, germplasmQueryMapper, queryParams, searchRequest); } catch (Exception e) { diff --git a/src/main/java/org/breedinginsight/brapi/v2/constants/BrAPIAdditionalInfoFields.java b/src/main/java/org/breedinginsight/brapi/v2/constants/BrAPIAdditionalInfoFields.java index 1a633b9a1..55a2c95f1 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/constants/BrAPIAdditionalInfoFields.java +++ b/src/main/java/org/breedinginsight/brapi/v2/constants/BrAPIAdditionalInfoFields.java @@ -18,6 +18,8 @@ package org.breedinginsight.brapi.v2.constants; public final class BrAPIAdditionalInfoFields { + public static final String GERMPLASM_LIST_ENTRY_NUMBERS = "listEntryNumbers"; + public static final String GERMPLASM_LIST_ID = "listId"; public static final String GERMPLASM_RAW_PEDIGREE = "rawPedigree"; public static final String GERMPLASM_PEDIGREE_BY_NAME = "pedigreeByName"; public static final String GERMPLASM_PEDIGREE_BY_UUID = "pedigreeByUUID"; diff --git a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIGermplasmService.java b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIGermplasmService.java index 6cc8446c8..b7c4fa323 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIGermplasmService.java +++ b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIGermplasmService.java @@ -9,11 +9,10 @@ import lombok.extern.slf4j.Slf4j; import org.brapi.v2.model.core.BrAPIListSummary; import org.brapi.v2.model.core.BrAPIListTypes; +import org.brapi.v2.model.core.request.BrAPIListNewRequest; import org.brapi.v2.model.core.response.BrAPIListDetails; -import org.brapi.v2.model.core.response.BrAPIListsListResponse; import org.brapi.v2.model.core.response.BrAPIListsSingleResponse; import org.brapi.v2.model.germ.BrAPIGermplasm; -import org.brapi.v2.model.germ.BrAPIGermplasmSynonyms; import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields; import org.breedinginsight.brapps.importer.daos.BrAPIListDAO; import org.breedinginsight.brapps.importer.model.exports.FileType; @@ -35,6 +34,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.function.ToIntFunction; import java.util.stream.Collectors; @Slf4j @@ -112,18 +112,25 @@ public List getGermplasmListsByProgramId(UUID programId, HttpR } } - public List> processData(List germplasm){ + public List> processListData(List germplasm, UUID germplasmListId){ List> processedData = new ArrayList<>(); for (BrAPIGermplasm germplasmEntry: germplasm) { HashMap row = new HashMap<>(); row.put("GID", Integer.valueOf(germplasmEntry.getAccessionNumber())); row.put("Name", germplasmEntry.getGermplasmName()); - row.put("Entry No", germplasmEntry.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsInt()); row.put("Breeding Method", germplasmEntry.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD).getAsString()); String source = germplasmEntry.getSeedSource(); row.put("Source", source); + // Use the entry number in the list map if generated + if(new UUID(0,0).compareTo(germplasmListId) == 0) { + row.put("Entry No", germplasmEntry.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsInt()); + } else { + row.put("Entry No", germplasmEntry.getAdditionalInfo() + .getAsJsonObject(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ENTRY_NUMBERS).get(germplasmListId.toString()).getAsInt()); + } + //If germplasm was imported with an external UID, it will be stored in external reference with same source as seed source List externalReferences = germplasmEntry.getExternalReferences(); for (BrAPIExternalReference reference: externalReferences){ @@ -156,17 +163,24 @@ public List> processData(List germplasm){ return processedData; } - public List getGermplasmByList(UUID programId, String listId) throws ApiException { + public List getGermplasmByList(UUID programId, String listDbId) throws ApiException { // get list germplasm names - BrAPIListsSingleResponse listResponse = brAPIListDAO.getListById(listId, programId); + BrAPIListsSingleResponse listResponse = brAPIListDAO.getListById(listDbId, programId); if(Objects.nonNull(listResponse) && Objects.nonNull(listResponse.getResult())) { - List germplasmNames = listResponse.getResult().getData(); + + // get the list ID stored in the list external references + UUID listId = getGermplasmListId(listResponse.getResult()); // get list BrAPI germplasm variables - return germplasmDAO.getGermplasmByRawName(germplasmNames, programId); + List germplasmNames = listResponse.getResult().getData(); + List germplasm = germplasmDAO.getGermplasmByRawName(germplasmNames, programId); + + // set the list ID in the germplasm additional info + germplasm.forEach(g -> g.putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ID, listId)); + return germplasm; } else throw new ApiException(); } - public DownloadFile exportGermplasmList(UUID programId, String listId, FileType fileExtension) throws ApiException, IOException { + public DownloadFile exportGermplasmList(UUID programId, String listId, FileType fileExtension) throws IllegalArgumentException, ApiException, IOException { List columns = GermplasmFileColumns.getOrderedColumns(); //Retrieve germplasm list data @@ -175,8 +189,10 @@ public DownloadFile exportGermplasmList(UUID programId, String listId, FileType //Retrieve germplasm data List germplasmNames = listData.getData(); List germplasm = germplasmDAO.getGermplasmByRawName(germplasmNames, programId); + //processGermplasmForDisplay, numbers - germplasm.sort(Comparator.comparingInt(g -> g.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsInt())); + UUID germplasmListId = getGermplasmListId(listData); + germplasm.sort(Comparator.comparingInt(getEntryNumber(germplasmListId))); String listName = listData.getListName(); Optional optionalProgram = programService.getById(programId); @@ -187,7 +203,7 @@ public DownloadFile exportGermplasmList(UUID programId, String listId, FileType String fileName = createFileName(listData, listName); StreamedFile downloadFile; //Convert list data to List> data to pass into file writer - List> processedData = processData(germplasm); + List> processedData = processListData(germplasm, germplasmListId); if (fileExtension == FileType.CSV){ downloadFile = CSVWriter.writeToDownload(columns, processedData, fileExtension); @@ -198,6 +214,57 @@ public DownloadFile exportGermplasmList(UUID programId, String listId, FileType return new DownloadFile(fileName, downloadFile); } + public UUID getGermplasmListId(BrAPIListDetails listData) { + if(Objects.nonNull(listData.getExternalReferences()) && hasListExternalReference(listData.getExternalReferences())) { + return UUID.fromString(listData.getExternalReferences().stream() + .filter(e -> referenceSource.concat("/lists").equals(e.getReferenceSource())) + .map(e -> e.getReferenceID()).findAny().orElse("00000000-0000-0000-000000000000")); + } else { + return new UUID(0,0); + } + } + + public UUID getGermplasmListId(BrAPIListNewRequest importList) { + if(Objects.nonNull(importList.getExternalReferences()) && hasListExternalReference(importList.getExternalReferences())) { + return UUID.fromString(importList.getExternalReferences().stream() + .filter(e -> referenceSource.concat("/lists").equals(e.getReferenceSource())) + .map(e -> e.getReferenceID()).findAny().orElse("00000000-0000-0000-000000000000")); + } else { + return new UUID(0,0); + } + } + + private boolean hasListExternalReference(List refs) throws IllegalArgumentException { + if (refs == null) throw new IllegalArgumentException(); + return refs.stream().anyMatch(e -> referenceSource.concat("/lists").equals(e.getReferenceSource())); + } + + private ToIntFunction getEntryNumber(UUID germplasmListId) throws IllegalArgumentException { + if(germplasmListId.compareTo(new UUID(0,0)) == 0) { + return this::getImportEntryNumber; + } else { + return g -> getGermplasmListEntryNumber(g, germplasmListId); + } + } + + private Integer getImportEntryNumber(BrAPIGermplasm g) throws IllegalArgumentException { + if(Objects.nonNull(g.getAdditionalInfo()) && + g.getAdditionalInfo().has(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER)) { + return g.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsInt(); + } else { + throw new IllegalArgumentException(); + } + } + private Integer getGermplasmListEntryNumber(BrAPIGermplasm g, UUID germplasmListId) throws IllegalArgumentException { + if(Objects.nonNull(g.getAdditionalInfo()) && + g.getAdditionalInfo().has(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ENTRY_NUMBERS)) { + return g.getAdditionalInfo().getAsJsonObject(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ENTRY_NUMBERS) + .get(germplasmListId.toString()).getAsInt(); + } else { + throw new IllegalArgumentException(); + } + } + private String createFileName(BrAPIListDetails listData, String listName) { //TODO change timestamp to edit date when editing functionality is added String timestamp; diff --git a/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java b/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java index c2c74a433..ae04e3a6b 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java +++ b/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java @@ -27,6 +27,7 @@ import org.brapi.v2.model.germ.BrAPIGermplasmSynonyms; import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields; import org.breedinginsight.brapps.importer.model.config.*; +import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.model.Program; import org.breedinginsight.model.User; @@ -131,11 +132,16 @@ public BrAPIListNewRequest constructBrAPIList(Program program, String referenceS brapiList.setListName(constructGermplasmListName(listName, program)); brapiList.setListDescription(this.listDescription); brapiList.listType(BrAPIListTypes.GERMPLASM); - // Set external reference - BrAPIExternalReference reference = new BrAPIExternalReference(); - reference.setReferenceSource(String.format("%s/programs", referenceSource)); - reference.setReferenceID(program.getId().toString()); - brapiList.setExternalReferences(List.of(reference)); + + // Set external references + BrAPIExternalReference programReference = new BrAPIExternalReference(); + programReference.setReferenceSource(String.format("%s/programs", referenceSource)); + programReference.setReferenceID(program.getId().toString()); + BrAPIExternalReference listReference = new BrAPIExternalReference(); + listReference.setReferenceSource(String.format("%s/lists", referenceSource)); + listReference.setReferenceID(UUID.randomUUID().toString()); + brapiList.setExternalReferences(List.of(programReference, listReference)); + return brapiList; } @@ -143,13 +149,12 @@ public static String constructGermplasmListName(String listName, Program program return String.format("%s [%s-germplasm]", listName, program.getKey()); } - private BrAPIGermplasm constructBrAPIGermplasm(ProgramBreedingMethodEntity breedingMethod, User user) { + public BrAPIGermplasm constructBrAPIGermplasm(ProgramBreedingMethodEntity breedingMethod, User user, UUID listId) { BrAPIGermplasm germplasm = new BrAPIGermplasm(); germplasm.setGermplasmName(getGermplasmName()); germplasm.setDefaultDisplayName(getGermplasmName()); germplasm.setGermplasmPUI(getGermplasmPUI()); germplasm.setCollection(getCollection()); - germplasm.putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER, entryNo); germplasm.putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_FEMALE_PARENT_GID, getFemaleParentDBID()); germplasm.putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_MALE_PARENT_GID, getMaleParentDBID()); germplasm.putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_FEMALE_PARENT_ENTRY_NO, getFemaleParentEntryNo()); @@ -158,6 +163,9 @@ private BrAPIGermplasm constructBrAPIGermplasm(ProgramBreedingMethodEntity breed createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_ID, user.getId().toString()); createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_NAME, user.getName()); germplasm.putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_BY, createdBy); + Map listEntryNumbers = new HashMap<>(); + listEntryNumbers.put(listId, entryNo); + germplasm.putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ENTRY_NUMBERS, listEntryNumbers); //TODO: Need to check that the acquisition date it in date format //brAPIGermplasm.setAcquisitionDate(pedigreeImport.getGermplasm().getAcquisitionDate()); germplasm.setCountryOfOriginCode(getCountryOfOrigin()); @@ -246,8 +254,8 @@ private void setBrAPIGermplasmCommitFields(BrAPIGermplasm germplasm, String prog } } - public BrAPIGermplasm constructBrAPIGermplasm(Program program, ProgramBreedingMethodEntity breedingMethod, User user, boolean commit, String referenceSource, Supplier nextVal) { - BrAPIGermplasm germplasm = constructBrAPIGermplasm(breedingMethod, user); + public BrAPIGermplasm constructBrAPIGermplasm(Program program, ProgramBreedingMethodEntity breedingMethod, User user, boolean commit, String referenceSource, Supplier nextVal, UUID listId) { + BrAPIGermplasm germplasm = constructBrAPIGermplasm(breedingMethod, user, listId); if (commit) { setBrAPIGermplasmCommitFields(germplasm, program.getKey(), referenceSource, nextVal); } @@ -261,4 +269,4 @@ public BrAPIGermplasm constructBrAPIGermplasm(Program program, ProgramBreedingMe return germplasm; } -} \ No newline at end of file +} diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java index 18388251e..5f4f44740 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java @@ -273,7 +273,9 @@ public Map process(List importRows entryNumberCounts.put(germplasm.getEntryNo(), entryNumberCounts.containsKey(germplasm.getEntryNo()) ? entryNumberCounts.get(germplasm.getEntryNo()) + 1 : 1); - BrAPIGermplasm newGermplasm = germplasm.constructBrAPIGermplasm(program, breedingMethod, user, commit, BRAPI_REFERENCE_SOURCE, nextVal); + UUID importListId = brAPIGermplasmService.getGermplasmListId(importList); + + BrAPIGermplasm newGermplasm = germplasm.constructBrAPIGermplasm(program, breedingMethod, user, commit, BRAPI_REFERENCE_SOURCE, nextVal, importListId); newGermplasmList.add(newGermplasm); // Assign status of the germplasm diff --git a/src/main/java/org/breedinginsight/utilities/response/mappers/GermplasmQueryMapper.java b/src/main/java/org/breedinginsight/utilities/response/mappers/GermplasmQueryMapper.java index a8b29503c..0b58c84d4 100644 --- a/src/main/java/org/breedinginsight/utilities/response/mappers/GermplasmQueryMapper.java +++ b/src/main/java/org/breedinginsight/utilities/response/mappers/GermplasmQueryMapper.java @@ -2,6 +2,7 @@ import com.google.gson.JsonObject; import lombok.Getter; +import org.brapi.v2.model.core.response.BrAPIListsSingleResponse; import org.brapi.v2.model.germ.BrAPIGermplasm; import org.breedinginsight.api.v1.controller.metadata.SortOrder; import org.breedinginsight.brapi.v1.model.ObservationVariable; @@ -24,10 +25,24 @@ public class GermplasmQueryMapper extends AbstractQueryMapper { public GermplasmQueryMapper() { fields = Map.ofEntries( - Map.entry("importEntryNumber", (germplasm) -> - germplasm.getAdditionalInfo() != null && germplasm.getAdditionalInfo().has(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER) ? - germplasm.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString() : - null), + Map.entry("importEntryNumber", (germplasm) ->{ + String entryNumber = null; + if (germplasm.getAdditionalInfo() != null) { + // if additionalInfo contains the importEntryNumber key then return the value + if (germplasm.getAdditionalInfo().has(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER)) { + entryNumber = germplasm.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(); + } + + // if additionalInfo has both listEntryNumbers and listId keys then return the entry number + // mapped to the listId + if (germplasm.getAdditionalInfo().has(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ENTRY_NUMBERS) + && germplasm.getAdditionalInfo().has(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ID)) { + String listId = germplasm.getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ID).getAsString(); + entryNumber = germplasm.getAdditionalInfo().getAsJsonObject(BrAPIAdditionalInfoFields.GERMPLASM_LIST_ENTRY_NUMBERS).get(listId).getAsString(); + } + } + return entryNumber; + }), Map.entry("accessionNumber", BrAPIGermplasm::getAccessionNumber), Map.entry("defaultDisplayName", BrAPIGermplasm::getDefaultDisplayName), Map.entry("breedingMethod", (germplasm) -> diff --git a/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java b/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java index c686897cb..0b82c9c86 100644 --- a/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java +++ b/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java @@ -177,7 +177,8 @@ public void minimalImportUserSpecifiedEntryNumbersSuccess() { for (int i = 0; i < previewRows.size(); i++) { JsonObject germplasm = previewRows.get(i).getAsJsonObject().getAsJsonObject("germplasm").getAsJsonObject("brAPIObject"); germplasmNames.add(germplasm.get("germplasmName").getAsString()); - assertEquals(Integer.toString(i+1), germplasm.getAsJsonObject("additionalInfo").get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(), "Wrong entry number"); + int finalI = i; + gson.fromJson(germplasm.getAsJsonObject("additionalInfo").getAsJsonObject("listEntryNumbers"), Map.class).forEach((listId, entryNumber) -> assertEquals(Integer.toString(finalI +1), entryNumber, "Wrong entry number")); } // Check the germplasm list @@ -607,7 +608,8 @@ public void headerCaseInsensitive() { for (int i = 0; i < previewRows.size(); i++) { JsonObject germplasm = previewRows.get(i).getAsJsonObject().getAsJsonObject("germplasm").getAsJsonObject("brAPIObject"); germplasmNames.add(germplasm.get("germplasmName").getAsString()); - assertEquals(Integer.toString(i+1), germplasm.getAsJsonObject("additionalInfo").get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(), "Wrong entry number"); + int finalI = i; + gson.fromJson(germplasm.getAsJsonObject("additionalInfo").getAsJsonObject("listEntryNumbers"), Map.class).forEach((listId, entryNumber) -> assertEquals(Integer.toString(finalI +1), entryNumber, "Wrong entry number")); } // Check the germplasm list @@ -739,8 +741,8 @@ public void checkBasicResponse(JsonObject germplasm, Table fileData, Integer i) // Germplasm display name assertEquals(fileData.getString(i, "Name"), germplasm.get("defaultDisplayName").getAsString(), "Wrong display name"); // Entry Number + gson.fromJson(germplasm.getAsJsonObject("additionalInfo").getAsJsonObject("listEntryNumbers"), Map.class).forEach((listId, entryNumber) -> assertEquals(fileData.getString(i, "Entry No"), entryNumber, "Wrong entry number")); JsonObject additionalInfo = germplasm.getAsJsonObject("additionalInfo"); - assertEquals(fileData.getString(i, "Entry No"), additionalInfo.get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(), "Wrong entry number"); // Created By User ID assertEquals(testUser.getId().toString(), additionalInfo.getAsJsonObject(BrAPIAdditionalInfoFields.CREATED_BY).get(BrAPIAdditionalInfoFields.CREATED_BY_USER_ID).getAsString(), "Wrong createdBy userId"); // Created by User name