Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<BrAPIObservationTableResponse> observationsTableGet(
@PathVariable("programId") UUID programId,
@QueryValue ObservationQuery queryParams) {

Optional<Program> program = programService.getById(programId);
if(program.isEmpty()) {
return HttpResponse.notFound();
}

try {
// Translate studyDbId if provided.
if (queryParams.getStudyDbId() != null) {
Optional<BrAPIStudy> 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<BrAPIObservationTableResponse> 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");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -260,18 +260,16 @@ public void testPutMultipleObsNotFound() {

@Test
@SneakyThrows
public void testGetObsTableNotFound() {
public void testGetObsTableOK() {
Flowable<HttpResponse<String>> getCall = client.exchange(
GET(String.format("/programs/%s/brapi/v2/observations/table",
program.getId().toString()))
.contentType(MediaType.APPLICATION_JSON)
.bearerAuth("test-registered-user"), String.class
);

HttpClientResponseException e = Assertions.assertThrows(HttpClientResponseException.class, () -> {
HttpResponse<String> response = getCall.blockingFirst();
});
assertEquals(HttpStatus.NOT_FOUND, e.getStatus());
HttpResponse<String> response = getCall.blockingFirst();
assertEquals(HttpStatus.OK, response.getStatus());
}

@Test
Expand Down