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
@@ -0,0 +1,20 @@
package org.breedinginsight.api.model.v1.request;

import io.micronaut.core.annotation.Introspected;
import lombok.*;

import javax.validation.constraints.NotBlank;
import java.util.UUID;

@Getter
@Setter
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Introspected
public class SharedOntologyProgramRequest {
@NotBlank
private UUID programId;
private String programName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package org.breedinginsight.api.v1.controller;

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.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;
import org.breedinginsight.api.model.v1.response.Response;
import org.breedinginsight.api.model.v1.response.metadata.Metadata;
import org.breedinginsight.api.model.v1.response.metadata.Pagination;
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.services.OntologyService;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.services.exceptions.UnprocessableEntityException;
import org.breedinginsight.services.exceptions.ValidatorException;

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

@Slf4j
@Controller("/${micronaut.bi.api.version}")
public class OntologyController {

private SecurityService securityService;
private OntologyService ontologyService;

@Inject
public OntologyController(SecurityService securityService, OntologyService ontologyService) {
this.securityService = securityService;
this.ontologyService = ontologyService;
}

/**
* Returns all available programs available to share programs ontology with. Includes programs
* currently being shared with and their editable (unshareable) status.
*
* @param programId
* @param shared
* @return
* {
* data: [
* {
* programName: string, -- Program name
* programId: UUID, -- Program ID
* shared: boolean,
* accepted: boolean || null, -- null if shared = false
* editable: boolean || null -- null if shared = false
* }
* ]
* }
*/
@Get("/programs/{programId}/ontology/shared/programs{?shared}")
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<SharedProgram>>> 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);
}

/**
* Accepts a list of programs to shared the ontology with.
* @param programId
* @return List of programs successfully shared to with acceptable status
* {
* data: [
* {
* programName: string, -- Program name
* programId: UUID, -- Required. Program ID
* }
* ]
* }
*/
@Post("/programs/{programId}/ontology/shared/programs")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<SharedProgram>>> 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<>();
metadataStatus.add(new Status(StatusCode.INFO, "Successful Creation"));
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);
} catch (ValidatorException e) {
log.error("Validation errors", e);
HttpResponse response = HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY).body(e.getErrors());
return response;
} catch (UnprocessableEntityException e) {
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
}
}

/**
* Revokes access to shared ontology from a program. If program is not currently shared with
* will return 404.
*
* @param programId
* @param sharedProgramId
* @return
*/
@Delete("/programs/{programId}/ontology/shared/programs/{sharedProgramId}")
@Produces(MediaType.APPLICATION_JSON)
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER})
public HttpResponse<Response<DataResponse<Trait>>> revokeOntology(
@PathVariable UUID programId, @PathVariable UUID sharedProgramId) {
try {
ontologyService.revokeOntology(programId, sharedProgramId);
return HttpResponse.ok();
} catch (UnprocessableEntityException e) {
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (DoesNotExistException e) {
return HttpResponse.status(HttpStatus.NOT_FOUND, e.getMessage());
}
}
}
7 changes: 2 additions & 5 deletions src/main/java/org/breedinginsight/daos/ProgramDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
import org.breedinginsight.dao.db.tables.BiUserTable;
import org.breedinginsight.dao.db.tables.daos.ProgramDao;
import org.breedinginsight.dao.db.tables.pojos.ProgramEntity;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.ProgramBrAPIEndpoints;
import org.breedinginsight.model.Species;
import org.breedinginsight.model.*;
import org.breedinginsight.model.User;
import org.breedinginsight.services.brapi.BrAPIClientProvider;
import org.breedinginsight.services.brapi.BrAPIClientType;
Expand Down Expand Up @@ -76,7 +74,7 @@ public class ProgramDAO extends ProgramDao {
private String referenceSource;
private Duration requestTimeout;

private final static String SYSTEM_DEFAULT = "System Default";
private final static String SYSTEM_DEFAULT = BrAPIConstants.SYSTEM_DEFAULT.getValue();

@Inject
public ProgramDAO(Configuration config, DSLContext dsl, BrAPIProvider brAPIProvider, BrAPIClientProvider brAPIClientProvider,
Expand Down Expand Up @@ -364,6 +362,5 @@ private Duration getRequestTimeout() {

return Duration.of(5, ChronoUnit.MINUTES);
}

}

39 changes: 38 additions & 1 deletion src/main/java/org/breedinginsight/daos/ProgramOntologyDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,55 @@
package org.breedinginsight.daos;

import org.breedinginsight.dao.db.tables.daos.ProgramOntologyDao;
import org.breedinginsight.dao.db.tables.daos.ProgramSharedOntologyDao;
import org.breedinginsight.dao.db.tables.pojos.ProgramSharedOntologyEntity;
import org.jooq.Configuration;
import org.jooq.DSLContext;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;

@Singleton
public class ProgramOntologyDAO extends ProgramOntologyDao {

private DSLContext dsl;
private ProgramSharedOntologyDao programSharedOntologyDao;

@Inject
public ProgramOntologyDAO(Configuration config, DSLContext dsl) {
public ProgramOntologyDAO(Configuration config, DSLContext dsl, ProgramSharedOntologyDao programSharedOntologyDao) {
super(config);
this.dsl = dsl;
this.programSharedOntologyDao = programSharedOntologyDao;
}

public void createSharedOntologies(List<ProgramSharedOntologyEntity> shareRecords) {
programSharedOntologyDao.insert(shareRecords);
}

public List<ProgramSharedOntologyEntity> getSharedOntologies(UUID programId) {
return programSharedOntologyDao.fetchByProgramId(programId);
}

public Optional<ProgramSharedOntologyEntity> getSharedOntologyById(UUID programId, UUID sharedProgramId) {
List<ProgramSharedOntologyEntity> sharedOntologies = getSharedOntologies(programId).stream()
.filter(programSharedOntologyEntity -> programSharedOntologyEntity.getSharedProgramId().equals(sharedProgramId))
.collect(Collectors.toList());
return sharedOntologies.size() > 0 ? Optional.of(sharedOntologies.get(0)) : Optional.empty();
}

public void revokeSharedOntology(ProgramSharedOntologyEntity sharedOntology) {
programSharedOntologyDao.delete(sharedOntology);
}

public boolean programSubscribedSharedOntology(UUID programId) {
List<ProgramSharedOntologyEntity> shareRecords = programSharedOntologyDao.fetchBySharedProgramId(programId);
return !shareRecords.stream()
.filter(shareRecord -> shareRecord.getActive())
.collect(Collectors.toList())
.isEmpty();
}
}
18 changes: 18 additions & 0 deletions src/main/java/org/breedinginsight/model/BrAPIConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.breedinginsight.model;

import com.fasterxml.jackson.annotation.JsonValue;

public enum BrAPIConstants {
SYSTEM_DEFAULT("System Default");

private String value;

BrAPIConstants(String value) {
this.value = value;
}

@JsonValue
public String getValue() {
return value;
}
}
31 changes: 18 additions & 13 deletions src/main/java/org/breedinginsight/model/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import lombok.experimental.SuperBuilder;
import org.brapi.v2.model.core.BrAPIProgram;
import org.brapi.v2.model.pheno.BrAPIObservationVariable;
import org.breedinginsight.dao.db.tables.ProgramTable;
import org.breedinginsight.dao.db.tables.pojos.ProgramEntity;
import org.breedinginsight.dao.db.tables.pojos.SpeciesEntity;
import org.jooq.Record;
Expand Down Expand Up @@ -65,22 +66,26 @@ public Program(ProgramEntity programEntity){
}

public static Program parseSQLRecord(Record record){
return parseSQLRecord(record, PROGRAM);
}

public static Program parseSQLRecord(Record record, ProgramTable programTable) {

// Generate our program record
Program program = Program.builder()
.id(record.getValue(PROGRAM.ID))
.name(record.getValue(PROGRAM.NAME))
.abbreviation(record.getValue(PROGRAM.ABBREVIATION))
.objective(record.getValue(PROGRAM.OBJECTIVE))
.documentationUrl(record.getValue(PROGRAM.DOCUMENTATION_URL))
.brapiUrl(record.getValue(PROGRAM.BRAPI_URL))
.key(record.getValue(PROGRAM.KEY))
.createdAt(record.getValue(PROGRAM.CREATED_AT))
.updatedAt(record.getValue(PROGRAM.UPDATED_AT))
.createdBy(record.getValue(PROGRAM.CREATED_BY))
.updatedBy(record.getValue(PROGRAM.UPDATED_BY))
.active(record.getValue(PROGRAM.ACTIVE))
.germplasmSequence(record.getValue(PROGRAM.GERMPLASM_SEQUENCE))
.id(record.getValue(programTable.ID))
.name(record.getValue(programTable.NAME))
.abbreviation(record.getValue(programTable.ABBREVIATION))
.objective(record.getValue(programTable.OBJECTIVE))
.documentationUrl(record.getValue(programTable.DOCUMENTATION_URL))
.brapiUrl(record.getValue(programTable.BRAPI_URL))
.key(record.getValue(programTable.KEY))
.createdAt(record.getValue(programTable.CREATED_AT))
.updatedAt(record.getValue(programTable.UPDATED_AT))
.createdBy(record.getValue(programTable.CREATED_BY))
.updatedBy(record.getValue(programTable.UPDATED_BY))
.active(record.getValue(programTable.ACTIVE))
.germplasmSequence(record.getValue(programTable.GERMPLASM_SEQUENCE))
.build();

return program;
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/breedinginsight/model/SharedProgram.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.breedinginsight.model;

import lombok.*;

import java.util.UUID;

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SharedProgram {
private UUID programId;
private String programName;
private Boolean shared;
private Boolean accepted;
private Boolean editable;
}
Loading