Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
48bc5b9
[BI-1720] - initial proof of concept
mlm483 Jun 13, 2023
f7d5a19
[BI-1720] - comments
mlm483 Jun 20, 2023
867e4c9
[BI-1720] - refactoring in progress
mlm483 Jun 21, 2023
809eaa7
[BI-1720] - cleaned up and fixed bugs
mlm483 Jun 23, 2023
a4653dd
[BI-1720] - expanded unit test (WIP)
mlm483 Jun 26, 2023
2ed7b63
[BI-1720] - completed unit test
mlm483 Jul 5, 2023
e48da59
[BI-1720] - updated comment
mlm483 Jul 5, 2023
c6a6cbf
[BI-1720] - removed unused imports
mlm483 Jul 5, 2023
cf113c7
[BI-1720] - fixed media type
mlm483 Jul 5, 2023
a95e95f
[BI-1720] - cleaned up ExperimentExportQuery.java
mlm483 Jul 5, 2023
4eb2c6f
[BI-1720] - simplified TestUtils::unzipFile
mlm483 Jul 5, 2023
65675f7
[BI-1720] - added BrAPI Study specific code
mlm483 Jul 16, 2023
7d0ea06
[BI-1720] - TODO
mlm483 Jul 16, 2023
11172c8
[BI-1720] - DRY
mlm483 Jul 16, 2023
84f7f54
[BI-1720] - study GET endpoint filtering working
mlm483 Jul 18, 2023
6d3040e
[BI-1720] - removed unused controller method
mlm483 Jul 18, 2023
6e0b36f
[BI-1720] - updated TODO
mlm483 Jul 18, 2023
18ce98f
Merge pull request #274 from Breeding-Insight/feature/BI-1720-brapi-s…
mlm483 Jul 18, 2023
be73324
[BI-1720] - renamed method
mlm483 Jul 18, 2023
0342789
[BI-1720] - removed unused methods
mlm483 Jul 18, 2023
8bebb8b
Merge pull request #275 from Breeding-Insight/feature/BI-1720-brapi-s…
mlm483 Jul 18, 2023
cf1727d
[BI-1720] - pulled in latest from develop
mlm483 Jul 18, 2023
47af603
[BI-1720] - clean up
mlm483 Jul 27, 2023
fdb4c4d
[BI-1720] - reverted ListQuery change
mlm483 Jul 27, 2023
7c0b3f7
[BI-1720] - added exRef source and ID to study query
mlm483 Jul 27, 2023
024f4e6
[BI-1720] - merged redundant BrAPIStudyDAO
mlm483 Jul 27, 2023
88a4cd5
[BI-1720] - cache studies on create
mlm483 Jul 27, 2023
6aa7cc8
[BI-1720] - made naming more consistent
mlm483 Jul 27, 2023
f975aa2
Merge branch 'develop' into feature/BI-1720
mlm483 Jul 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
import org.breedinginsight.utilities.response.mappers.ExperimentQueryMapper;
import javax.inject.Inject;
import javax.validation.Valid;
import java.util.List;
import java.util.UUID;
import java.util.*;

@Slf4j
@Controller
Expand Down Expand Up @@ -92,17 +91,22 @@ public HttpResponse<Response<BrAPITrial>> getExperimentById(

@Get("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/export{?queryParams*}")
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL})
@Produces(value={"text/csv", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})
@Produces(value={"text/csv", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/octet-stream"})
public HttpResponse<StreamedFile> datasetExport(
@PathVariable("programId") UUID programId, @PathVariable("experimentId") UUID experimentId,
@QueryValue @Valid ExperimentExportQuery queryParams) {
String downloadErrorMessage = "An error occurred while generating the download file. Contact the development team at bidevteam@cornell.edu.";
try {
Program program = programService.getById(programId).orElseThrow(() -> new DoesNotExistException("Program does not exist"));
DownloadFile datasetFile = experimentService.exportObservations(program, experimentId, queryParams);

// if a list of environmentIds are sent, return multiple files (zipped),
// else if a single environmentId is sent, return single file (CSV/Excel),
// else (if no environmentIds are sent), return a single file (CSV/Excel) including all Environments.
DownloadFile downloadFile = experimentService.exportObservations(program, experimentId, queryParams);

HttpResponse<StreamedFile> response = HttpResponse
.ok(datasetFile.getStreamedFile())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + datasetFile.getFileName());
.ok(downloadFile.getStreamedFile())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + downloadFile.getFileName());
return response;
} catch (Exception e) {
log.info(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public GermplasmController(BrAPIGermplasmService germplasmService, GermplasmQuer
this.brAPIEndpointProvider = brAPIEndpointProvider;
}

// TODO: expand to fully support BrAPI request body.
@Post("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/search/germplasm{?queryParams*}")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL})
Expand Down
83 changes: 83 additions & 0 deletions src/main/java/org/breedinginsight/brapi/v2/StudyController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.brapi.v2;

import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.*;
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.rules.SecurityRule;
import lombok.extern.slf4j.Slf4j;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.v2.model.core.BrAPIStudy;
import org.breedinginsight.api.auth.ProgramSecured;
import org.breedinginsight.api.auth.ProgramSecuredRoleGroup;
import org.breedinginsight.api.model.v1.request.query.SearchRequest;
import org.breedinginsight.api.model.v1.response.DataResponse;
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.v2.model.request.query.StudyQuery;
import org.breedinginsight.brapi.v2.services.BrAPIStudyService;
import org.breedinginsight.utilities.response.ResponseUtils;
import org.breedinginsight.utilities.response.mappers.StudyQueryMapper;

import javax.inject.Inject;
import javax.validation.Valid;
import java.util.List;
import java.util.UUID;

@Slf4j
@Controller("/${micronaut.bi.api.version}")
@Secured(SecurityRule.IS_AUTHENTICATED)
public class StudyController {

private final BrAPIStudyService studyService;
private final StudyQueryMapper studyQueryMapper;


@Inject
public StudyController(BrAPIStudyService studyService, StudyQueryMapper studyQueryMapper) {
this.studyService = studyService;
this.studyQueryMapper = studyQueryMapper;
}

@Get("/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/studies{?queryParams*}")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL})
public HttpResponse<Response<DataResponse<List<BrAPIStudy>>>> getStudies(
@PathVariable("programId") UUID programId,
@QueryValue @QueryValid(using = StudyQueryMapper.class) @Valid StudyQuery queryParams) {
try {
log.debug("fetching studies for program: " + programId);

List<BrAPIStudy> studies = studyService.getStudies(programId);
queryParams.setSortField(studyQueryMapper.getDefaultSortField());
queryParams.setSortOrder(studyQueryMapper.getDefaultSortOrder());
SearchRequest searchRequest = queryParams.constructSearchRequest();
return ResponseUtils.getBrapiQueryResponse(studies, studyQueryMapper, queryParams, searchRequest);
} catch (ApiException e) {
log.info(e.getMessage(), e);
return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving study");
} catch (IllegalArgumentException e) {
log.info(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, "Error parsing requested date format");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

import io.micronaut.core.annotation.Introspected;
import lombok.Getter;
import org.breedinginsight.api.model.v1.request.query.FilterRequest;
import org.breedinginsight.api.model.v1.request.query.SearchRequest;
import org.breedinginsight.brapi.v1.model.request.query.BrapiQuery;
import org.breedinginsight.brapps.importer.model.exports.FileType;
import org.jooq.tools.StringUtils;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

@Getter
@Introspected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import org.breedinginsight.api.model.v1.request.query.FilterRequest;
import org.breedinginsight.api.model.v1.request.query.SearchRequest;
import org.breedinginsight.brapi.v1.model.request.query.BrapiQuery;
import org.breedinginsight.brapps.importer.services.ExternalReferenceSource;
import org.jooq.tools.StringUtils;

import java.util.ArrayList;
Expand Down Expand Up @@ -39,7 +38,7 @@ public SearchRequest constructSearchRequest() {
if (!StringUtils.isBlank(getSize())) {
filters.add(constructFilterRequest("size", getSize()));
}
if (getExternalReferenceSource() != null) {
if (!StringUtils.isBlank(getExternalReferenceSource())) {
filters.add(constructFilterRequest("externalReferenceSource", getExternalReferenceSource()));
}
if (!StringUtils.isBlank(getExternalReferenceId())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.breedinginsight.brapi.v2.model.request.query;

import io.micronaut.core.annotation.Introspected;
import lombok.Getter;
import org.breedinginsight.api.model.v1.request.query.FilterRequest;
import org.breedinginsight.api.model.v1.request.query.SearchRequest;
import org.breedinginsight.brapi.v1.model.request.query.BrapiQuery;
import org.jooq.tools.StringUtils;

import java.util.ArrayList;
import java.util.List;

@Getter
@Introspected
public class StudyQuery extends BrapiQuery {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think externalReferenceId and externalReferenceSource should be added to the query param, and probably change the frontend to send the request using those params instead of trialDbId

private String studyType;
private String locationDbId;
private String studyCode;
private String studyPUI;
private String commonCropName;
private String trialDbId;
private String studyDbId;
private String studyName;
private String externalReferenceSource;
private String externalReferenceId;

public SearchRequest constructSearchRequest() {
List<FilterRequest> filters = new ArrayList<>();
if (!StringUtils.isBlank(getStudyType())) {
filters.add(constructFilterRequest("studyType", getStudyType()));
}
if (!StringUtils.isBlank(getLocationDbId())) {
filters.add(constructFilterRequest("locationDbId", getLocationDbId()));
}
if (!StringUtils.isBlank(getStudyCode())) {
filters.add(constructFilterRequest("studyCode", getStudyCode()));
}
if (!StringUtils.isBlank(getStudyPUI())) {
filters.add(constructFilterRequest("studyPUI", getStudyPUI()));
}
if (!StringUtils.isBlank(getCommonCropName())) {
filters.add(constructFilterRequest("commonCropName", getCommonCropName()));
}
if (!StringUtils.isBlank(getTrialDbId())) {
filters.add(constructFilterRequest("trialDbId", getTrialDbId()));
}
if (!StringUtils.isBlank(getStudyDbId())) {
filters.add(constructFilterRequest("studyDbId", getStudyDbId()));
}
if (!StringUtils.isBlank(getStudyName())) {
filters.add(constructFilterRequest("studyName", getStudyName()));
}
if (!StringUtils.isBlank(getExternalReferenceSource())) {
filters.add(constructFilterRequest("externalReferenceSource", getExternalReferenceSource()));
}
if (!StringUtils.isBlank(getExternalReferenceId())) {
filters.add(constructFilterRequest("externalReferenceId", getExternalReferenceId()));
}
return new SearchRequest(filters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.brapi.v2.services;

import io.micronaut.http.server.exceptions.InternalServerException;
import lombok.extern.slf4j.Slf4j;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.v2.model.core.BrAPIStudy;
import org.breedinginsight.brapps.importer.daos.BrAPIStudyDAO;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
import java.util.UUID;

@Slf4j
@Singleton
public class BrAPIStudyService {

private final BrAPIStudyDAO studyDAO;

@Inject
public BrAPIStudyService(BrAPIStudyDAO studyDAO) {
this.studyDAO = studyDAO;
}

public List<BrAPIStudy> getStudies(UUID programId) throws ApiException {
try {
return studyDAO.getStudies(programId);
} catch (ApiException e) {
throw new InternalServerException(e.getMessage(), e);
}
}

}
Loading