diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java index 5e70846ac..cbb476910 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIObservationsController.java @@ -19,26 +19,53 @@ import io.micronaut.http.HttpResponse; +import io.micronaut.http.HttpStatus; import io.micronaut.http.annotation.*; +import io.micronaut.http.server.exceptions.InternalServerException; import io.micronaut.security.annotation.Secured; import io.micronaut.security.rules.SecurityRule; import lombok.extern.slf4j.Slf4j; +import org.brapi.client.v2.ApiResponse; +import org.brapi.client.v2.model.exceptions.ApiException; +import org.brapi.client.v2.modules.phenotype.ObservationsApi; +import org.brapi.v2.model.BrAPIWSMIMEDataTypes; +import org.brapi.v2.model.core.BrAPIStudy; import org.brapi.v2.model.pheno.BrAPIObservation; +import org.brapi.v2.model.pheno.response.BrAPIObservationTableResponse; import org.breedinginsight.api.auth.ProgramSecured; import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; import org.breedinginsight.brapi.v1.controller.BrapiVersion; +import org.breedinginsight.brapi.v2.dao.BrAPIStudyDAO; +import org.breedinginsight.brapi.v2.model.request.query.ObservationQuery; +import org.breedinginsight.daos.ProgramDAO; +import org.breedinginsight.model.Program; +import org.breedinginsight.services.ProgramService; +import org.breedinginsight.services.brapi.BrAPIEndpointProvider; +import org.breedinginsight.utilities.Utilities; + import javax.annotation.Nullable; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import javax.inject.Inject; +import java.util.*; @Slf4j @Controller("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2) @Secured(SecurityRule.IS_AUTHENTICATED) public class BrAPIObservationsController { + private final ProgramService programService; + private final ProgramDAO programDAO; + private final BrAPIStudyDAO brAPIStudyDAO; + private final BrAPIEndpointProvider brAPIEndpointProvider; + + @Inject + public BrAPIObservationsController(ProgramService programService, ProgramDAO programDAO, ProgramDAO programDAO1, BrAPIStudyDAO brAPIStudyDAO, BrAPIEndpointProvider brAPIEndpointProvider) { + this.programService = programService; + this.programDAO = programDAO1; + this.brAPIStudyDAO = brAPIStudyDAO; + this.brAPIEndpointProvider = brAPIEndpointProvider; + } + @Get("/observations") @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) public HttpResponse observationsGet(@PathVariable("programId") UUID programId, @@ -109,30 +136,39 @@ public HttpResponse observationsPut(@PathVariable("programId") UUID programId, @ return HttpResponse.notFound(); } - @Get("/observations/table") + @Get("/observations/table{?queryParams*}") @Produces({"application/json", "text/csv", "text/tsv"}) @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.PROGRAM_SCOPED_ROLES}) - public HttpResponse observationsTableGet(@PathVariable("programId") UUID programId, - @Nullable @Header("Accept") String accept, - @Nullable @QueryValue("observationUnitDbId") String observationUnitDbId, - @Nullable @QueryValue("observationVariableDbId") String observationVariableDbId, - @Nullable @QueryValue("locationDbId") String locationDbId, - @Nullable @QueryValue("seasonDbId") String seasonDbId, - @Nullable @QueryValue("observationLevel") String observationLevel, - @Nullable @QueryValue("searchResultsDbId") String searchResultsDbId, - @Nullable @QueryValue("observationTimeStampRangeStart") Date observationTimeStampRangeStart, - @Nullable @QueryValue("observationTimeStampRangeEnd") Date observationTimeStampRangeEnd, - @Nullable @QueryValue("programDbId") String programDbId, - @Nullable @QueryValue("trialDbId") String trialDbId, - @Nullable @QueryValue("studyDbId") String studyDbId, - @Nullable @QueryValue("germplasmDbId") String germplasmDbId, - @Nullable @QueryValue("observationUnitLevelName") String observationUnitLevelName, - @Nullable @QueryValue("observationUnitLevelOrder") String observationUnitLevelOrder, - @Nullable @QueryValue("observationUnitLevelCode") String observationUnitLevelCode, - @Nullable @QueryValue("observationUnitLevelRelationshipName") String observationUnitLevelRelationshipName, - @Nullable @QueryValue("observationUnitLevelRelationshipOrder") String observationUnitLevelRelationshipOrder, - @Nullable @QueryValue("observationUnitLevelRelationshipCode") String observationUnitLevelRelationshipCode, - @Nullable @QueryValue("observationUnitLevelRelationshipDbId") String observationUnitLevelRelationshipDbId) { - return HttpResponse.notFound(); + public HttpResponse observationsTableGet( + @PathVariable("programId") UUID programId, + @QueryValue ObservationQuery queryParams) { + + Optional program = programService.getById(programId); + if(program.isEmpty()) { + return HttpResponse.notFound(); + } + + try { + // Translate studyDbId if provided. + if (queryParams.getStudyDbId() != null) { + Optional study = brAPIStudyDAO.getStudyByEnvironmentId(UUID.fromString(queryParams.getStudyDbId()), program.get()); + if (study.isEmpty()) { + return HttpResponse.notFound(); + } + queryParams.setStudyDbId(study.get().getStudyDbId()); + } + // TODO: Translate other DbIds if provided as well (but studyDbId is sufficient for Mr. Bean). + + ObservationsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationsApi.class); + ApiResponse response = api.observationsTableGet(BrAPIWSMIMEDataTypes.APPLICATION_JSON, queryParams.toBrAPIQueryParams()); + + return HttpResponse.ok(response.getBody()); + } catch (InternalServerException e) { + log.error(e.getMessage(), e); + return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving observations table"); + } catch (ApiException e) { + log.error(Utilities.generateApiExceptionLogMessage(e), e); + return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, "Error retrieving observations table"); + } } } diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java index f806f5a1b..be5046077 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java @@ -113,6 +113,7 @@ public BrAPIServerInfoResponse programServerinfo(@PathVariable("programId") UUID .setBase("variables").GET().addPath("{observationVariableDbId}").GET().withSearch() .setBase("observationunits").GET().addPath("{observationUnitDbId}").GET().setPath("table").GET().withSearch() .setBase("observations").GET().addPath("{observationDbId}").GET().setPath("table").GET().withSearch() + .setBase("observations").addPath("tables").GET() .setBase("observationlevels").GET().build() //GENOTYPING - TODO // .setBase("calls").GET().withSearch() diff --git a/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ObservationQuery.java b/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ObservationQuery.java new file mode 100644 index 000000000..95ef760a2 --- /dev/null +++ b/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ObservationQuery.java @@ -0,0 +1,70 @@ +package org.breedinginsight.brapi.v2.model.request.query; + +import io.micronaut.core.annotation.Introspected; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.brapi.client.v2.model.queryParams.phenotype.ObservationTableQueryParams; +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 java.util.ArrayList; +import java.util.List; + +@Getter +@Introspected +public class ObservationQuery extends BrapiQuery { + @Setter + private String observationUnitDbId; + @Setter + private String observationVariableDbId; + @Setter + private String locationDbId; + @Setter + private String seasonDbId; + private String observationLevel; + @Setter + private String searchResultsDbId; + private String observationTimeStampRangeStart; + private String observationTimeStampRangeEnd; + @Setter + private String programDbId; + @Setter + private String trialDbId; + @Setter + private String studyDbId; + @Setter + private String germplasmDbId; + private String observationUnitLevelName; + private String observationUnitLevelOrder; + private String observationUnitLevelCode; + private String observationUnitLevelRelationshipName; + private String observationUnitLevelRelationshipOrder; + private String observationUnitLevelRelationshipCode; + + public ObservationTableQueryParams toBrAPIQueryParams() { + return (ObservationTableQueryParams) new ObservationTableQueryParams() + .observationUnitDbId(observationUnitDbId) + .observationVariableDbId(observationVariableDbId) + .locationDbId(locationDbId) + .seasonDbId(seasonDbId) + .observationLevel(observationLevel) + .searchResultsDbId(searchResultsDbId) + .observationTimeStampRangeStart(observationTimeStampRangeStart) + .observationTimeStampRangeEnd(observationTimeStampRangeEnd) + .programDbId(programDbId) + .trialDbId(trialDbId) + .studyDbId(studyDbId) + .germplasmDbId(germplasmDbId) + .observationUnitLevelName(observationUnitLevelName) + .observationUnitLevelOrder(observationUnitLevelOrder) + .observationUnitLevelCode(observationUnitLevelCode) + .observationUnitLevelRelationshipName(observationUnitLevelRelationshipName) + .observationUnitLevelRelationshipOrder(observationUnitLevelRelationshipOrder) + .observationUnitLevelRelationshipCode(observationUnitLevelRelationshipCode) + .page(getPage()) + .pageSize(getPageSize()); + } + +} diff --git a/src/test/java/org/breedinginsight/brapi/v2/BrAPIObservationsControllerIntegrationTest.java b/src/test/java/org/breedinginsight/brapi/v2/BrAPIObservationsControllerIntegrationTest.java index be3f61e4f..b9ba07d43 100644 --- a/src/test/java/org/breedinginsight/brapi/v2/BrAPIObservationsControllerIntegrationTest.java +++ b/src/test/java/org/breedinginsight/brapi/v2/BrAPIObservationsControllerIntegrationTest.java @@ -260,7 +260,7 @@ public void testPutMultipleObsNotFound() { @Test @SneakyThrows - public void testGetObsTableNotFound() { + public void testGetObsTableOK() { Flowable> getCall = client.exchange( GET(String.format("/programs/%s/brapi/v2/observations/table", program.getId().toString())) @@ -268,10 +268,8 @@ public void testGetObsTableNotFound() { .bearerAuth("test-registered-user"), String.class ); - HttpClientResponseException e = Assertions.assertThrows(HttpClientResponseException.class, () -> { - HttpResponse response = getCall.blockingFirst(); - }); - assertEquals(HttpStatus.NOT_FOUND, e.getStatus()); + HttpResponse response = getCall.blockingFirst(); + assertEquals(HttpStatus.OK, response.getStatus()); } @Test