Skip to content

Commit

Permalink
revert GET list data objects from ListController
Browse files Browse the repository at this point in the history
  • Loading branch information
dmeidlin committed Nov 20, 2024
1 parent e29d0fe commit 095342f
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 393 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.breedinginsight.brapi.v2;

import com.drew.lang.annotations.Nullable;
import io.micronaut.context.annotation.Property;
import io.micronaut.http.HttpHeaders;
import io.micronaut.http.HttpResponse;
Expand All @@ -19,10 +20,11 @@
import org.brapi.v2.model.BrAPIIndexPagination;
import org.brapi.v2.model.BrAPIMetadata;
import org.brapi.v2.model.BrAPIStatus;
import org.brapi.v2.model.core.BrAPITrial;
import org.brapi.v2.model.germ.*;
import org.brapi.v2.model.germ.request.BrAPIGermplasmSearchRequest;
import org.brapi.v2.model.germ.response.*;
import org.brapi.v2.model.germ.response.BrAPIGermplasmListResponse;
import org.brapi.v2.model.germ.response.BrAPIGermplasmPedigreeResponse;
import org.brapi.v2.model.germ.response.BrAPIGermplasmProgenyResponse;
import org.breedinginsight.api.auth.ProgramSecured;
import org.breedinginsight.api.auth.ProgramSecuredRoleGroup;
import org.breedinginsight.api.model.v1.request.query.SearchRequest;
Expand All @@ -33,27 +35,25 @@
import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields;
import org.breedinginsight.brapi.v2.dao.BrAPIGermplasmDAO;
import org.breedinginsight.brapi.v2.model.request.query.GermplasmQuery;
import org.breedinginsight.brapps.importer.services.ExternalReferenceSource;
import org.breedinginsight.model.Program;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.utilities.Utilities;
import org.breedinginsight.utilities.response.mappers.GermplasmQueryMapper;
import org.breedinginsight.brapi.v2.services.BrAPIGermplasmService;
import org.breedinginsight.brapps.importer.model.exports.FileType;
import org.breedinginsight.daos.ProgramDAO;
import org.breedinginsight.model.DownloadFile;
import org.breedinginsight.model.GermplasmGenotype;
import org.breedinginsight.model.Program;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.services.brapi.BrAPIEndpointProvider;
import org.breedinginsight.services.exceptions.AuthorizationException;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.services.geno.GenotypeService;
import org.breedinginsight.utilities.Utilities;
import org.breedinginsight.utilities.response.ResponseUtils;
import org.breedinginsight.utilities.response.mappers.GermplasmQueryMapper;

import javax.inject.Inject;
import javax.validation.Valid;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Controller("/${micronaut.bi.api.version}")
Expand Down Expand Up @@ -222,15 +222,17 @@ public HttpResponse<Response<DataResponse<List<BrAPIGermplasm>>>> getGermplasm(
}
}

@Get("/programs/{programId}/germplasm/export{?fileExtension}")
@Get("/programs/{programId}/germplasm/export{?fileExtension,list}")
@Produces(value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES})
public HttpResponse<StreamedFile> germplasmExport(
@PathVariable("programId") UUID programId, @QueryValue(defaultValue = "XLSX") String fileExtension) {
@PathVariable("programId") UUID programId,
@QueryValue(defaultValue = "XLSX") String fileExtension,
@QueryValue Optional<String> list) {
String downloadErrorMessage = "An error occurred while generating the download file. Contact the development team at [email protected].";
try {
FileType extension = Enum.valueOf(FileType.class, fileExtension);
DownloadFile germplasmListFile = germplasmService.exportGermplasm(programId, extension);
DownloadFile germplasmListFile = list.isEmpty() ? germplasmService.exportGermplasm(programId, extension) : germplasmService.exportGermplasmList(programId, list.get(), extension);
HttpResponse<StreamedFile> germplasmExport = HttpResponse.ok(germplasmListFile.getStreamedFile()).header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename="+germplasmListFile.getFileName()+extension.getExtension());
return germplasmExport;
}
Expand Down
124 changes: 5 additions & 119 deletions src/main/java/org/breedinginsight/brapi/v2/BrAPIListController.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.breedinginsight.brapi.v2;

import io.micronaut.core.beans.BeanIntrospection;
import io.micronaut.core.beans.BeanProperty;
import io.micronaut.http.*;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.*;
import io.micronaut.http.server.types.files.StreamedFile;
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.rules.SecurityRule;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -18,27 +18,19 @@
import org.breedinginsight.api.model.v1.response.Response;
import org.breedinginsight.api.model.v1.validators.QueryValid;
import org.breedinginsight.brapi.v1.controller.BrapiVersion;
import org.breedinginsight.brapi.v1.model.request.query.BrapiQuery;
import org.breedinginsight.brapi.v2.model.request.query.ListQuery;
import org.breedinginsight.brapi.v2.services.BrAPIListService;
import org.breedinginsight.brapps.importer.model.exports.FileType;
import org.breedinginsight.model.DownloadFile;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.delta.DeltaListDetails;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.utilities.response.ResponseUtils;
import org.breedinginsight.utilities.response.mappers.AbstractQueryMapper;
import org.breedinginsight.utilities.response.mappers.ListQueryMapper;

import javax.inject.Inject;
import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Controller("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2)
Expand Down Expand Up @@ -105,7 +97,7 @@ public HttpResponse<Response<DataResponse<Object>>> deleteListById(
@PathVariable("programId") UUID programId,
@PathVariable("listDbId") String listDbId,
HttpRequest<Void> request
) throws DoesNotExistException, ApiException {
) {
boolean hardDelete = false;
if (request.getParameters().contains("hardDelete")) {
String paramValue = request.getParameters().get("hardDelete");
Expand All @@ -119,110 +111,4 @@ public HttpResponse<Response<DataResponse<Object>>> deleteListById(
return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving germplasm list records");
}
}

@Get("/lists/{listDbId}")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES})
@SuppressWarnings("unchecked")
public <T extends BrapiQuery, U> HttpResponse<Response<DataResponse<List<U>>>> getListById(
@PathVariable("programId") UUID programId,
@PathVariable("listDbId") String listDbId,
HttpRequest<?> request) {
try {
// Get the list from the BrAPI service
DeltaListDetails details = brapiListService.getDeltaListDetails(listDbId, programId);

// Get a new instance of BrAPI query matching the type of list contents
T queryParams = (T) details.getQuery();

// Bind query parameters to the object
bindQueryParams(queryParams, request);

// Perform standard bean validation
Set<ConstraintViolation<Object>> violations = validator.validate(queryParams);
if (!violations.isEmpty()) {
List<String> errorMessages = violations.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.toList());
log.info(String.join(", ", errorMessages));
return HttpResponse.status(HttpStatus.BAD_REQUEST, "Error with list contents search parameters");
}

// Fetch the list contents from the BrAPI service
List<U> listContentsBrAPIObjects = (List<U>) details.getDataObjects();

// Construct a search request for sorting the list contents
SearchRequest searchRequest = details.constructSearchRequest(queryParams);

// Get the map used to connect query sorting keys to contents object values
AbstractQueryMapper contentsQueryMapper = details.getQueryMapper();

return ResponseUtils.getBrapiQueryResponse(listContentsBrAPIObjects, contentsQueryMapper, queryParams, searchRequest);
} catch (Exception e) {
log.info(e.getMessage(), e);
return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving list records");
}
}

@Get("/lists/{listDbId}/export{?fileExtension}")
@Produces(value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES})
public HttpResponse<StreamedFile> germplasmListExport(
@PathVariable("programId") UUID programId, @PathVariable("listDbId") String listDbId, @QueryValue(defaultValue = "XLSX") String fileExtension) {
String downloadErrorMessage = "An error occurred while generating the download file. Contact the development team at [email protected].";
try {
// Get the list from the BrAPI service
DeltaListDetails details = brapiListService.getDeltaListDetails(listDbId, programId);

FileType extension = Enum.valueOf(FileType.class, fileExtension);
DownloadFile listContentsFile = details.exportListObjects(extension);
return HttpResponse.ok(listContentsFile.getStreamedFile()).header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename="+listContentsFile.getFileName()+extension.getExtension());
}
catch (Exception e) {
log.info(e.getMessage(), e);
e.printStackTrace();
HttpResponse response = HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, downloadErrorMessage).contentType(MediaType.TEXT_PLAIN).body(downloadErrorMessage);
return response;
}
}

private void bindQueryParams(BrapiQuery queryParams, HttpRequest<?> request) {
BeanIntrospection<BrapiQuery> introspection = BeanIntrospection.getIntrospection(BrapiQuery.class);
for (BeanProperty<BrapiQuery, Object> property : introspection.getBeanProperties()) {
String paramName = property.getName();
if (request.getParameters().contains(paramName)) {
String paramValue = request.getParameters().get(paramName);
Object convertedValue;
Class<?> propertyType = property.getType();

if (propertyType.isEnum()) {
convertedValue = convertToEnum(paramValue, (Class<? extends Enum<?>>) propertyType);
} else {
convertedValue = convertValue(paramValue, propertyType);
}

property.set(queryParams, convertedValue);
}
}
}

private <T extends Enum<T>> T convertToEnum(String value, Class<? extends Enum<?>> enumClass) {
if (value == null) {
return null;
}
return Enum.valueOf((Class<T>) enumClass, value.toUpperCase());
}


// Convert, if necessary, the values of query parameters to match the type defined for the fields in the BrapiQuery class
private Object convertValue(String value, Class<?> targetType) {
// Implement type conversion logic here
// Other list content types might need more complex logic
if (targetType == String.class) return value;
if (targetType == Integer.class) return Integer.parseInt(value);
if (targetType == Long.class) return Long.parseLong(value);
if (targetType == Boolean.class) return Boolean.parseBoolean(value);
// Add more type conversions as needed
return value;
}
}
31 changes: 10 additions & 21 deletions src/main/java/org/breedinginsight/brapi/v2/dao/BrAPIListDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import okhttp3.Request;
import org.brapi.client.v2.ApiResponse;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.client.v2.model.queryParams.core.ListQueryParams;
import org.brapi.client.v2.modules.core.ListsApi;
import org.brapi.v2.model.BrAPIExternalReference;
import org.brapi.v2.model.BrAPIResponse;
Expand All @@ -34,15 +33,15 @@
import org.brapi.v2.model.core.BrAPIListTypes;
import org.brapi.v2.model.core.request.BrAPIListNewRequest;
import org.brapi.v2.model.core.request.BrAPIListSearchRequest;
import org.brapi.v2.model.core.response.*;
import org.brapi.v2.model.pheno.BrAPIObservation;
import org.brapi.v2.model.core.response.BrAPIListDetails;
import org.brapi.v2.model.core.response.BrAPIListsListResponse;
import org.brapi.v2.model.core.response.BrAPIListsListResponseResult;
import org.brapi.v2.model.core.response.BrAPIListsSingleResponse;
import org.breedinginsight.brapi.v1.controller.BrapiVersion;
import org.breedinginsight.brapps.importer.daos.ImportDAO;
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.daos.ProgramDAO;
import org.breedinginsight.model.ProgramBrAPIEndpoints;
import org.breedinginsight.model.delta.DeltaEntityFactory;
import org.breedinginsight.model.delta.DeltaListDetails;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.services.brapi.BrAPIEndpointProvider;
import org.breedinginsight.services.exceptions.DoesNotExistException;
Expand All @@ -52,7 +51,10 @@
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
Expand All @@ -62,16 +64,14 @@ public class BrAPIListDAO {
private ImportDAO importDAO;
private final BrAPIDAOUtil brAPIDAOUtil;
private final BrAPIEndpointProvider brAPIEndpointProvider;
private final DeltaEntityFactory deltaEntityFactory;
private final ProgramService programService;

@Inject
public BrAPIListDAO(ProgramDAO programDAO, ImportDAO importDAO, BrAPIDAOUtil brAPIDAOUtil, BrAPIEndpointProvider brAPIEndpointProvider, DeltaEntityFactory deltaEntityFactory, ProgramService programService) {
public BrAPIListDAO(ProgramDAO programDAO, ImportDAO importDAO, BrAPIDAOUtil brAPIDAOUtil, BrAPIEndpointProvider brAPIEndpointProvider, ProgramService programService) {
this.programDAO = programDAO;
this.importDAO = importDAO;
this.brAPIDAOUtil = brAPIDAOUtil;
this.brAPIEndpointProvider = brAPIEndpointProvider;
this.deltaEntityFactory = deltaEntityFactory;
this.programService = programService;
}

Expand Down Expand Up @@ -211,19 +211,8 @@ public List<BrAPIListSummary> createBrAPILists(List<BrAPIListNewRequest> brapiLi
throw new ApiException("No response after creating list");
}

public DeltaListDetails getDeltaListDetailsByDbId(String listDbId, UUID programId) throws ApiException {
ListsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ListsApi.class);
ApiResponse<BrAPIListsSingleResponse> response = api.listsListDbIdGet(listDbId);
if (Objects.isNull(response.getBody()) || Objects.isNull(response.getBody().getResult()))
{
throw new ApiException();
}

BrAPIListDetails details = response.getBody().getResult();
return deltaEntityFactory.makeDeltaListDetailsBean(details);
}

public void deleteBrAPIList(String listDbId, UUID programId, boolean hardDelete) throws ApiException {
// TODO: Switch to using the ListsApi from the BrAPI client library once the delete endpoints are merged into it
var programBrAPIBaseUrl = getProgramBrAPIBaseUrl(programId);
var requestUrl = HttpUrl.parse(programBrAPIBaseUrl + "/lists/" + listDbId).newBuilder();
requestUrl.addQueryParameter("hardDelete", Boolean.toString(hardDelete));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public Optional<BrAPIGermplasm> getGermplasmByDBID(UUID programId, String germpl
return germplasmDAO.getGermplasmByDBID(germplasmId, programId);
}

public List<Map<String, Object>> processListData(List<BrAPIGermplasm> germplasm, BrAPIListDetails germplasmList, Program program){
public List<Map<String, Object>> processListData(List<BrAPIGermplasm> germplasm, List<String> listData, Program program){
Map<String, BrAPIGermplasm> germplasmByName = new HashMap<>();
for (BrAPIGermplasm g: germplasm) {
// Use the full, unique germplasmName with programKey and accessionNumber (GID) for 2 reasons:
Expand All @@ -97,14 +97,14 @@ public List<Map<String, Object>> processListData(List<BrAPIGermplasm> germplasm,

// This holds the BrAPI list items or all germplasm in a program if the list is null.
List<String> orderedGermplasmNames = new ArrayList<>();
if (germplasmList == null) {
if (listData == null) {
orderedGermplasmNames = germplasm.stream().sorted((left, right) -> {
Integer leftAccessionNumber = Integer.parseInt(left.getAccessionNumber());
Integer rightAccessionNumber = Integer.parseInt(right.getAccessionNumber());
return leftAccessionNumber.compareTo(rightAccessionNumber);
}).map(BrAPIGermplasm::getGermplasmName).collect(Collectors.toList());
} else {
orderedGermplasmNames = germplasmList.getData();
orderedGermplasmNames = listData;
}

// For export, assign entry number sequentially based on BrAPI list order.
Expand All @@ -124,7 +124,7 @@ public List<Map<String, Object>> processListData(List<BrAPIGermplasm> germplasm,
row.put("Source", source);

// Use the entry number in the list map if generated
if(germplasmList == null) {
if(listData == null) {
// Not downloading a real list, use GID (https://breedinginsight.atlassian.net/browse/BI-2266).
row.put("Entry No", Integer.valueOf(germplasmEntry.getAccessionNumber()));
} else {
Expand Down Expand Up @@ -254,7 +254,9 @@ public DownloadFile exportGermplasm(UUID programId, FileType fileExtension) thro
return new DownloadFile(fileName, downloadFile);
}

public DownloadFile exportGermplasmList(UUID programId, String listId, FileType fileExtension) throws IllegalArgumentException, ApiException, IOException, DoesNotExistException {
public DownloadFile exportGermplasmList(UUID programId,
String listId,
FileType fileExtension) throws IllegalArgumentException, ApiException, IOException, DoesNotExistException {
List<Column> columns = GermplasmFileColumns.getOrderedColumns();

//Retrieve germplasm list data
Expand All @@ -270,7 +272,7 @@ public DownloadFile exportGermplasmList(UUID programId, String listId, FileType
String fileName = createFileName(listData, listName);
StreamedFile downloadFile;
//Convert list data to List<Map<String, Object>> data to pass into file writer
List<Map<String, Object>> processedData = processListData(germplasm, listData, program);
List<Map<String, Object>> processedData = processListData(germplasm, germplasmNames, program);

if (fileExtension == FileType.CSV){
downloadFile = CSVWriter.writeToDownload(columns, processedData, fileExtension);
Expand Down
Loading

0 comments on commit 095342f

Please sign in to comment.