Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -4,12 +4,9 @@
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.breedinginsight.api.auth.ProgramSecured;
import org.breedinginsight.api.auth.ProgramSecuredRole;
import org.breedinginsight.api.auth.ProgramSecuredRoleGroup;
import org.breedinginsight.api.auth.SecurityService;
import org.breedinginsight.api.model.v1.request.SharedOntologyProgramRequest;
import org.breedinginsight.api.model.v1.response.DataResponse;
Expand All @@ -19,8 +16,8 @@
import org.breedinginsight.api.model.v1.response.metadata.Status;
import org.breedinginsight.api.model.v1.response.metadata.StatusCode;
import org.breedinginsight.api.v1.controller.metadata.AddMetadata;
import org.breedinginsight.model.SharedProgram;
import org.breedinginsight.model.Trait;
import org.breedinginsight.model.SharedOntology;
import org.breedinginsight.model.SubscribedOntology;
import org.breedinginsight.services.OntologyService;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.services.exceptions.UnprocessableEntityException;
Expand Down Expand Up @@ -67,15 +64,20 @@ public OntologyController(SecurityService securityService, OntologyService ontol
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<SharedProgram>>> getAvailablePrograms(
public HttpResponse<Response<DataResponse<SharedOntology>>> getAvailablePrograms(
@PathVariable UUID programId, @QueryValue(defaultValue = "false") Boolean shared) {
List<SharedProgram> sharedPrograms = ontologyService.getSharedOntology(programId, shared);
List<org.breedinginsight.api.model.v1.response.metadata.Status> metadataStatus = new ArrayList<>();
metadataStatus.add(new Status(StatusCode.INFO, "Successful Query"));
Pagination pagination = new Pagination(sharedPrograms.size(), 1, 1, 0);
Metadata metadata = new Metadata(pagination, metadataStatus);
Response<DataResponse<SharedProgram>> response = new Response(metadata, new DataResponse<>(sharedPrograms));
return HttpResponse.ok(response);
try {
List<SharedOntology> sharedOntologies = ontologyService.getSharedOntology(programId, shared);
List<Status> metadataStatus = new ArrayList<>();
metadataStatus.add(new Status(StatusCode.INFO, "Successful Query"));
Pagination pagination = new Pagination(sharedOntologies.size(), 1, 1, 0);
Metadata metadata = new Metadata(pagination, metadataStatus);
Response<DataResponse<SharedOntology>> response = new Response(metadata, new DataResponse<>(sharedOntologies));
return HttpResponse.ok(response);
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}

/**
Expand All @@ -94,22 +96,26 @@ public HttpResponse<Response<DataResponse<SharedProgram>>> getAvailablePrograms(
@Post("/programs/{programId}/ontology/shared/programs")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<SharedProgram>>> shareOntology(
public HttpResponse<Response<DataResponse<SharedOntology>>> shareOntology(
@PathVariable UUID programId, @Body List<SharedOntologyProgramRequest> request) {
try {
List<SharedProgram> sharedPrograms = ontologyService.shareOntology(programId, securityService.getUser(), request);
List<org.breedinginsight.api.model.v1.response.metadata.Status> metadataStatus = new ArrayList<>();
List<SharedOntology> sharedOntologies = ontologyService.shareOntology(programId, securityService.getUser(), request);
List<Status> metadataStatus = new ArrayList<>();
metadataStatus.add(new Status(StatusCode.INFO, "Successful Creation"));
Pagination pagination = new Pagination(sharedPrograms.size(), 1, 1, 0);
Pagination pagination = new Pagination(sharedOntologies.size(), 1, 1, 0);
Metadata metadata = new Metadata(pagination, metadataStatus);
Response<DataResponse<SharedProgram>> response = new Response(metadata, new DataResponse<>(sharedPrograms));
Response<DataResponse<SharedOntology>> response = new Response(metadata, new DataResponse<>(sharedOntologies));
return HttpResponse.ok(response);
} catch (ValidatorException e) {
log.error("Validation errors", e);
HttpResponse response = HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY).body(e.getErrors());
return response;
} catch (UnprocessableEntityException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}

Expand All @@ -124,14 +130,99 @@ public HttpResponse<Response<DataResponse<SharedProgram>>> shareOntology(
@Delete("/programs/{programId}/ontology/shared/programs/{sharedProgramId}")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<Trait>>> revokeOntology(
public HttpResponse revokeOntology(
@PathVariable UUID programId, @PathVariable UUID sharedProgramId) {
try {
ontologyService.revokeOntology(programId, sharedProgramId);
return HttpResponse.ok();
} catch (UnprocessableEntityException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}

/**
* Scoped under the program that is subscribing. Accept a shared ontology.
*
* @param programId -- Program that is subscribing to an ontology
* @param sharingProgramId -- Program that has shared its ontology.
* @return
*/
@Put("/programs/{programId}/ontology/subscribe/{sharingProgramId}")
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<SubscribedOntology>> subscribeOntology(
@PathVariable UUID programId, @PathVariable UUID sharingProgramId) {
try {
SubscribedOntology shareRequest = ontologyService.subscribeOntology(programId, sharingProgramId);
Response<SubscribedOntology> response = new Response(shareRequest);
return HttpResponse.ok(response);
} catch (UnprocessableEntityException e) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you add an error log statement, please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}

/**
* Scoped under the program that is subscribing. Unsubscribe from a shared ontology.
*
* @param programId -- Program that is unsubscribing from an ontology
* @param sharingProgramId -- Program that has shared its ontology.
* @return
*/
@Delete("/programs/{programId}/ontology/subscribe/{sharingProgramId}")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse unsubscribeOntology(
@PathVariable UUID programId, @PathVariable UUID sharingProgramId) {
try {
ontologyService.unsubscribeOntology(programId, sharingProgramId);
return HttpResponse.ok();
} catch (UnprocessableEntityException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
Copy link
Member

Choose a reason for hiding this comment

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

Can you add an error log statement, please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}

/**
* Retrieves subscription options for programs that have shared their ontology with the requesting program.
* Will indicate whether the program has subscribed to a given ontology or not.
*
* @param programId -- Program request information
* @return
* {
* programId, -- Program that owns the ontology the request program is subscribed to.
* programName,
* subscribed, -- boolean. Whether the requesting program is subscribed to this ontology or not.
* editable -- boolean || null. Indicates whether this program can unsubscribe from this ontology or not. Null if not subscribed to this ontology.
* }
*/
@Get("/programs/{programId}/ontology/subscribe")
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<SubscribedOntology>>> getSubscribedOntology(
@PathVariable UUID programId) {
try {
List<SubscribedOntology> shareRequests = ontologyService.getSubscribeOntologyOptions(programId);
List<Status> metadataStatus = new ArrayList<>();
metadataStatus.add(new Status(StatusCode.INFO, "Successful Creation"));
Pagination pagination = new Pagination(shareRequests.size(), 1, 1, 0);
Metadata metadata = new Metadata(pagination, metadataStatus);
Response<DataResponse<SubscribedOntology>> response = new Response(metadata, new DataResponse<>(shareRequests));
return HttpResponse.ok(response);
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/org/breedinginsight/daos/ObservationDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.brapi.v2.model.BrAPIWSMIMEDataTypes.APPLICATION_JSON;

Expand Down Expand Up @@ -77,6 +78,25 @@ public List<BrAPIObservation> getObservationsByVariableDbIds(List<String> observ

}

public List<BrAPIObservation> getObservationsByVariableAndBrAPIProgram(String brapiProgramId, List<String> observationVariableDbIds) {

try {
BrAPIObservationSearchRequest request = new BrAPIObservationSearchRequest()
.observationVariableDbIds(observationVariableDbIds)
.programDbIds(List.of(brapiProgramId));

ObservationsApi api = brAPIProvider.getObservationsAPI(BrAPIClientType.PHENO);
return BrAPIDAOUtil.search(
api::searchObservationsPost,
this::searchObservationsSearchResultsDbIdGet,
request
);
} catch (ApiException e) {
throw new InternalServerException("Observations brapi search error", e);
}

}

private ApiResponse<Pair<Optional<BrAPIObservationListResponse>, Optional<BrAPIAcceptedSearchResponse>>>
searchObservationsSearchResultsDbIdGet(String searchResultsDbId, Integer page, Integer pageSize) throws ApiException {
ObservationsApi api = brAPIProvider.getObservationsAPI(BrAPIClientType.PHENO);
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/org/breedinginsight/daos/ProgramOntologyDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,25 @@ public void revokeSharedOntology(ProgramSharedOntologyEntity sharedOntology) {
programSharedOntologyDao.delete(sharedOntology);
}

public boolean programSubscribedSharedOntology(UUID programId) {
List<ProgramSharedOntologyEntity> shareRecords = programSharedOntologyDao.fetchBySharedProgramId(programId);
return !shareRecords.stream()
public Optional<ProgramSharedOntologyEntity> getSubscribedSharedOntology(UUID programId) {
List<ProgramSharedOntologyEntity> shareRecords = programSharedOntologyDao.fetchBySharedProgramId(programId).stream()
.filter(shareRecord -> shareRecord.getActive())
.collect(Collectors.toList())
.isEmpty();
.collect(Collectors.toList());

return shareRecords.size() > 0 ? Optional.of(shareRecords.get(0)) : Optional.empty();
}

public void acceptSharedOntology(ProgramSharedOntologyEntity sharedOntology) {
sharedOntology.setActive(true);
programSharedOntologyDao.update(sharedOntology);
}

public void denySharedOntology(ProgramSharedOntologyEntity sharedOntology) {
sharedOntology.setActive(false);
programSharedOntologyDao.update(sharedOntology);
}

public List<ProgramSharedOntologyEntity> getSubscriptionOptions(UUID programId) {
return programSharedOntologyDao.fetchBySharedProgramId(programId);
}
}
22 changes: 21 additions & 1 deletion src/main/java/org/breedinginsight/daos/TraitDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,28 @@ public List<BrAPIObservation> getObservationsForTraits(List<UUID> traitIds) {
return observationDao.getObservationsByVariableDbIds(brapiVariableIds);
}

public List<BrAPIObservation> getObservationsForTraitsByBrAPIProgram(String brapiProgramId, List<UUID> traitIds) {

List<String> ids = traitIds.stream()
.map(trait -> trait.toString())
.collect(Collectors.toList());

List<BrAPIObservationVariable> variables = searchVariables(ids);

// TODO: make sure have all expected external references
if (variables.size() != ids.size()) {
throw new InternalServerException("Observation variables search results mismatch");
}

List<String> brapiVariableIds = variables.stream()
.map(variable -> variable.getObservationVariableDbId()).collect(Collectors.toList());

return observationDao.getObservationsByVariableAndBrAPIProgram(brapiProgramId, brapiVariableIds);
}

public List<BrAPIObservationVariable> searchVariables(List<String> variableIds) {

if (variableIds == null || variableIds.size() == 0) return new ArrayList<>();
try {
BrAPIObservationVariableSearchRequest request = new BrAPIObservationVariableSearchRequest()
.externalReferenceIDs(variableIds);
Expand Down Expand Up @@ -573,5 +594,4 @@ private void saturateTrait(Trait trait, BrAPIObservationVariable brApiVariable)
Scale scale = trait.getScale();
scale.setBrAPIProperties(brApiVariable.getScale());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SharedProgram {
public class SharedOntology {
private UUID programId;
private String programName;
private Boolean shared;
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/org/breedinginsight/model/SubscribedOntology.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.breedinginsight.model;

import lombok.*;

import java.util.UUID;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SubscribedOntology {
private UUID programId;
private String programName;
private Boolean subscribed;
private Boolean editable;
}
Loading