From b33f77ed36ee4d6c174dfab60fe1061ec3a0f152 Mon Sep 17 00:00:00 2001 From: timparsons Date: Fri, 28 Oct 2022 18:31:48 -0400 Subject: [PATCH 01/12] [BI-1651] - Introducing program defined breeding methods Also added ability for programs to enable/disable breeding methods defined at the system level --- .../controller/BreedingMethodController.java | 171 ++++++++++++++++++ .../daos/BreedingMethodDAO.java | 39 ++-- .../daos/impl/BreedingMethodDAOImpl.java | 148 +++++++++++++++ .../services/ProgramService.java | 8 +- ...1.0.8__create_program_breeding_methods.sql | 39 ++++ .../brapps/importer/GermplasmTemplateMap.java | 3 +- 6 files changed, 384 insertions(+), 24 deletions(-) create mode 100644 src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java create mode 100644 src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java create mode 100644 src/main/resources/db/migration/V1.0.8__create_program_breeding_methods.sql diff --git a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java new file mode 100644 index 000000000..2b545dff3 --- /dev/null +++ b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java @@ -0,0 +1,171 @@ +package org.breedinginsight.api.v1.controller; + +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +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.apache.commons.lang3.StringUtils; +import org.breedinginsight.api.auth.*; +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.dao.db.tables.pojos.BreedingMethodEntity; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; +import org.breedinginsight.daos.BreedingMethodDAO; +import org.breedinginsight.services.exceptions.BadRequestException; + +import javax.inject.Inject; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@Slf4j +@Controller("/${micronaut.bi.api.version}") +public class BreedingMethodController { + + private SecurityService securityService; + private BreedingMethodDAO breedingMethodDAO; + + @Inject + public BreedingMethodController(SecurityService securityService, BreedingMethodDAO breedingMethodDAO) { + this.securityService = securityService; + this.breedingMethodDAO = breedingMethodDAO; + } + + @Get("/breeding-methods") + @Produces(MediaType.APPLICATION_JSON) + @AddMetadata + @Secured(SecurityRule.IS_AUTHENTICATED) + public HttpResponse>> getSystemBreedingMethods() { + log.debug("fetching system breeding methods"); + + try { + AuthenticatedUser actingUser = securityService.getUser(); + + List breedingMethods = breedingMethodDAO.getSystemBreedingMethods(); + return buildResponse(breedingMethods); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new InternalServerException("Error fetching system breeding methods", e); + } + } + + @Post("programs/{programId}/breeding-methods") + @Produces(MediaType.APPLICATION_JSON) + @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) + public HttpResponse> createProgramBreedingMethod(@PathVariable UUID programId, @Body ProgramBreedingMethodEntity breedingMethod) throws BadRequestException { + log.debug("Saving new program breeding method"); + + try { + AuthenticatedUser user = securityService.getUser(); + if(!validateBreedingMethod(breedingMethod)) { + throw new BadRequestException("Missing required data"); + } + Response response = new Response<>(); + response.result = breedingMethodDAO.createProgramMethod(breedingMethod, programId, user.getId()); + + List metadataStatus = new ArrayList<>(); + metadataStatus.add(new Status(StatusCode.INFO, "Successful Creation")); + Pagination pagination = new Pagination(1, 1, 1, 0); + Metadata metadata = new Metadata(pagination, metadataStatus); + response.metadata = metadata; + + return HttpResponse.ok(response); + } catch (Exception e) { + log.error("Error creating program breeding method", e); + throw e; + } + } + + @Get("programs/{programId}/breeding-methods") + @Produces(MediaType.APPLICATION_JSON) + @AddMetadata + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + public HttpResponse>> getProgramBreedingMethods(@PathVariable UUID programId) { + log.debug(String.format("fetching breeding methods for program: %s", programId)); + + try { + AuthenticatedUser actingUser = securityService.getUser(); + + List breedingMethods = breedingMethodDAO.getProgramBreedingMethods(programId); + return buildResponse(breedingMethods); +// } catch (DoesNotExistException e) { +// log.info(e.getMessage(), e); +// return HttpResponse.notFound(); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new InternalServerException("Error fetching breeding methods", e); + } + } + + @Put("programs/{programId}/breeding-methods/{breedingMethodId}") + @Produces(MediaType.APPLICATION_JSON) + @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) + public HttpResponse> updateProgramBreedingMethod(@PathVariable UUID programId, @PathVariable UUID breedingMethodId, @Body ProgramBreedingMethodEntity breedingMethod) throws BadRequestException { + log.debug("Saving new program breeding method"); + + try { + AuthenticatedUser user = securityService.getUser(); + + if(!validateBreedingMethod(breedingMethod)) { + throw new BadRequestException("Missing required data"); + } + breedingMethod.setId(breedingMethodId); + + Response response = new Response<>(); + response.result = breedingMethodDAO.updateProgramMethod(breedingMethod, programId, user.getId()); + + List metadataStatus = new ArrayList<>(); + metadataStatus.add(new Status(StatusCode.INFO, "Successful Update")); + Pagination pagination = new Pagination(1, 1, 1, 0); + Metadata metadata = new Metadata(pagination, metadataStatus); + response.metadata = metadata; + + return HttpResponse.ok(response); + } catch (Exception e) { + log.error("Error updating program breeding method", e); + throw e; + } + } + + @Put("programs/{programId}/breeding-methods/enable") + @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) + public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @Body List systemBreedingMethodIds) { + log.debug("enabling system breeding methods for program: "+programId); + + try { + AuthenticatedUser user = securityService.getUser(); + + breedingMethodDAO.enableSystemMethods(systemBreedingMethodIds, programId, user.getId()); + return HttpResponse.ok(); + } catch (Exception e) { + log.error("Error enabling system breeding methods for program: "+programId, e); + throw e; + } + } + + private boolean validateBreedingMethod(ProgramBreedingMethodEntity method) { + return StringUtils.isNotBlank(method.getName()) + && StringUtils.isNotBlank(method.getAbbreviation()) + && StringUtils.isNotBlank(method.getCategory()) + && StringUtils.isNotBlank(method.getGeneticDiversity()); + } + + private HttpResponse>> buildResponse(List breedingMethods) { + List metadataStatus = new ArrayList<>(); + metadataStatus.add(new Status(StatusCode.INFO, "Successful Query")); + Pagination pagination = new Pagination(breedingMethods.size(), breedingMethods.size(), 1, 0); + Metadata metadata = new Metadata(pagination, metadataStatus); + Response> response = new Response<>(metadata, new DataResponse<>(breedingMethods)); + return HttpResponse.ok(response); + } +} diff --git a/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java b/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java index c0a5118c7..d5cd4e9d5 100644 --- a/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java +++ b/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java @@ -1,31 +1,26 @@ package org.breedinginsight.daos; -import org.breedinginsight.dao.db.tables.daos.BreedingMethodDao; import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; -import org.jooq.Configuration; -import org.jooq.DSLContext; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; -import javax.inject.Inject; import javax.inject.Singleton; import java.util.List; - -import static org.breedinginsight.dao.db.tables.BreedingMethodTable.BREEDING_METHOD; +import java.util.UUID; @Singleton -public class BreedingMethodDAO extends BreedingMethodDao { - - private DSLContext dsl; - - @Inject - public BreedingMethodDAO(Configuration config, DSLContext dsl) { - super(config); - this.dsl = dsl; - } - - public List findByNameOrAbbreviation(String nameOrAbbrev) { - return dsl.select().from(BREEDING_METHOD) - .where(BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) - .or(BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) - .fetchInto(BreedingMethodEntity.class); - } +public interface BreedingMethodDAO { + + List getProgramBreedingMethods(UUID programId); + + List getSystemBreedingMethods(); + + List findByNameOrAbbreviation(String nameOrAbbrev, UUID programId); + + void enableAllSystemMethods(UUID programId, UUID userId); + + void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId); + + ProgramBreedingMethodEntity createProgramMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID id); + + ProgramBreedingMethodEntity updateProgramMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID id); } diff --git a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java new file mode 100644 index 000000000..cfe864163 --- /dev/null +++ b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java @@ -0,0 +1,148 @@ +package org.breedinginsight.daos.impl; + +import org.breedinginsight.dao.db.tables.daos.BreedingMethodDao; +import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; +import org.breedinginsight.daos.BreedingMethodDAO; +import org.jooq.Configuration; +import org.jooq.DSLContext; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.breedinginsight.dao.db.Tables.PROGRAM_BREEDING_METHOD; +import static org.breedinginsight.dao.db.Tables.PROGRAM_ENABLED_BREEDING_METHODS; +import static org.breedinginsight.dao.db.tables.BreedingMethodTable.BREEDING_METHOD; + +@Singleton +public class BreedingMethodDAOImpl extends BreedingMethodDao implements BreedingMethodDAO{ + + private DSLContext dsl; + + @Inject + public BreedingMethodDAOImpl(Configuration config, DSLContext dsl) { + super(config); + this.dsl = dsl; + } + + @Override + public List getProgramBreedingMethods(UUID programId) { + List breedingMethodEntities = dsl.select(BREEDING_METHOD.fields()) + .from(BREEDING_METHOD) + .join(PROGRAM_ENABLED_BREEDING_METHODS) + .on(PROGRAM_ENABLED_BREEDING_METHODS.BREEDING_METHOD_ID.eq(BREEDING_METHOD.ID)) + .where(PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID.eq(programId)) + .fetchInto(ProgramBreedingMethodEntity.class); + + List programBreedingMethodEntities = dsl.select(PROGRAM_BREEDING_METHOD.fields()) + .from(PROGRAM_BREEDING_METHOD) + .where(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)) + .fetchInto(ProgramBreedingMethodEntity.class); + + List ret = new ArrayList<>(); + if(!breedingMethodEntities.isEmpty()) { + ret.addAll(breedingMethodEntities); + } + if(!programBreedingMethodEntities.isEmpty()) { + ret.addAll(programBreedingMethodEntities); + } + return ret; + } + + @Override + public List getSystemBreedingMethods() { + return dsl.select(BREEDING_METHOD.fields()) + .from(BREEDING_METHOD) + .fetchInto(ProgramBreedingMethodEntity.class); + } + + public List findByNameOrAbbreviation(String nameOrAbbrev, UUID programId) { + List breedingMethodEntities = dsl.select() + .from(BREEDING_METHOD) + .join(PROGRAM_ENABLED_BREEDING_METHODS) + .on(PROGRAM_ENABLED_BREEDING_METHODS.BREEDING_METHOD_ID.eq(BREEDING_METHOD.ID)) + .where(PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID.eq(programId)) + .and(BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) + .or(BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) + .fetchInto(ProgramBreedingMethodEntity.class); + + List programBreedingMethodEntities = dsl.select() + .from(PROGRAM_BREEDING_METHOD) + .where(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)) + .and(PROGRAM_BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) + .or(PROGRAM_BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) + .fetchInto(ProgramBreedingMethodEntity.class); + + List ret = new ArrayList<>(); + if(!breedingMethodEntities.isEmpty()) { + ret.addAll(breedingMethodEntities); + } + if(!programBreedingMethodEntities.isEmpty()) { + ret.addAll(programBreedingMethodEntities); + } + return ret; + } + + @Override + public void enableAllSystemMethods(UUID programId, UUID userId) { + dsl.execute("insert into program_enabled_breeding_methods(breeding_method_id, program_id, created_by, created_at, updated_by, updated_at)\n" + + "select breeding_method.id, ?, ?, now(), ?, now() from breeding_method", programId, userId, userId); + } + + @Override + public void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) { + dsl.transaction(() -> { + dsl.deleteFrom(PROGRAM_ENABLED_BREEDING_METHODS).where(PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID.eq(programId)).execute(); + + for(UUID methodId : systemBreedingMethods) { + dsl.insertInto(PROGRAM_ENABLED_BREEDING_METHODS) + .columns(PROGRAM_ENABLED_BREEDING_METHODS.BREEDING_METHOD_ID, + PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID, + PROGRAM_ENABLED_BREEDING_METHODS.CREATED_BY, + PROGRAM_ENABLED_BREEDING_METHODS.CREATED_AT, + PROGRAM_ENABLED_BREEDING_METHODS.UPDATED_BY, + PROGRAM_ENABLED_BREEDING_METHODS.UPDATED_AT) + .values(methodId, programId, userId, OffsetDateTime.now(), userId, OffsetDateTime.now()) + .execute(); + } + }); + } + + @Override + public ProgramBreedingMethodEntity createProgramMethod(ProgramBreedingMethodEntity method, UUID programId, UUID userId) { + return dsl.insertInto(PROGRAM_BREEDING_METHOD) + .columns(PROGRAM_BREEDING_METHOD.NAME, + PROGRAM_BREEDING_METHOD.ABBREVIATION, + PROGRAM_BREEDING_METHOD.DESCRIPTION, + PROGRAM_BREEDING_METHOD.CATEGORY, + PROGRAM_BREEDING_METHOD.GENETIC_DIVERSITY, + PROGRAM_BREEDING_METHOD.PROGRAM_ID, + PROGRAM_BREEDING_METHOD.CREATED_BY, + PROGRAM_BREEDING_METHOD.CREATED_AT, + PROGRAM_BREEDING_METHOD.UPDATED_BY, + PROGRAM_BREEDING_METHOD.UPDATED_AT) + .values(method.getName(), method.getAbbreviation(), method.getDescription(), method.getCategory(), method.getGeneticDiversity(), programId, userId, OffsetDateTime.now(), userId, OffsetDateTime.now()) + .returning(PROGRAM_BREEDING_METHOD.fields()) + .fetchOneInto(ProgramBreedingMethodEntity.class); + } + + @Override + public ProgramBreedingMethodEntity updateProgramMethod(ProgramBreedingMethodEntity method, UUID programId, UUID userId) { + return dsl.update(PROGRAM_BREEDING_METHOD) + .set(PROGRAM_BREEDING_METHOD.NAME, method.getName()) + .set(PROGRAM_BREEDING_METHOD.ABBREVIATION, method.getAbbreviation()) + .set(PROGRAM_BREEDING_METHOD.DESCRIPTION, method.getDescription()) + .set(PROGRAM_BREEDING_METHOD.CATEGORY, method.getCategory()) + .set(PROGRAM_BREEDING_METHOD.GENETIC_DIVERSITY, method.getGeneticDiversity()) + .set(PROGRAM_BREEDING_METHOD.UPDATED_BY, userId) + .set(PROGRAM_BREEDING_METHOD.UPDATED_AT, OffsetDateTime.now()) + .where(PROGRAM_BREEDING_METHOD.ID.eq(method.getId())) + .returning(PROGRAM_BREEDING_METHOD.fields()) + .fetchOneInto(ProgramBreedingMethodEntity.class); + } +} diff --git a/src/main/java/org/breedinginsight/services/ProgramService.java b/src/main/java/org/breedinginsight/services/ProgramService.java index c933235ae..6a4e52238 100644 --- a/src/main/java/org/breedinginsight/services/ProgramService.java +++ b/src/main/java/org/breedinginsight/services/ProgramService.java @@ -25,6 +25,7 @@ import org.breedinginsight.api.model.v1.request.ProgramRequest; import org.breedinginsight.dao.db.tables.pojos.*; import org.breedinginsight.api.model.v1.request.SpeciesRequest; +import org.breedinginsight.daos.BreedingMethodDAO; import org.breedinginsight.daos.ProgramDAO; import org.breedinginsight.daos.ProgramObservationLevelDAO; import org.breedinginsight.daos.ProgramOntologyDAO; @@ -55,6 +56,7 @@ public class ProgramService { private DSLContext dsl; private SecurityService securityService; private BrAPIClientProvider brAPIClientProvider; + private BreedingMethodDAO breedingMethodDAO; private static final String PROGRAM_NAME_IN_USE = "PROGRAM_NAME_IN_USE"; private static final String PROGRAM_KEY_IN_USE = "PROGRAM_KEY_IN_USE"; @@ -66,7 +68,8 @@ public class ProgramService { @Inject public ProgramService(ProgramDAO dao, ProgramOntologyDAO programOntologyDAO, ProgramObservationLevelDAO programObservationLevelDAO, - SpeciesService speciesService, DSLContext dsl, SecurityService securityService, BrAPIClientProvider brAPIClientProvider) { + SpeciesService speciesService, DSLContext dsl, SecurityService securityService, BrAPIClientProvider brAPIClientProvider, + BreedingMethodDAO breedingMethodDAO) { this.dao = dao; this.programOntologyDAO = programOntologyDAO; this.programObservationLevelDAO = programObservationLevelDAO; @@ -74,6 +77,7 @@ public ProgramService(ProgramDAO dao, ProgramOntologyDAO programOntologyDAO, Pro this.dsl = dsl; this.securityService = securityService; this.brAPIClientProvider = brAPIClientProvider; + this.breedingMethodDAO = breedingMethodDAO; } public Optional getById(UUID programId) { @@ -193,6 +197,8 @@ public Program create(ProgramRequest programRequest, AuthenticatedUser actingUse .build(); programOntologyDAO.insert(programOntologyEntity); + breedingMethodDAO.enableAllSystemMethods(createdProgram.getId(), actingUser.getId()); + // Add program to brapi service dao.createProgramBrAPI(createdProgram); diff --git a/src/main/resources/db/migration/V1.0.8__create_program_breeding_methods.sql b/src/main/resources/db/migration/V1.0.8__create_program_breeding_methods.sql new file mode 100644 index 000000000..1637517e5 --- /dev/null +++ b/src/main/resources/db/migration/V1.0.8__create_program_breeding_methods.sql @@ -0,0 +1,39 @@ +/* + * 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. + */ + +create table program_breeding_method +( + like base_entity INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES, + name TEXT, + abbreviation TEXT, + description TEXT, + category TEXT, + genetic_diversity TEXT, + program_id uuid not null references program (id), + like base_edit_track_entity INCLUDING ALL +); + +create table program_enabled_breeding_methods +( + like base_entity INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES, + breeding_method_id uuid not null references breeding_method (id), + program_id uuid not null references program (id), + like base_edit_track_entity INCLUDING ALL +); + +insert into program_enabled_breeding_methods(breeding_method_id, program_id, created_by, created_at, updated_by, updated_at) +select breeding_method.id, program.id, (select id from bi_user where name = 'system'), now(), (select id from bi_user where name = 'system'), now() from breeding_method, program; \ No newline at end of file diff --git a/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java b/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java index e46ce1c28..c5bedc0f4 100644 --- a/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java +++ b/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java @@ -25,6 +25,7 @@ import org.breedinginsight.brapps.importer.services.processors.GermplasmProcessor; import org.breedinginsight.dao.db.tables.pojos.BiUserEntity; import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.daos.BreedingMethodDAO; import org.breedinginsight.daos.UserDAO; import org.breedinginsight.model.Program; @@ -745,7 +746,7 @@ public void checkBasicResponse(JsonObject germplasm, Table fileData, Integer i) assertEquals(testUser.getName(), additionalInfo.getAsJsonObject("createdBy").get("userName").getAsString(), "Wrong createdBy userId"); // Breeding Method String breedingMethodName = fileData.getString(i, "Breeding Method"); - BreedingMethodEntity breedingMethod = breedingMethodDAO.findByNameOrAbbreviation(breedingMethodName).get(0); + ProgramBreedingMethodEntity breedingMethod = breedingMethodDAO.findByNameOrAbbreviation(breedingMethodName, validProgram.getId()).get(0); assertEquals(breedingMethod.getId().toString(), additionalInfo.get("breedingMethodId").getAsString(), "Wrong Breeding Method ID"); assertEquals(breedingMethod.getName(), additionalInfo.get("breedingMethod").getAsString(), "Wrong Breeding Method name"); // Seed source From 72c015187d3c1d999220dc68efef84d4bf783987 Mon Sep 17 00:00:00 2001 From: timparsons Date: Tue, 1 Nov 2022 13:46:21 -0400 Subject: [PATCH 02/12] [BI-1651] - cleanup --- .../brapps/importer/model/base/Germplasm.java | 20 +++++----- .../processors/GermplasmProcessor.java | 40 +++++++++---------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java b/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java index c8c323619..3cafdf87c 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java +++ b/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java @@ -27,7 +27,7 @@ import org.brapi.v2.model.germ.BrAPIGermplasmSynonyms; import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields; import org.breedinginsight.brapps.importer.model.config.*; -import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.model.Program; import org.breedinginsight.model.User; import org.breedinginsight.utilities.Utilities; @@ -143,7 +143,7 @@ public static String constructGermplasmListName(String listName, Program program return String.format("%s [%s-germplasm]", listName, program.getKey()); } - public BrAPIGermplasm constructBrAPIGermplasm(BreedingMethodEntity breedingMethod, User user) { + public BrAPIGermplasm constructBrAPIGermplasm(ProgramBreedingMethodEntity breedingMethod, User user) { BrAPIGermplasm germplasm = new BrAPIGermplasm(); germplasm.setGermplasmName(getGermplasmName()); germplasm.setDefaultDisplayName(getGermplasmName()); @@ -163,8 +163,8 @@ public BrAPIGermplasm constructBrAPIGermplasm(BreedingMethodEntity breedingMetho germplasm.setCountryOfOriginCode(getCountryOfOrigin()); if (additionalInfos != null) { additionalInfos.stream() - .filter(additionalInfo -> additionalInfo.getAdditionalInfoValue() != null) - .forEach(additionalInfo -> germplasm.putAdditionalInfoItem(additionalInfo.getAdditionalInfoName(), additionalInfo.getAdditionalInfoValue())); + .filter(additionalInfo -> additionalInfo.getAdditionalInfoValue() != null) + .forEach(additionalInfo -> germplasm.putAdditionalInfoItem(additionalInfo.getAdditionalInfoName(), additionalInfo.getAdditionalInfoValue())); } // Seed Source @@ -183,8 +183,8 @@ public BrAPIGermplasm constructBrAPIGermplasm(BreedingMethodEntity breedingMetho germplasm.externalReferences(new ArrayList<>()); if (externalReferences != null) { List brAPIExternalReferences = externalReferences.stream() - .map(externalReference -> externalReference.constructBrAPIExternalReference()) - .collect(Collectors.toList()); + .map(externalReference -> externalReference.constructBrAPIExternalReference()) + .collect(Collectors.toList()); if (uidExternalReference != null) { brAPIExternalReferences.add(uidExternalReference); } @@ -203,9 +203,9 @@ public BrAPIGermplasm constructBrAPIGermplasm(BreedingMethodEntity breedingMetho List brapiSynonyms = new ArrayList<>(); if (synonyms != null) { List synonyms = Arrays.asList(blobSynonyms.split(";")).stream() - .map(synonym -> synonym.strip()) - .distinct() - .collect(Collectors.toList()); + .map(synonym -> synonym.strip()) + .distinct() + .collect(Collectors.toList()); // Create synonym for (String synonym: synonyms) { BrAPIGermplasmSynonyms brapiSynonym = new BrAPIGermplasmSynonyms(); @@ -246,7 +246,7 @@ private void setBrAPIGermplasmCommitFields(BrAPIGermplasm germplasm, String prog } } - public BrAPIGermplasm constructBrAPIGermplasm(Program program, BreedingMethodEntity breedingMethod, User user, boolean commit, String referenceSource, Supplier nextVal) { + public BrAPIGermplasm constructBrAPIGermplasm(Program program, ProgramBreedingMethodEntity breedingMethod, User user, boolean commit, String referenceSource, Supplier nextVal) { BrAPIGermplasm germplasm = constructBrAPIGermplasm(breedingMethod, user); if (commit) { setBrAPIGermplasmCommitFields(germplasm, program.getKey(), referenceSource, nextVal); diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java index 40ed50ed4..18388251e 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/GermplasmProcessor.java @@ -38,7 +38,7 @@ import org.breedinginsight.brapps.importer.model.response.ImportObjectState; import org.breedinginsight.brapps.importer.model.response.ImportPreviewStatistics; import org.breedinginsight.brapps.importer.model.response.PendingImportObject; -import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.daos.BreedingMethodDAO; import org.breedinginsight.model.Program; import org.breedinginsight.model.User; @@ -132,8 +132,8 @@ public void getExistingBrapiData(List importRows, Program program) try { existingParentGermplasms = brAPIGermplasmService.getRawGermplasmByAccessionNumber(new ArrayList<>(germplasmDBIDs), program.getId()); List existingDbIds = existingParentGermplasms.stream() - .map(germplasm -> germplasm.getAccessionNumber()) - .collect(Collectors.toList()); + .map(germplasm -> germplasm.getAccessionNumber()) + .collect(Collectors.toList()); missingDbIds.removeAll(existingDbIds); existingParentGermplasms.forEach(existingGermplasm -> { @@ -174,8 +174,8 @@ public void getExistingBrapiData(List importRows, Program program) // Parent reference checks if (missingDbIds.size() > 0) { throw new HttpStatusException(HttpStatus.UNPROCESSABLE_ENTITY, - String.format(missingParentalDbIdsMsg, - arrayOfStringFormatter.apply(missingDbIds))); + String.format(missingParentalDbIdsMsg, + arrayOfStringFormatter.apply(missingDbIds))); } List missingEntryNumbers = new ArrayList<>(); @@ -196,8 +196,8 @@ public void getExistingBrapiData(List importRows, Program program) } if (missingEntryNumbers.size() > 0) { throw new HttpStatusException(HttpStatus.UNPROCESSABLE_ENTITY, - String.format(missingParentalEntryNoMsg, - arrayOfStringFormatter.apply(missingEntryNumbers))); + String.format(missingParentalEntryNoMsg, + arrayOfStringFormatter.apply(missingEntryNumbers))); } if (listNameDup) { @@ -228,7 +228,7 @@ public Map process(List importRows // All rows are considered new germplasm, we don't check for duplicates newGermplasmList = new ArrayList<>(); - Map breedingMethods = new HashMap<>(); + Map breedingMethods = new HashMap<>(); Boolean nullEntryNotFound = false; List badBreedingMethods = new ArrayList<>(); Map entryNumberCounts = new HashMap<>(); @@ -244,12 +244,12 @@ public Map process(List importRows if (germplasm != null && germplasm.getGermplasmName() != null) { // Get the breeding method database object - BreedingMethodEntity breedingMethod = null; + ProgramBreedingMethodEntity breedingMethod = null; if (germplasm.getBreedingMethod() != null) { if (breedingMethods.containsKey(germplasm.getBreedingMethod())) { breedingMethod = breedingMethods.get(germplasm.getBreedingMethod()); } else { - List breedingMethodResults = breedingMethodDAO.findByNameOrAbbreviation(germplasm.getBreedingMethod()); + List breedingMethodResults = breedingMethodDAO.findByNameOrAbbreviation(germplasm.getBreedingMethod(), program.getId()); if (breedingMethodResults.size() > 0) { breedingMethods.put(germplasm.getBreedingMethod(), breedingMethodResults.get(0)); breedingMethod = breedingMethods.get(germplasm.getBreedingMethod()); @@ -271,7 +271,7 @@ public Map process(List importRows userProvidedEntryNumbers.add(germplasm.getEntryNo()); } entryNumberCounts.put(germplasm.getEntryNo(), - entryNumberCounts.containsKey(germplasm.getEntryNo()) ? entryNumberCounts.get(germplasm.getEntryNo()) + 1 : 1); + entryNumberCounts.containsKey(germplasm.getEntryNo()) ? entryNumberCounts.get(germplasm.getEntryNo()) + 1 : 1); BrAPIGermplasm newGermplasm = germplasm.constructBrAPIGermplasm(program, breedingMethod, user, commit, BRAPI_REFERENCE_SOURCE, nextVal); @@ -301,10 +301,10 @@ public Map process(List importRows // Check for duplicate entry numbers if (entryNumberCounts.size() < importRows.size()) { List dups = entryNumberCounts.keySet().stream() - .filter(key -> entryNumberCounts.get(key) > 1) - .collect(Collectors.toList()); + .filter(key -> entryNumberCounts.get(key) > 1) + .collect(Collectors.toList()); throw new HttpStatusException(HttpStatus.UNPROCESSABLE_ENTITY, - String.format(duplicateEntryNoMsg, arrayOfStringFormatter.apply(dups))); + String.format(duplicateEntryNoMsg, arrayOfStringFormatter.apply(dups))); } // Construct pedigree @@ -317,16 +317,16 @@ public Map process(List importRows // Construct our response object ImportPreviewStatistics germplasmStats = ImportPreviewStatistics.builder() - .newObjectCount(newGermplasmList.size()) - .build(); + .newObjectCount(newGermplasmList.size()) + .build(); //Modified logic here to check for female parent dbid or entry no, removed check for male due to assumption that shouldn't have only male parent int newObjectCount = newGermplasmList.stream().filter(newGermplasm -> newGermplasm != null).collect(Collectors.toList()).size(); ImportPreviewStatistics pedigreeConnectStats = ImportPreviewStatistics.builder() - .newObjectCount(importRows.stream().filter(germplasmImport -> - germplasmImport.getGermplasm() != null && - (germplasmImport.getGermplasm().getFemaleParentDBID() != null || germplasmImport.getGermplasm().getFemaleParentEntryNo() != null) - ).collect(Collectors.toList()).size()).build(); + .newObjectCount(importRows.stream().filter(germplasmImport -> + germplasmImport.getGermplasm() != null && + (germplasmImport.getGermplasm().getFemaleParentDBID() != null || germplasmImport.getGermplasm().getFemaleParentEntryNo() != null) + ).collect(Collectors.toList()).size()).build(); return Map.of( "Germplasm", germplasmStats, From 3db629b21015d34566a520da253473c1d2ef13e5 Mon Sep 17 00:00:00 2001 From: timparsons Date: Tue, 22 Nov 2022 10:25:42 -0500 Subject: [PATCH 03/12] [BI-1651] Preventing editing of breeding methods in use by a germplasm --- .../controller/BreedingMethodController.java | 52 ++++----- .../daos/impl/BreedingMethodDAOImpl.java | 56 +++++----- .../services/BreedingMethodService.java | 23 ++++ .../impl/BreedingMethodServiceImpl.java | 101 ++++++++++++++++++ ....0.9__create_program_breeding_methods.sql} | 0 .../impl/BreedingMethodServiceImplTest.java | 5 + 6 files changed, 178 insertions(+), 59 deletions(-) create mode 100644 src/main/java/org/breedinginsight/services/BreedingMethodService.java create mode 100644 src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java rename src/main/resources/db/migration/{V1.0.8__create_program_breeding_methods.sql => V1.0.9__create_program_breeding_methods.sql} (100%) create mode 100644 src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java diff --git a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java index 2b545dff3..3ef87ef63 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java @@ -8,6 +8,7 @@ import io.micronaut.security.rules.SecurityRule; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.brapi.client.v2.model.exceptions.ApiException; import org.breedinginsight.api.auth.*; import org.breedinginsight.api.model.v1.response.DataResponse; import org.breedinginsight.api.model.v1.response.Response; @@ -19,6 +20,7 @@ import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.daos.BreedingMethodDAO; +import org.breedinginsight.services.BreedingMethodService; import org.breedinginsight.services.exceptions.BadRequestException; import javax.inject.Inject; @@ -32,13 +34,13 @@ @Controller("/${micronaut.bi.api.version}") public class BreedingMethodController { - private SecurityService securityService; - private BreedingMethodDAO breedingMethodDAO; + private final SecurityService securityService; + private final BreedingMethodService breedingMethodService; @Inject - public BreedingMethodController(SecurityService securityService, BreedingMethodDAO breedingMethodDAO) { + public BreedingMethodController(SecurityService securityService, BreedingMethodService breedingMethodService) { this.securityService = securityService; - this.breedingMethodDAO = breedingMethodDAO; + this.breedingMethodService = breedingMethodService; } @Get("/breeding-methods") @@ -51,7 +53,7 @@ public HttpResponse>> getSyst try { AuthenticatedUser actingUser = securityService.getUser(); - List breedingMethods = breedingMethodDAO.getSystemBreedingMethods(); + List breedingMethods = breedingMethodService.getSystemBreedingMethods(); return buildResponse(breedingMethods); } catch (Exception e) { log.error(e.getMessage(), e); @@ -62,16 +64,13 @@ public HttpResponse>> getSyst @Post("programs/{programId}/breeding-methods") @Produces(MediaType.APPLICATION_JSON) @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) - public HttpResponse> createProgramBreedingMethod(@PathVariable UUID programId, @Body ProgramBreedingMethodEntity breedingMethod) throws BadRequestException { + public HttpResponse> createProgramBreedingMethod(@PathVariable UUID programId, @Body ProgramBreedingMethodEntity breedingMethod) throws BadRequestException, ApiException { log.debug("Saving new program breeding method"); try { AuthenticatedUser user = securityService.getUser(); - if(!validateBreedingMethod(breedingMethod)) { - throw new BadRequestException("Missing required data"); - } Response response = new Response<>(); - response.result = breedingMethodDAO.createProgramMethod(breedingMethod, programId, user.getId()); + response.result = breedingMethodService.createBreedingMethod(breedingMethod, programId, user.getId()); List metadataStatus = new ArrayList<>(); metadataStatus.add(new Status(StatusCode.INFO, "Successful Creation")); @@ -86,21 +85,22 @@ public HttpResponse> createProgramBreeding } } - @Get("programs/{programId}/breeding-methods") + @Get("programs/{programId}/breeding-methods{?inUse}") @Produces(MediaType.APPLICATION_JSON) @AddMetadata @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) - public HttpResponse>> getProgramBreedingMethods(@PathVariable UUID programId) { + public HttpResponse>> getProgramBreedingMethods(@PathVariable UUID programId, @QueryValue(defaultValue = "false") Boolean inUse) { log.debug(String.format("fetching breeding methods for program: %s", programId)); try { AuthenticatedUser actingUser = securityService.getUser(); - - List breedingMethods = breedingMethodDAO.getProgramBreedingMethods(programId); + List breedingMethods; + if(inUse) { + breedingMethods = breedingMethodService.fetchBreedingMethodsInUse(programId); + } else { + breedingMethods = breedingMethodService.getBreedingMethods(programId); + } return buildResponse(breedingMethods); -// } catch (DoesNotExistException e) { -// log.info(e.getMessage(), e); -// return HttpResponse.notFound(); } catch (Exception e) { log.error(e.getMessage(), e); throw new InternalServerException("Error fetching breeding methods", e); @@ -110,19 +110,16 @@ public HttpResponse>> getProg @Put("programs/{programId}/breeding-methods/{breedingMethodId}") @Produces(MediaType.APPLICATION_JSON) @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) - public HttpResponse> updateProgramBreedingMethod(@PathVariable UUID programId, @PathVariable UUID breedingMethodId, @Body ProgramBreedingMethodEntity breedingMethod) throws BadRequestException { + public HttpResponse> updateProgramBreedingMethod(@PathVariable UUID programId, @PathVariable UUID breedingMethodId, @Body ProgramBreedingMethodEntity breedingMethod) throws BadRequestException, ApiException { log.debug("Saving new program breeding method"); try { AuthenticatedUser user = securityService.getUser(); - if(!validateBreedingMethod(breedingMethod)) { - throw new BadRequestException("Missing required data"); - } breedingMethod.setId(breedingMethodId); Response response = new Response<>(); - response.result = breedingMethodDAO.updateProgramMethod(breedingMethod, programId, user.getId()); + response.result = breedingMethodService.updateBreedingMethod(breedingMethod, programId, user.getId()); List metadataStatus = new ArrayList<>(); metadataStatus.add(new Status(StatusCode.INFO, "Successful Update")); @@ -139,13 +136,13 @@ public HttpResponse> updateProgramBreeding @Put("programs/{programId}/breeding-methods/enable") @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) - public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @Body List systemBreedingMethodIds) { + public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @Body List systemBreedingMethodIds) throws ApiException { log.debug("enabling system breeding methods for program: "+programId); try { AuthenticatedUser user = securityService.getUser(); - breedingMethodDAO.enableSystemMethods(systemBreedingMethodIds, programId, user.getId()); + breedingMethodService.enableSystemMethods(systemBreedingMethodIds, programId, user.getId()); return HttpResponse.ok(); } catch (Exception e) { log.error("Error enabling system breeding methods for program: "+programId, e); @@ -153,13 +150,6 @@ public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @B } } - private boolean validateBreedingMethod(ProgramBreedingMethodEntity method) { - return StringUtils.isNotBlank(method.getName()) - && StringUtils.isNotBlank(method.getAbbreviation()) - && StringUtils.isNotBlank(method.getCategory()) - && StringUtils.isNotBlank(method.getGeneticDiversity()); - } - private HttpResponse>> buildResponse(List breedingMethods) { List metadataStatus = new ArrayList<>(); metadataStatus.add(new Status(StatusCode.INFO, "Successful Query")); diff --git a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java index cfe864163..05fd8c056 100644 --- a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java +++ b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java @@ -1,15 +1,13 @@ package org.breedinginsight.daos.impl; import org.breedinginsight.dao.db.tables.daos.BreedingMethodDao; -import org.breedinginsight.dao.db.tables.pojos.BreedingMethodEntity; import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.daos.BreedingMethodDAO; -import org.jooq.Configuration; -import org.jooq.DSLContext; +import org.jetbrains.annotations.NotNull; +import org.jooq.*; import javax.inject.Inject; import javax.inject.Singleton; -import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; @@ -20,7 +18,7 @@ import static org.breedinginsight.dao.db.tables.BreedingMethodTable.BREEDING_METHOD; @Singleton -public class BreedingMethodDAOImpl extends BreedingMethodDao implements BreedingMethodDAO{ +public class BreedingMethodDAOImpl extends BreedingMethodDao implements BreedingMethodDAO { private DSLContext dsl; @@ -32,16 +30,10 @@ public BreedingMethodDAOImpl(Configuration config, DSLContext dsl) { @Override public List getProgramBreedingMethods(UUID programId) { - List breedingMethodEntities = dsl.select(BREEDING_METHOD.fields()) - .from(BREEDING_METHOD) - .join(PROGRAM_ENABLED_BREEDING_METHODS) - .on(PROGRAM_ENABLED_BREEDING_METHODS.BREEDING_METHOD_ID.eq(BREEDING_METHOD.ID)) - .where(PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID.eq(programId)) + List breedingMethodEntities = systemMethodBase(programId) .fetchInto(ProgramBreedingMethodEntity.class); - List programBreedingMethodEntities = dsl.select(PROGRAM_BREEDING_METHOD.fields()) - .from(PROGRAM_BREEDING_METHOD) - .where(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)) + List programBreedingMethodEntities = programMethodBase(programId) .fetchInto(ProgramBreedingMethodEntity.class); List ret = new ArrayList<>(); @@ -62,21 +54,15 @@ public List getSystemBreedingMethods() { } public List findByNameOrAbbreviation(String nameOrAbbrev, UUID programId) { - List breedingMethodEntities = dsl.select() - .from(BREEDING_METHOD) - .join(PROGRAM_ENABLED_BREEDING_METHODS) - .on(PROGRAM_ENABLED_BREEDING_METHODS.BREEDING_METHOD_ID.eq(BREEDING_METHOD.ID)) - .where(PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID.eq(programId)) - .and(BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) - .or(BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) - .fetchInto(ProgramBreedingMethodEntity.class); - - List programBreedingMethodEntities = dsl.select() - .from(PROGRAM_BREEDING_METHOD) - .where(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)) - .and(PROGRAM_BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) - .or(PROGRAM_BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) - .fetchInto(ProgramBreedingMethodEntity.class); + List breedingMethodEntities = systemMethodBase(programId) + .and(BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) + .or(BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) + .fetchInto(ProgramBreedingMethodEntity.class); + + List programBreedingMethodEntities = programMethodBase(programId) + .and(PROGRAM_BREEDING_METHOD.ABBREVIATION.equalIgnoreCase(nameOrAbbrev) + .or(PROGRAM_BREEDING_METHOD.NAME.equalIgnoreCase(nameOrAbbrev))) + .fetchInto(ProgramBreedingMethodEntity.class); List ret = new ArrayList<>(); if(!breedingMethodEntities.isEmpty()) { @@ -145,4 +131,18 @@ public ProgramBreedingMethodEntity updateProgramMethod(ProgramBreedingMethodEnti .returning(PROGRAM_BREEDING_METHOD.fields()) .fetchOneInto(ProgramBreedingMethodEntity.class); } + + private SelectConditionStep systemMethodBase(UUID programId) { + return dsl.select(BREEDING_METHOD.fields()) + .from(BREEDING_METHOD) + .join(PROGRAM_ENABLED_BREEDING_METHODS) + .on(PROGRAM_ENABLED_BREEDING_METHODS.BREEDING_METHOD_ID.eq(BREEDING_METHOD.ID)) + .where(PROGRAM_ENABLED_BREEDING_METHODS.PROGRAM_ID.eq(programId)); + } + + private SelectConditionStep programMethodBase(UUID programId) { + return dsl.select(PROGRAM_BREEDING_METHOD.fields()) + .from(PROGRAM_BREEDING_METHOD) + .where(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)); + } } diff --git a/src/main/java/org/breedinginsight/services/BreedingMethodService.java b/src/main/java/org/breedinginsight/services/BreedingMethodService.java new file mode 100644 index 000000000..f27a21685 --- /dev/null +++ b/src/main/java/org/breedinginsight/services/BreedingMethodService.java @@ -0,0 +1,23 @@ +package org.breedinginsight.services; + +import org.brapi.client.v2.model.exceptions.ApiException; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; +import org.breedinginsight.services.exceptions.BadRequestException; + +import java.util.List; +import java.util.UUID; + +public interface BreedingMethodService { + + List getBreedingMethods(UUID programId); + + List getSystemBreedingMethods(); + + List fetchBreedingMethodsInUse(UUID programId) throws ApiException; + + ProgramBreedingMethodEntity createBreedingMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID userId) throws BadRequestException, ApiException; + + ProgramBreedingMethodEntity updateBreedingMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID userId) throws BadRequestException, ApiException; + + void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException; +} diff --git a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java new file mode 100644 index 000000000..2c25dd4a5 --- /dev/null +++ b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java @@ -0,0 +1,101 @@ +package org.breedinginsight.services.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.brapi.client.v2.model.exceptions.ApiException; +import org.breedinginsight.brapi.v2.services.BrAPIGermplasmService; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; +import org.breedinginsight.daos.BreedingMethodDAO; +import org.breedinginsight.services.BreedingMethodService; +import org.breedinginsight.services.exceptions.BadRequestException; + +import javax.inject.Singleton; +import java.util.*; +import java.util.stream.Collectors; + +@Singleton +@Slf4j +public class BreedingMethodServiceImpl implements BreedingMethodService { + + private final BreedingMethodDAO breedingMethodDAO; + private final BrAPIGermplasmService germplasmService; + + public BreedingMethodServiceImpl(BreedingMethodDAO breedingMethodDAO, BrAPIGermplasmService germplasmService) { + this.breedingMethodDAO = breedingMethodDAO; + this.germplasmService = germplasmService; + } + + @Override + public List getBreedingMethods(UUID programId) { + return breedingMethodDAO.getProgramBreedingMethods(programId); + } + + @Override + public List getSystemBreedingMethods() { + return breedingMethodDAO.getSystemBreedingMethods(); + } + + @Override + public List fetchBreedingMethodsInUse(UUID programId) throws ApiException { + Map inUse = new HashMap<>(); + Map programMethods = breedingMethodDAO.getProgramBreedingMethods(programId) + .stream() + .collect(Collectors.toMap(ProgramBreedingMethodEntity::getId, o -> o)); + + //TODO retest with new germplasm after updating the DAO to return the correct ID for a method + germplasmService.getGermplasm(programId).forEach(germplasm -> { + UUID id = UUID.fromString(germplasm.getBreedingMethodDbId()); + if(!inUse.containsKey(id)) { + inUse.put(id, programMethods.get(id)); + } + }); + + return new ArrayList<>(inUse.values()); + } + + @Override + public ProgramBreedingMethodEntity createBreedingMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID userId) throws BadRequestException, ApiException { + if(!validateBreedingMethod(breedingMethod)) { + throw new BadRequestException("Missing required data"); + } + + return breedingMethodDAO.createProgramMethod(breedingMethod, programId, userId); + } + + @Override + public ProgramBreedingMethodEntity updateBreedingMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID userId) throws BadRequestException, ApiException { + if(!validateBreedingMethod(breedingMethod)) { + throw new BadRequestException("Missing required data"); + } + + List inUseMethods = fetchBreedingMethodsInUse(programId); + if(inUseMethods.stream().anyMatch(method -> method.getId().equals(breedingMethod.getId()))) { + throw new BadRequestException("Breeding method is not allowed to be edited"); + } + + return breedingMethodDAO.updateProgramMethod(breedingMethod, programId, userId); + } + + @Override + public void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException { + List inUseMethods = fetchBreedingMethodsInUse(programId); + + Set uniqueSystemIds = new HashSet<>(systemBreedingMethods); + + //ensure that a program cannot deactivate a system method if one or more germplasm are using that method + inUseMethods.forEach(method -> { + if(method.getProgramId() == null) { + uniqueSystemIds.add(method.getId()); + } + }); + + breedingMethodDAO.enableSystemMethods(new ArrayList<>(uniqueSystemIds), programId, userId); + } + + private boolean validateBreedingMethod(ProgramBreedingMethodEntity method) { + return StringUtils.isNotBlank(method.getName()) + && StringUtils.isNotBlank(method.getAbbreviation()) + && StringUtils.isNotBlank(method.getCategory()) + && StringUtils.isNotBlank(method.getGeneticDiversity()); + } +} diff --git a/src/main/resources/db/migration/V1.0.8__create_program_breeding_methods.sql b/src/main/resources/db/migration/V1.0.9__create_program_breeding_methods.sql similarity index 100% rename from src/main/resources/db/migration/V1.0.8__create_program_breeding_methods.sql rename to src/main/resources/db/migration/V1.0.9__create_program_breeding_methods.sql diff --git a/src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java b/src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java new file mode 100644 index 000000000..97d38b8c9 --- /dev/null +++ b/src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java @@ -0,0 +1,5 @@ +package org.breedinginsight.services.impl; + +public class BreedingMethodServiceImplTest { + //TODO +} From fde2de6a6afa191b3ca33d5f3c3e35e9df853d66 Mon Sep 17 00:00:00 2001 From: timparsons Date: Mon, 5 Dec 2022 21:33:55 +1100 Subject: [PATCH 04/12] [BI-1651] Adding ability to delete a program breeding method --- .../controller/BreedingMethodController.java | 12 ++++++++++ .../daos/BreedingMethodDAO.java | 2 ++ .../daos/impl/BreedingMethodDAOImpl.java | 7 ++++++ .../services/BreedingMethodService.java | 2 ++ .../impl/BreedingMethodServiceImpl.java | 22 +++++++++++++++---- 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java index 3ef87ef63..1d704305d 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java @@ -150,6 +150,18 @@ public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @B } } + @Delete("programs/{programId}/breeding-methods/{breedingMethodId}") + public HttpResponse deleteProgramBreedingMethod(@PathVariable UUID programId, @PathVariable UUID breedingMethodId) throws BadRequestException, ApiException { + try { + AuthenticatedUser user = securityService.getUser(); + breedingMethodService.deleteBreedingMethod(programId, breedingMethodId); + return HttpResponse.ok(); + } catch (Exception e) { + log.error("Error deleting breeding method.\n\tprogramId: " + programId + "\n\tbreedingMethodId: " + breedingMethodId); + throw e; + } + } + private HttpResponse>> buildResponse(List breedingMethods) { List metadataStatus = new ArrayList<>(); metadataStatus.add(new Status(StatusCode.INFO, "Successful Query")); diff --git a/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java b/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java index d5cd4e9d5..0ccdcd47f 100644 --- a/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java +++ b/src/main/java/org/breedinginsight/daos/BreedingMethodDAO.java @@ -23,4 +23,6 @@ public interface BreedingMethodDAO { ProgramBreedingMethodEntity createProgramMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID id); ProgramBreedingMethodEntity updateProgramMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID id); + + void deleteProgramMethod(UUID programId, UUID breedingMethodId); } diff --git a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java index 05fd8c056..a5280c66b 100644 --- a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java +++ b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java @@ -132,6 +132,13 @@ public ProgramBreedingMethodEntity updateProgramMethod(ProgramBreedingMethodEnti .fetchOneInto(ProgramBreedingMethodEntity.class); } + @Override + public void deleteProgramMethod(UUID programId, UUID breedingMethodId) { + dsl.deleteFrom(PROGRAM_BREEDING_METHOD) + .where(PROGRAM_BREEDING_METHOD.ID.eq(breedingMethodId)) + .and(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)); + } + private SelectConditionStep systemMethodBase(UUID programId) { return dsl.select(BREEDING_METHOD.fields()) .from(BREEDING_METHOD) diff --git a/src/main/java/org/breedinginsight/services/BreedingMethodService.java b/src/main/java/org/breedinginsight/services/BreedingMethodService.java index f27a21685..37e792cf7 100644 --- a/src/main/java/org/breedinginsight/services/BreedingMethodService.java +++ b/src/main/java/org/breedinginsight/services/BreedingMethodService.java @@ -20,4 +20,6 @@ public interface BreedingMethodService { ProgramBreedingMethodEntity updateBreedingMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID userId) throws BadRequestException, ApiException; void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException; + + void deleteBreedingMethod(UUID programId, UUID breedingMethodId) throws ApiException, BadRequestException; } diff --git a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java index 2c25dd4a5..10d8cac32 100644 --- a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java +++ b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java @@ -8,6 +8,7 @@ import org.breedinginsight.daos.BreedingMethodDAO; import org.breedinginsight.services.BreedingMethodService; import org.breedinginsight.services.exceptions.BadRequestException; +import org.jooq.DSLContext; import javax.inject.Singleton; import java.util.*; @@ -20,9 +21,12 @@ public class BreedingMethodServiceImpl implements BreedingMethodService { private final BreedingMethodDAO breedingMethodDAO; private final BrAPIGermplasmService germplasmService; - public BreedingMethodServiceImpl(BreedingMethodDAO breedingMethodDAO, BrAPIGermplasmService germplasmService) { + private final DSLContext dsl; + + public BreedingMethodServiceImpl(BreedingMethodDAO breedingMethodDAO, BrAPIGermplasmService germplasmService, DSLContext dsl) { this.breedingMethodDAO = breedingMethodDAO; this.germplasmService = germplasmService; + this.dsl = dsl; } @Override @@ -59,7 +63,7 @@ public ProgramBreedingMethodEntity createBreedingMethod(ProgramBreedingMethodEnt throw new BadRequestException("Missing required data"); } - return breedingMethodDAO.createProgramMethod(breedingMethod, programId, userId); + return dsl.transactionResult(() -> breedingMethodDAO.createProgramMethod(breedingMethod, programId, userId)); } @Override @@ -73,7 +77,7 @@ public ProgramBreedingMethodEntity updateBreedingMethod(ProgramBreedingMethodEnt throw new BadRequestException("Breeding method is not allowed to be edited"); } - return breedingMethodDAO.updateProgramMethod(breedingMethod, programId, userId); + return dsl.transactionResult(() -> breedingMethodDAO.updateProgramMethod(breedingMethod, programId, userId)); } @Override @@ -89,7 +93,17 @@ public void enableSystemMethods(List systemBreedingMethods, UUID programId } }); - breedingMethodDAO.enableSystemMethods(new ArrayList<>(uniqueSystemIds), programId, userId); + dsl.transaction(() -> breedingMethodDAO.enableSystemMethods(new ArrayList<>(uniqueSystemIds), programId, userId)); + } + + @Override + public void deleteBreedingMethod(UUID programId, UUID breedingMethodId) throws ApiException, BadRequestException { + List inUseMethods = fetchBreedingMethodsInUse(programId); + if(inUseMethods.stream().anyMatch(method -> method.getId().equals(breedingMethodId))) { + throw new BadRequestException("Breeding method is not allowed to be deleted"); + } + + dsl.transaction(() -> breedingMethodDAO.deleteProgramMethod(programId, breedingMethodId)); } private boolean validateBreedingMethod(ProgramBreedingMethodEntity method) { From 2a50ea518a036c2eaa72cc1e8d3005a195d33df5 Mon Sep 17 00:00:00 2001 From: timparsons Date: Wed, 21 Dec 2022 15:02:40 -0500 Subject: [PATCH 05/12] [BI-1651] Adding unit tests --- .../controller/BreedingMethodController.java | 1 + .../daos/impl/BreedingMethodDAOImpl.java | 2 +- .../impl/BreedingMethodServiceImpl.java | 4 +- ...eedingMethodControllerIntegrationTest.java | 446 ++++++++++++++++++ 4 files changed, 449 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java diff --git a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java index 1d704305d..ab512e2e1 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java @@ -151,6 +151,7 @@ public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @B } @Delete("programs/{programId}/breeding-methods/{breedingMethodId}") + @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) public HttpResponse deleteProgramBreedingMethod(@PathVariable UUID programId, @PathVariable UUID breedingMethodId) throws BadRequestException, ApiException { try { AuthenticatedUser user = securityService.getUser(); diff --git a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java index a5280c66b..4d502b84e 100644 --- a/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java +++ b/src/main/java/org/breedinginsight/daos/impl/BreedingMethodDAOImpl.java @@ -136,7 +136,7 @@ public ProgramBreedingMethodEntity updateProgramMethod(ProgramBreedingMethodEnti public void deleteProgramMethod(UUID programId, UUID breedingMethodId) { dsl.deleteFrom(PROGRAM_BREEDING_METHOD) .where(PROGRAM_BREEDING_METHOD.ID.eq(breedingMethodId)) - .and(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)); + .and(PROGRAM_BREEDING_METHOD.PROGRAM_ID.eq(programId)).execute(); } private SelectConditionStep systemMethodBase(UUID programId) { diff --git a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java index 10d8cac32..6a47bece9 100644 --- a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java +++ b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java @@ -49,9 +49,7 @@ public List fetchBreedingMethodsInUse(UUID programI //TODO retest with new germplasm after updating the DAO to return the correct ID for a method germplasmService.getGermplasm(programId).forEach(germplasm -> { UUID id = UUID.fromString(germplasm.getBreedingMethodDbId()); - if(!inUse.containsKey(id)) { - inUse.put(id, programMethods.get(id)); - } + inUse.put(id, programMethods.get(id)); }); return new ArrayList<>(inUse.values()); diff --git a/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java b/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java new file mode 100644 index 000000000..277b346fd --- /dev/null +++ b/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java @@ -0,0 +1,446 @@ +package org.breedinginsight.api.v1.controller; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import io.kowalski.fannypack.FannyPack; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.HttpStatus; +import io.micronaut.http.client.RxHttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.http.netty.cookies.NettyCookie; +import io.micronaut.test.annotation.MicronautTest; +import io.micronaut.test.annotation.MockBean; +import io.reactivex.Flowable; +import org.brapi.client.v2.model.exceptions.ApiException; +import org.brapi.v2.model.germ.BrAPIGermplasm; +import org.breedinginsight.BrAPITest; +import org.breedinginsight.TestUtils; +import org.breedinginsight.api.model.v1.request.ProgramRequest; +import org.breedinginsight.api.model.v1.request.SpeciesRequest; +import org.breedinginsight.brapi.v2.dao.BrAPIGermplasmDAO; +import org.breedinginsight.brapi.v2.services.BrAPIGermplasmService; +import org.breedinginsight.brapps.importer.daos.BrAPIListDAO; +import org.breedinginsight.brapps.importer.daos.ImportDAO; +import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; +import org.breedinginsight.dao.db.tables.pojos.SpeciesEntity; +import org.breedinginsight.daos.ProgramDAO; +import org.breedinginsight.daos.SpeciesDAO; +import org.breedinginsight.daos.UserDAO; +import org.breedinginsight.daos.cache.ProgramCacheProvider; +import org.breedinginsight.daos.impl.ProgramDAOImpl; +import org.breedinginsight.model.Program; +import org.breedinginsight.model.User; +import org.breedinginsight.services.ProgramService; +import org.breedinginsight.utilities.BrAPIDAOUtil; +import org.jooq.DSLContext; +import org.junit.jupiter.api.*; +import org.mockito.Mockito; + +import javax.inject.Inject; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static io.micronaut.http.HttpRequest.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +@MicronautTest +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class BreedingMethodControllerIntegrationTest extends BrAPITest { + + private FannyPack securityFp; + private FannyPack brapiFp; + private User testUser; + + @Inject + private UserDAO userDAO; + + @Inject + private ProgramDAO programDAO; + + @Inject + private SpeciesDAO speciesDAO; + + @Inject + private DSLContext dsl; + + @Inject + @Client("/${micronaut.bi.api.version}") + private RxHttpClient client; + + + @Inject + private BrAPIListDAO brAPIListDAO; + + @Inject + private ProgramService programService; + + @Inject + private BrAPIGermplasmDAO germplasmDAO; + + @Inject + private BrAPIGermplasmService germplasmService; + + @MockBean(BrAPIGermplasmDAO.class) + BrAPIGermplasmService brAPIGermplasmService() { + return spy(new BrAPIGermplasmService(brAPIListDAO, programService, germplasmDAO); + } + + private Gson gson = new GsonBuilder().registerTypeAdapter(OffsetDateTime.class, (JsonDeserializer) + (json, type, context) -> OffsetDateTime.parse(json.getAsString())) + .create(); + + @BeforeAll + void setup() throws Exception { + // Create two programs with fanny pack + securityFp = FannyPack.fill("src/test/resources/sql/ProgramSecuredAnnotationRuleIntegrationTest.sql"); + brapiFp = FannyPack.fill("src/test/resources/sql/brapi/species.sql"); + + testUser = userDAO.getUserByOrcId(TestTokenValidator.TEST_USER_ORCID).get(); + super.getBrapiDsl().execute(brapiFp.get("InsertSpecies")); + dsl.execute(securityFp.get("InsertSystemRoleAdmin"), testUser.getId().toString()); + + + } + + private Program createProgram(String name, String abbv, String key) { + SpeciesEntity validSpecies = speciesDAO.findAll().get(0); + SpeciesRequest speciesRequest = SpeciesRequest.builder() + .commonName(validSpecies.getCommonName()) + .id(validSpecies.getId()) + .build(); + ProgramRequest programRequest1 = ProgramRequest.builder() + .name(name) + .abbreviation(abbv) + .documentationUrl("localhost:8080") + .objective("To test things") + .species(speciesRequest) + .key(key) + .build(); + + + TestUtils.insertAndFetchTestProgram(gson, client, programRequest1); + + // Get main program + List programs = programDAO.getProgramByKey(key); + Program program = programs.get(0); + + dsl.execute(securityFp.get("InsertProgramRolesBreeder"), testUser.getId().toString(), program.getId().toString()); + + return program; + } + + @Test + public void fetchMethodsForNewProgram() { + Program program = createProgram("newProgramBM", "BM", "NEWBM"); + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse systemResponse = systemCall.blockingFirst(); + assertEquals(HttpStatus.OK, systemResponse.getStatus()); + + JsonObject systemResult = JsonParser.parseString(systemResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List systemMethods = gson.fromJson(systemResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + //fetch program breeding methods, and ensure that list matches list of system methods + String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> programCall = client.exchange( + GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse programResponse = programCall.blockingFirst(); + assertEquals(HttpStatus.OK, programResponse.getStatus()); + + JsonObject programResult = JsonParser.parseString(programResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + assertThat(programMethods.size(), equalTo(systemMethods.size())); + + assertThat(programMethods.stream() + .map(ProgramBreedingMethodEntity::getId) + .collect(Collectors.toList()), + equalTo(systemMethods.stream() + .map(ProgramBreedingMethodEntity::getId) + .collect(Collectors.toList()))); + } + + @Test + public void enableSystemMethods() { + Program program = createProgram("enableProgramBM", "EBM", "ENBM"); + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse systemResponse = systemCall.blockingFirst(); + assertEquals(HttpStatus.OK, systemResponse.getStatus()); + + JsonObject systemResult = JsonParser.parseString(systemResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List systemMethods = gson.fromJson(systemResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + List enabledSystemMethods = new ArrayList<>(); + enabledSystemMethods.add(systemMethods.get(0).getId()); + + String enableUrl = String.format("/programs/%s/breeding-methods/enable", program.getId()); + Flowable> enableCall = client.exchange( + PUT(enableUrl, enabledSystemMethods).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse enableResponse = enableCall.blockingFirst(); + assertEquals(HttpStatus.OK, enableResponse.getStatus()); + + //fetch program breeding methods, and ensure that list matches list of system methods + String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> programCall = client.exchange( + GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse programResponse = programCall.blockingFirst(); + assertEquals(HttpStatus.OK, programResponse.getStatus()); + + JsonObject programResult = JsonParser.parseString(programResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + assertThat(programMethods.size(), equalTo(1)); + assertThat(programMethods.get(0).getId(), equalTo(enabledSystemMethods.get(0))); + } + + @Test + public void createProgramMethod() { + Program program = createProgram("createProgramBM", "CBM", "CRBM"); + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() + .programId(program.getId()) + .name("test created method") + .abbreviation("TCM") + .category("Cross") + .description("new method creation") + .geneticDiversity("Generative (+)") + .build(); + + String createUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> createCall = client.exchange( + POST(createUrl, method).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse createdResponse = createCall.blockingFirst(); + assertEquals(HttpStatus.OK, createdResponse.getStatus()); + + JsonObject createdResult = JsonParser.parseString(createdResponse.body()).getAsJsonObject().getAsJsonObject("result"); + ProgramBreedingMethodEntity createdMethod = gson.fromJson(createdResult, ProgramBreedingMethodEntity.class); + + assertThat(createdMethod.getId(), is(notNullValue())); + assertThat(createdMethod.getProgramId(), equalTo(program.getId())); + assertThat(createdMethod.getName(), equalTo(method.getName())); + assertThat(createdMethod.getAbbreviation(), equalTo(method.getAbbreviation())); + assertThat(createdMethod.getCategory(), equalTo(method.getCategory())); + assertThat(createdMethod.getDescription(), equalTo(method.getDescription())); + assertThat(createdMethod.getGeneticDiversity(), equalTo(method.getGeneticDiversity())); + + //fetch program breeding methods, and ensure that list matches list of system methods + String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> programCall = client.exchange( + GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse programResponse = programCall.blockingFirst(); + assertEquals(HttpStatus.OK, programResponse.getStatus()); + + JsonObject programResult = JsonParser.parseString(programResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + assertThat(programMethods.size(), greaterThan(0)); + assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), hasItem(createdMethod.getId())); + } + + @Test + public void editProgramMethod() { + Program program = createProgram("editProgramBM", "EBM", "EDBM"); + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() + .programId(program.getId()) + .name("test edit method") + .abbreviation("TEM") + .category("Cross") + .description("new method creation") + .geneticDiversity("Generative (+)") + .build(); + + String createUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> createCall = client.exchange( + POST(createUrl, method).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse createdResponse = createCall.blockingFirst(); + assertEquals(HttpStatus.OK, createdResponse.getStatus()); + + JsonObject createdResult = JsonParser.parseString(createdResponse.body()).getAsJsonObject().getAsJsonObject("result"); + ProgramBreedingMethodEntity createdMethod = gson.fromJson(createdResult, ProgramBreedingMethodEntity.class); + + assertThat(createdMethod.getId(), is(notNullValue())); + + createdMethod.setName("Edited name"); + createdMethod.setAbbreviation("TEEM"); + createdMethod.setCategory("Unknown"); + createdMethod.setDescription("Edited description"); + createdMethod.setGeneticDiversity("Maintenance (0)"); + + String updateUrl = String.format("/programs/%s/breeding-methods/%s", program.getId(), createdMethod.getId()); + Flowable> editCall = client.exchange( + PUT(updateUrl, createdMethod).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse editResponse = editCall.blockingFirst(); + assertEquals(HttpStatus.OK, editResponse.getStatus()); + + JsonObject editResult = JsonParser.parseString(editResponse.body()).getAsJsonObject().getAsJsonObject("result"); + ProgramBreedingMethodEntity editedMethod = gson.fromJson(editResult, ProgramBreedingMethodEntity.class); + + assertThat(editedMethod.getId(), equalTo(createdMethod.getId())); + assertThat(editedMethod.getProgramId(), equalTo(program.getId())); + assertThat(editedMethod.getName(), equalTo(createdMethod.getName())); + assertThat(editedMethod.getAbbreviation(), equalTo(createdMethod.getAbbreviation())); + assertThat(editedMethod.getCategory(), equalTo(createdMethod.getCategory())); + assertThat(editedMethod.getDescription(), equalTo(createdMethod.getDescription())); + assertThat(editedMethod.getGeneticDiversity(), equalTo(createdMethod.getGeneticDiversity())); + } + + @Test + public void deleteProgramMethod() { + Program program = createProgram("deleteProgramBM", "DBM", "DELBM"); + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() + .programId(program.getId()) + .name("test delete method") + .abbreviation("TDM") + .category("Cross") + .description("method deletion") + .geneticDiversity("Generative (+)") + .build(); + + String createUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> createCall = client.exchange( + POST(createUrl, method).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse createdResponse = createCall.blockingFirst(); + assertEquals(HttpStatus.OK, createdResponse.getStatus()); + + JsonObject createdResult = JsonParser.parseString(createdResponse.body()).getAsJsonObject().getAsJsonObject("result"); + ProgramBreedingMethodEntity createdMethod = gson.fromJson(createdResult, ProgramBreedingMethodEntity.class); + + assertThat(createdMethod.getId(), is(notNullValue())); + + String deleteUrl = String.format("/programs/%s/breeding-methods/%s", program.getId(), createdMethod.getId()); + Flowable> deleteCall = client.exchange( + DELETE(deleteUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse deleteResponse = deleteCall.blockingFirst(); + assertEquals(HttpStatus.OK, deleteResponse.getStatus()); + + //fetch program breeding methods, and ensure that list does not contain the method just deleted + String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> programCall = client.exchange( + GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse programResponse = programCall.blockingFirst(); + assertEquals(HttpStatus.OK, programResponse.getStatus()); + + JsonObject programResult = JsonParser.parseString(programResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + assertThat(programMethods.size(), greaterThan(0)); + assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), not(hasItem(createdMethod.getId()))); + } + + @Test + public void tryDeleteProgramMethodInUse() throws ApiException { + Program program = createProgram("tryDeleteProgramBM", "TDBM", "TRYDBM"); + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() + .programId(program.getId()) + .name("try delete method") + .abbreviation("TRYDM") + .category("Cross") + .description("try method deletion") + .geneticDiversity("Generative (+)") + .build(); + + String createUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> createCall = client.exchange( + POST(createUrl, method).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse createdResponse = createCall.blockingFirst(); + assertEquals(HttpStatus.OK, createdResponse.getStatus()); + + JsonObject createdResult = JsonParser.parseString(createdResponse.body()).getAsJsonObject().getAsJsonObject("result"); + ProgramBreedingMethodEntity createdMethod = gson.fromJson(createdResult, ProgramBreedingMethodEntity.class); + + assertThat(createdMethod.getId(), is(notNullValue())); + + BrAPIGermplasm germplasm = new BrAPIGermplasm() + .breedingMethodDbId(createdMethod.getId().toString()) + .germplasmName("test germ") + .accessionNumber("1"); + + doReturn(List.of(germplasm)).when(germplasmService).getGermplasm(Mockito.any(UUID.class)); + + String deleteUrl = String.format("/programs/%s/breeding-methods/%s", program.getId(), createdMethod.getId()); + Flowable> deleteCall = client.exchange( + DELETE(deleteUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse deleteResponse = deleteCall.blockingFirst(); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, deleteResponse.getStatus()); + + //fetch program breeding methods, and ensure that list does contain the method just deleted + String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> programCall = client.exchange( + GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse programResponse = programCall.blockingFirst(); + assertEquals(HttpStatus.OK, programResponse.getStatus()); + + JsonObject programResult = JsonParser.parseString(programResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + assertThat(programMethods.size(), greaterThan(0)); + assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), not(hasItem(createdMethod.getId()))); + } + + @Test + public void tryDisableSystemMethodInUse() { + Assertions.fail(); + } +} From 7ac0f7ab81b893ad183e8afa20ed140b912260dc Mon Sep 17 00:00:00 2001 From: timparsons Date: Mon, 9 Jan 2023 11:47:15 -0500 Subject: [PATCH 06/12] [BI-1651] Finishing implementation of integration tests --- .../controller/BreedingMethodController.java | 2 +- .../daos/cache/ProgramCache.java | 7 +- .../services/BreedingMethodService.java | 2 +- .../impl/BreedingMethodServiceImpl.java | 5 +- ...eedingMethodControllerIntegrationTest.java | 236 +++++++++++++----- 5 files changed, 191 insertions(+), 61 deletions(-) diff --git a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java index ab512e2e1..5ef7caa75 100644 --- a/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java +++ b/src/main/java/org/breedinginsight/api/v1/controller/BreedingMethodController.java @@ -136,7 +136,7 @@ public HttpResponse> updateProgramBreeding @Put("programs/{programId}/breeding-methods/enable") @ProgramSecured(roles = {ProgramSecuredRole.BREEDER}) - public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @Body List systemBreedingMethodIds) throws ApiException { + public HttpResponse enableSystemBreedingMethods(@PathVariable UUID programId, @Body List systemBreedingMethodIds) throws ApiException, BadRequestException { log.debug("enabling system breeding methods for program: "+programId); try { diff --git a/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java b/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java index be7168c0d..cb28fb67f 100644 --- a/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java +++ b/src/main/java/org/breedinginsight/daos/cache/ProgramCache.java @@ -164,7 +164,7 @@ private Map deserialize(Map cachedVals) { return retMap; } - public List post(UUID key, Callable> postMethod) { + public List post(UUID key, Callable> postMethod) throws Exception { log.debug("posting for key: " + generateCacheKey(key)); Map response = null; try { @@ -177,10 +177,13 @@ public List post(UUID key, Callable> postMethod) { map.put(obj.getKey(), gson.toJson(obj.getValue())); } populate(key); + + return new ArrayList<>(response.values()); } catch (Exception e) { + log.error("Error posting data and populating the cache", e); invalidate(key); + throw e; } - return new ArrayList<>(response.values()); } public boolean isRefreshing(UUID key) { diff --git a/src/main/java/org/breedinginsight/services/BreedingMethodService.java b/src/main/java/org/breedinginsight/services/BreedingMethodService.java index 37e792cf7..e9e428d0f 100644 --- a/src/main/java/org/breedinginsight/services/BreedingMethodService.java +++ b/src/main/java/org/breedinginsight/services/BreedingMethodService.java @@ -19,7 +19,7 @@ public interface BreedingMethodService { ProgramBreedingMethodEntity updateBreedingMethod(ProgramBreedingMethodEntity breedingMethod, UUID programId, UUID userId) throws BadRequestException, ApiException; - void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException; + void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException, BadRequestException; void deleteBreedingMethod(UUID programId, UUID breedingMethodId) throws ApiException, BadRequestException; } diff --git a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java index 6a47bece9..018431fc6 100644 --- a/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java +++ b/src/main/java/org/breedinginsight/services/impl/BreedingMethodServiceImpl.java @@ -79,8 +79,11 @@ public ProgramBreedingMethodEntity updateBreedingMethod(ProgramBreedingMethodEnt } @Override - public void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException { + public void enableSystemMethods(List systemBreedingMethods, UUID programId, UUID userId) throws ApiException, BadRequestException { List inUseMethods = fetchBreedingMethodsInUse(programId); + if(!systemBreedingMethods.containsAll(inUseMethods.stream().map(method -> method.getId()).collect(Collectors.toList()))) { + throw new BadRequestException("Breeding method is not allowed to be edited"); + } Set uniqueSystemIds = new HashSet<>(systemBreedingMethods); diff --git a/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java b/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java index 277b346fd..1c0dc11af 100644 --- a/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java +++ b/src/test/java/org/breedinginsight/api/v1/controller/BreedingMethodControllerIntegrationTest.java @@ -3,54 +3,46 @@ import com.google.gson.*; import com.google.gson.reflect.TypeToken; import io.kowalski.fannypack.FannyPack; +import io.micronaut.context.annotation.Property; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; import io.micronaut.http.client.RxHttpClient; import io.micronaut.http.client.annotation.Client; +import io.micronaut.http.client.exceptions.HttpClientResponseException; import io.micronaut.http.netty.cookies.NettyCookie; import io.micronaut.test.annotation.MicronautTest; -import io.micronaut.test.annotation.MockBean; import io.reactivex.Flowable; import org.brapi.client.v2.model.exceptions.ApiException; +import org.brapi.v2.model.BrAPIExternalReference; import org.brapi.v2.model.germ.BrAPIGermplasm; import org.breedinginsight.BrAPITest; import org.breedinginsight.TestUtils; import org.breedinginsight.api.model.v1.request.ProgramRequest; import org.breedinginsight.api.model.v1.request.SpeciesRequest; -import org.breedinginsight.brapi.v2.dao.BrAPIGermplasmDAO; +import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields; import org.breedinginsight.brapi.v2.services.BrAPIGermplasmService; -import org.breedinginsight.brapps.importer.daos.BrAPIListDAO; -import org.breedinginsight.brapps.importer.daos.ImportDAO; import org.breedinginsight.dao.db.tables.pojos.ProgramBreedingMethodEntity; import org.breedinginsight.dao.db.tables.pojos.SpeciesEntity; import org.breedinginsight.daos.ProgramDAO; import org.breedinginsight.daos.SpeciesDAO; import org.breedinginsight.daos.UserDAO; -import org.breedinginsight.daos.cache.ProgramCacheProvider; -import org.breedinginsight.daos.impl.ProgramDAOImpl; import org.breedinginsight.model.Program; import org.breedinginsight.model.User; -import org.breedinginsight.services.ProgramService; -import org.breedinginsight.utilities.BrAPIDAOUtil; import org.jooq.DSLContext; import org.junit.jupiter.api.*; -import org.mockito.Mockito; import javax.inject.Inject; -import java.time.Duration; +import java.time.LocalDateTime; import java.time.OffsetDateTime; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.time.format.DateTimeFormatter; +import java.util.*; import java.util.stream.Collectors; import static io.micronaut.http.HttpRequest.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; @MicronautTest @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -77,23 +69,11 @@ public class BreedingMethodControllerIntegrationTest extends BrAPITest { @Client("/${micronaut.bi.api.version}") private RxHttpClient client; - - @Inject - private BrAPIListDAO brAPIListDAO; - - @Inject - private ProgramService programService; - - @Inject - private BrAPIGermplasmDAO germplasmDAO; - @Inject private BrAPIGermplasmService germplasmService; - @MockBean(BrAPIGermplasmDAO.class) - BrAPIGermplasmService brAPIGermplasmService() { - return spy(new BrAPIGermplasmService(brAPIListDAO, programService, germplasmDAO); - } + @Property(name = "brapi.server.reference-source") + private String referenceSource; private Gson gson = new GsonBuilder().registerTypeAdapter(OffsetDateTime.class, (JsonDeserializer) (json, type, context) -> OffsetDateTime.parse(json.getAsString())) @@ -219,10 +199,6 @@ public void enableSystemMethods() { @Test public void createProgramMethod() { Program program = createProgram("createProgramBM", "CBM", "CRBM"); - String systemMethodsUrl = "/breeding-methods"; - Flowable> systemCall = client.exchange( - GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class - ); ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() .programId(program.getId()) @@ -271,10 +247,6 @@ public void createProgramMethod() { @Test public void editProgramMethod() { Program program = createProgram("editProgramBM", "EBM", "EDBM"); - String systemMethodsUrl = "/breeding-methods"; - Flowable> systemCall = client.exchange( - GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class - ); ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() .programId(program.getId()) @@ -327,10 +299,6 @@ public void editProgramMethod() { @Test public void deleteProgramMethod() { Program program = createProgram("deleteProgramBM", "DBM", "DELBM"); - String systemMethodsUrl = "/breeding-methods"; - Flowable> systemCall = client.exchange( - GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class - ); ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() .programId(program.getId()) @@ -378,13 +346,81 @@ public void deleteProgramMethod() { assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), not(hasItem(createdMethod.getId()))); } + @Test + public void createGermplasmWithProgramMethod() throws ApiException { + Program program = createProgram("createGermProgBM", "CGBM", "CGERBM"); + + ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() + .programId(program.getId()) + .name("create germ prog method") + .abbreviation("CGERMPBM") + .category("Cross") + .description("create germ from prog method") + .geneticDiversity("Generative (+)") + .build(); + + String createUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> createCall = client.exchange( + POST(createUrl, method).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse createdResponse = createCall.blockingFirst(); + assertEquals(HttpStatus.OK, createdResponse.getStatus()); + + JsonObject createdResult = JsonParser.parseString(createdResponse.body()).getAsJsonObject().getAsJsonObject("result"); + ProgramBreedingMethodEntity createdMethod = gson.fromJson(createdResult, ProgramBreedingMethodEntity.class); + + assertThat(createdMethod.getId(), is(notNullValue())); + + Map createdBy = new HashMap<>(); + createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_ID, testUser.getId().toString()); + createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_NAME, testUser.getName()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + String accessionNum = String.valueOf((int)(Math.random()*100)); + BrAPIExternalReference programRef = new BrAPIExternalReference(); + programRef.setReferenceSource(String.format("%s/programs", referenceSource)); + programRef.setReferenceID(program.getId().toString()); + BrAPIExternalReference germIdRef = new BrAPIExternalReference(); + germIdRef.setReferenceSource(referenceSource); + germIdRef.setReferenceID(UUID.randomUUID().toString()); + BrAPIGermplasm germplasm = new BrAPIGermplasm() + .germplasmName("test germ ["+program.getKey()+"-"+accessionNum+"]") + .defaultDisplayName("test germ") + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER, "1") + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_BY, createdBy) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD_ID, createdMethod.getId()) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD, createdMethod.getName()) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_DATE, formatter.format(now)) + .externalReferences(List.of(programRef, germIdRef)) + .accessionNumber(accessionNum); + + assertDoesNotThrow(() -> germplasmService.importBrAPIGermplasm(List.of(germplasm), program.getId(), null)); + + String germplasmUrl = String.format("/programs/%s/brapi/v2/germplasm", program.getId()); + Flowable> germplasmCall = client.exchange( + GET(germplasmUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse germplasmResponse = germplasmCall.blockingFirst(); + assertEquals(HttpStatus.OK, germplasmResponse.getStatus()); + + JsonObject germplasmResult = JsonParser.parseString(germplasmResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programGerm = gson.fromJson(germplasmResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + assertThat(programGerm.size(), greaterThan(0)); + + Optional savedGerm = programGerm.stream().filter(brAPIGermplasm -> brAPIGermplasm.getDefaultDisplayName().equals(germplasm.getDefaultDisplayName())).findFirst(); + assertThat(savedGerm, not(Optional.empty())); + + assertThat(savedGerm.get().getBreedingMethodDbId(), equalTo(createdMethod.getId().toString())); + + assertThat(savedGerm.get().getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD_ID).getAsString(), equalTo(createdMethod.getId().toString())); + assertThat(savedGerm.get().getAdditionalInfo().get(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD).getAsString(), equalTo(createdMethod.getName())); + } + @Test public void tryDeleteProgramMethodInUse() throws ApiException { Program program = createProgram("tryDeleteProgramBM", "TDBM", "TRYDBM"); - String systemMethodsUrl = "/breeding-methods"; - Flowable> systemCall = client.exchange( - GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class - ); ProgramBreedingMethodEntity method = ProgramBreedingMethodEntity.builder() .programId(program.getId()) @@ -408,22 +444,40 @@ public void tryDeleteProgramMethodInUse() throws ApiException { assertThat(createdMethod.getId(), is(notNullValue())); + Map createdBy = new HashMap<>(); + createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_ID, testUser.getId().toString()); + createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_NAME, testUser.getName()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + String accessionNum = String.valueOf((int)(Math.random()*100)); + BrAPIExternalReference programRef = new BrAPIExternalReference(); + programRef.setReferenceSource(String.format("%s/programs", referenceSource)); + programRef.setReferenceID(program.getId().toString()); + BrAPIExternalReference germIdRef = new BrAPIExternalReference(); + germIdRef.setReferenceSource(referenceSource); + germIdRef.setReferenceID(UUID.randomUUID().toString()); BrAPIGermplasm germplasm = new BrAPIGermplasm() - .breedingMethodDbId(createdMethod.getId().toString()) - .germplasmName("test germ") - .accessionNumber("1"); - - doReturn(List.of(germplasm)).when(germplasmService).getGermplasm(Mockito.any(UUID.class)); + .germplasmName("test germ ["+program.getKey()+"-"+accessionNum+"]") + .defaultDisplayName("test germ") + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER, "1") + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_BY, createdBy) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD_ID, createdMethod.getId()) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD, createdMethod.getName()) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_DATE, formatter.format(now)) + .externalReferences(List.of(programRef, germIdRef)) + .accessionNumber(accessionNum); + + assertDoesNotThrow(() -> germplasmService.importBrAPIGermplasm(List.of(germplasm), program.getId(), null)); String deleteUrl = String.format("/programs/%s/breeding-methods/%s", program.getId(), createdMethod.getId()); Flowable> deleteCall = client.exchange( DELETE(deleteUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")) , String.class); - HttpResponse deleteResponse = deleteCall.blockingFirst(); - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, deleteResponse.getStatus()); + HttpClientResponseException e = Assertions.assertThrows(HttpClientResponseException.class, () -> deleteCall.blockingFirst()); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, e.getStatus()); - //fetch program breeding methods, and ensure that list does contain the method just deleted + //fetch program breeding methods, and ensure that list contains the method we tried to delete String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); Flowable> programCall = client.exchange( GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class @@ -436,11 +490,81 @@ public void tryDeleteProgramMethodInUse() throws ApiException { List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); assertThat(programMethods.size(), greaterThan(0)); - assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), not(hasItem(createdMethod.getId()))); + assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), hasItem(createdMethod.getId())); } @Test public void tryDisableSystemMethodInUse() { - Assertions.fail(); + Program program = createProgram("tryDeleteSystemBM", "TDSBM", "TRDSBM"); + + String systemMethodsUrl = "/breeding-methods"; + Flowable> systemCall = client.exchange( + GET(systemMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse systemResponse = systemCall.blockingFirst(); + assertEquals(HttpStatus.OK, systemResponse.getStatus()); + + JsonObject systemResult = JsonParser.parseString(systemResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List systemMethods = gson.fromJson(systemResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + ProgramBreedingMethodEntity systemMethod = systemMethods.get(0); + + List enabledSystemMethods = new ArrayList<>(); + enabledSystemMethods.add(systemMethod.getId()); + + String enableUrl = String.format("/programs/%s/breeding-methods/enable", program.getId()); + Flowable> enableCall = client.exchange( + PUT(enableUrl, enabledSystemMethods).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpResponse enableResponse = enableCall.blockingFirst(); + assertEquals(HttpStatus.OK, enableResponse.getStatus()); + + Map createdBy = new HashMap<>(); + createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_ID, testUser.getId().toString()); + createdBy.put(BrAPIAdditionalInfoFields.CREATED_BY_USER_NAME, testUser.getName()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + String accessionNum = String.valueOf((int)(Math.random()*100)); + BrAPIExternalReference programRef = new BrAPIExternalReference(); + programRef.setReferenceSource(String.format("%s/programs", referenceSource)); + programRef.setReferenceID(program.getId().toString()); + BrAPIExternalReference germIdRef = new BrAPIExternalReference(); + germIdRef.setReferenceSource(referenceSource); + germIdRef.setReferenceID(UUID.randomUUID().toString()); + BrAPIGermplasm germplasm = new BrAPIGermplasm() + .germplasmName("test germ ["+program.getKey()+"-"+accessionNum+"]") + .defaultDisplayName("test germ") + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER, "1") + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_BY, createdBy) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD_ID, systemMethod.getId()) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD, systemMethod.getName()) + .putAdditionalInfoItem(BrAPIAdditionalInfoFields.CREATED_DATE, formatter.format(now)) + .externalReferences(List.of(programRef, germIdRef)) + .accessionNumber(accessionNum); + + assertDoesNotThrow(() -> germplasmService.importBrAPIGermplasm(List.of(germplasm), program.getId(), null)); + + Flowable> enableCallRemove = client.exchange( + PUT(enableUrl, List.of()).cookie(new NettyCookie("phylo-token", "test-registered-user")) + , String.class); + + HttpClientResponseException e = Assertions.assertThrows(HttpClientResponseException.class, () -> enableCallRemove.blockingFirst()); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, e.getStatus()); + + //fetch program breeding methods, and ensure that list still contains the system method we tried to remove + String programMethodsUrl = String.format("/programs/%s/breeding-methods", program.getId()); + Flowable> programCall = client.exchange( + GET(programMethodsUrl).cookie(new NettyCookie("phylo-token", "test-registered-user")), String.class + ); + + HttpResponse programResponse = programCall.blockingFirst(); + assertEquals(HttpStatus.OK, programResponse.getStatus()); + + JsonObject programResult = JsonParser.parseString(programResponse.body()).getAsJsonObject().getAsJsonObject("result"); + List programMethods = gson.fromJson(programResult.getAsJsonArray("data"), new TypeToken>(){}.getType()); + + assertThat(programMethods.size(), greaterThan(0)); + assertThat(programMethods.stream().map(ProgramBreedingMethodEntity::getId).collect(Collectors.toList()), hasItem(systemMethod.getId())); } } From 9e81a6c150bf6f1637d071bc35ea25015f8d0a12 Mon Sep 17 00:00:00 2001 From: timparsons Date: Mon, 9 Jan 2023 16:50:16 -0500 Subject: [PATCH 07/12] [BI-1651] Renaming flyway script --- ...g_methods.sql => V1.0.10__create_program_breeding_methods.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V1.0.9__create_program_breeding_methods.sql => V1.0.10__create_program_breeding_methods.sql} (100%) diff --git a/src/main/resources/db/migration/V1.0.9__create_program_breeding_methods.sql b/src/main/resources/db/migration/V1.0.10__create_program_breeding_methods.sql similarity index 100% rename from src/main/resources/db/migration/V1.0.9__create_program_breeding_methods.sql rename to src/main/resources/db/migration/V1.0.10__create_program_breeding_methods.sql From 156bde6c59cc8bdd7f233387731bdf8de4bd29c4 Mon Sep 17 00:00:00 2001 From: timparsons Date: Mon, 9 Jan 2023 17:00:11 -0500 Subject: [PATCH 08/12] [BI-1651] Removing unused test class --- .../services/impl/BreedingMethodServiceImplTest.java | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java diff --git a/src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java b/src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java deleted file mode 100644 index 97d38b8c9..000000000 --- a/src/test/java/org/breedinginsight/services/impl/BreedingMethodServiceImplTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.breedinginsight.services.impl; - -public class BreedingMethodServiceImplTest { - //TODO -} From 05eb500947f0d36d4ddc7d3131cb3ec63644a3aa Mon Sep 17 00:00:00 2001 From: timparsons Date: Mon, 9 Jan 2023 17:38:06 -0500 Subject: [PATCH 09/12] [BI-1651] updating delete program script for unit tests --- src/test/resources/sql/ProgramControllerIntegrationTest.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/resources/sql/ProgramControllerIntegrationTest.sql b/src/test/resources/sql/ProgramControllerIntegrationTest.sql index eff3cedf3..0c05b39d3 100644 --- a/src/test/resources/sql/ProgramControllerIntegrationTest.sql +++ b/src/test/resources/sql/ProgramControllerIntegrationTest.sql @@ -30,6 +30,8 @@ join bi_user on bi_user.name = 'Test User' limit 1; -- name: DeleteProgram delete from program_ontology where program_id = ?::uuid; delete from program_observation_level where program_id = ?::uuid; +delete from program_breeding_method where program_id = ?::uuid; +delete from program_enabled_breeding_methods where program_id = ?::uuid; delete from program where id = ?::uuid; -- name: InsertManyPrograms From 3b78f84d182ba667a888146bd9b08f4222bd1429 Mon Sep 17 00:00:00 2001 From: timparsons Date: Mon, 9 Jan 2023 22:53:50 -0500 Subject: [PATCH 10/12] [BI-1651] fixing unit tests --- .../api/v1/controller/ProgramControllerIntegrationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/breedinginsight/api/v1/controller/ProgramControllerIntegrationTest.java b/src/test/java/org/breedinginsight/api/v1/controller/ProgramControllerIntegrationTest.java index 44727dbaf..f9367c6db 100644 --- a/src/test/java/org/breedinginsight/api/v1/controller/ProgramControllerIntegrationTest.java +++ b/src/test/java/org/breedinginsight/api/v1/controller/ProgramControllerIntegrationTest.java @@ -642,7 +642,7 @@ public void postProgramsMinimalBodySuccess() throws Exception{ checkMinimalValidProgram(validProgramB, result); - dsl.execute(fp.get("DeleteProgram"), program.getId().toString(), program.getId().toString(), program.getId().toString()); + dsl.execute(fp.get("DeleteProgram"), program.getId().toString(), program.getId().toString(), program.getId().toString(), program.getId().toString(), program.getId().toString()); } @Test @@ -915,7 +915,7 @@ public void archiveProgramsSuccess() { Program program = getProgramById(gson, client, UUID.fromString(newProgramId)); assertEquals(false, program.getActive(), "Inactive flag not set in database"); - dsl.execute(fp.get("DeleteProgram"), newProgramId, newProgramId, newProgramId); + dsl.execute(fp.get("DeleteProgram"), newProgramId, newProgramId, newProgramId, newProgramId, newProgramId); } @Test From 61acf9e14f87c48448518724d6a8750e05c03c53 Mon Sep 17 00:00:00 2001 From: timparsons Date: Tue, 24 Jan 2023 11:01:10 -0500 Subject: [PATCH 11/12] [BI-1651] Addressing PR change requests --- .../brapps/importer/model/base/Germplasm.java | 2 +- .../brapps/importer/GermplasmTemplateMap.java | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java b/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java index 3cafdf87c..c2c74a433 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java +++ b/src/main/java/org/breedinginsight/brapps/importer/model/base/Germplasm.java @@ -143,7 +143,7 @@ public static String constructGermplasmListName(String listName, Program program return String.format("%s [%s-germplasm]", listName, program.getKey()); } - public BrAPIGermplasm constructBrAPIGermplasm(ProgramBreedingMethodEntity breedingMethod, User user) { + private BrAPIGermplasm constructBrAPIGermplasm(ProgramBreedingMethodEntity breedingMethod, User user) { BrAPIGermplasm germplasm = new BrAPIGermplasm(); germplasm.setGermplasmName(getGermplasmName()); germplasm.setDefaultDisplayName(getGermplasmName()); diff --git a/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java b/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java index c5bedc0f4..c686897cb 100644 --- a/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java +++ b/src/test/java/org/breedinginsight/brapps/importer/GermplasmTemplateMap.java @@ -19,6 +19,7 @@ import org.breedinginsight.api.model.v1.request.ProgramRequest; import org.breedinginsight.api.model.v1.request.SpeciesRequest; import org.breedinginsight.api.v1.controller.TestTokenValidator; +import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields; import org.breedinginsight.brapps.importer.model.base.Germplasm; import org.breedinginsight.brapps.importer.model.response.ImportObjectState; import org.breedinginsight.brapps.importer.services.MappingManager; @@ -176,7 +177,7 @@ public void minimalImportUserSpecifiedEntryNumbersSuccess() { for (int i = 0; i < previewRows.size(); i++) { JsonObject germplasm = previewRows.get(i).getAsJsonObject().getAsJsonObject("germplasm").getAsJsonObject("brAPIObject"); germplasmNames.add(germplasm.get("germplasmName").getAsString()); - assertEquals(Integer.toString(i+1), germplasm.getAsJsonObject("additionalInfo").get("importEntryNumber").getAsString(), "Wrong entry number"); + assertEquals(Integer.toString(i+1), germplasm.getAsJsonObject("additionalInfo").get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(), "Wrong entry number"); } // Check the germplasm list @@ -213,7 +214,7 @@ public void fullImportPreviewSuccess() { assertEquals(fileData.getString(i, "Name"), germplasm.get("germplasmName").getAsString()); JsonObject additionalInfo = germplasm.getAsJsonObject("additionalInfo"); // Created Date (not present) - assertTrue(!additionalInfo.has("createdDate"), "createdDate is present, but should not be"); + assertTrue(!additionalInfo.has(BrAPIAdditionalInfoFields.CREATED_DATE), "createdDate is present, but should not be"); // Accession Number (not present) assertTrue(!germplasm.has("accessionNumber"), "accessionNumber is present, but should not be"); // Pedigree (display names) @@ -276,7 +277,7 @@ public void fullImportCommitSuccess() { assertEquals(expectedGermplasmName, germplasm.get("germplasmName").getAsString()); // Created Date JsonObject additionalInfo = germplasm.getAsJsonObject("additionalInfo"); - assertTrue(additionalInfo.has("createdDate"), "createdDate is missing"); + assertTrue(additionalInfo.has(BrAPIAdditionalInfoFields.CREATED_DATE), "createdDate is missing"); // Accession Number assertTrue(germplasm.has("accessionNumber"), "accessionNumber missing"); // Pedigree (germplasm names) @@ -606,7 +607,7 @@ public void headerCaseInsensitive() { for (int i = 0; i < previewRows.size(); i++) { JsonObject germplasm = previewRows.get(i).getAsJsonObject().getAsJsonObject("germplasm").getAsJsonObject("brAPIObject"); germplasmNames.add(germplasm.get("germplasmName").getAsString()); - assertEquals(Integer.toString(i+1), germplasm.getAsJsonObject("additionalInfo").get("importEntryNumber").getAsString(), "Wrong entry number"); + assertEquals(Integer.toString(i+1), germplasm.getAsJsonObject("additionalInfo").get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(), "Wrong entry number"); } // Check the germplasm list @@ -739,16 +740,16 @@ public void checkBasicResponse(JsonObject germplasm, Table fileData, Integer i) assertEquals(fileData.getString(i, "Name"), germplasm.get("defaultDisplayName").getAsString(), "Wrong display name"); // Entry Number JsonObject additionalInfo = germplasm.getAsJsonObject("additionalInfo"); - assertEquals(fileData.getString(i, "Entry No"), additionalInfo.get("importEntryNumber").getAsString(), "Wrong entry number"); + assertEquals(fileData.getString(i, "Entry No"), additionalInfo.get(BrAPIAdditionalInfoFields.GERMPLASM_IMPORT_ENTRY_NUMBER).getAsString(), "Wrong entry number"); // Created By User ID - assertEquals(testUser.getId().toString(), additionalInfo.getAsJsonObject("createdBy").get("userId").getAsString(), "Wrong createdBy userId"); + assertEquals(testUser.getId().toString(), additionalInfo.getAsJsonObject(BrAPIAdditionalInfoFields.CREATED_BY).get(BrAPIAdditionalInfoFields.CREATED_BY_USER_ID).getAsString(), "Wrong createdBy userId"); // Created by User name - assertEquals(testUser.getName(), additionalInfo.getAsJsonObject("createdBy").get("userName").getAsString(), "Wrong createdBy userId"); + assertEquals(testUser.getName(), additionalInfo.getAsJsonObject(BrAPIAdditionalInfoFields.CREATED_BY).get(BrAPIAdditionalInfoFields.CREATED_BY_USER_NAME).getAsString(), "Wrong createdBy userId"); // Breeding Method String breedingMethodName = fileData.getString(i, "Breeding Method"); ProgramBreedingMethodEntity breedingMethod = breedingMethodDAO.findByNameOrAbbreviation(breedingMethodName, validProgram.getId()).get(0); - assertEquals(breedingMethod.getId().toString(), additionalInfo.get("breedingMethodId").getAsString(), "Wrong Breeding Method ID"); - assertEquals(breedingMethod.getName(), additionalInfo.get("breedingMethod").getAsString(), "Wrong Breeding Method name"); + assertEquals(breedingMethod.getId().toString(), additionalInfo.get(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD_ID).getAsString(), "Wrong Breeding Method ID"); + assertEquals(breedingMethod.getName(), additionalInfo.get(BrAPIAdditionalInfoFields.GERMPLASM_BREEDING_METHOD).getAsString(), "Wrong Breeding Method name"); // Seed source assertEquals(fileData.getString(i, "Source"), germplasm.get("seedSource").getAsString(), "Wrong seed source"); // External Reference (user specified) From db68d7b3231fb67249db9131a2777110e4615eef Mon Sep 17 00:00:00 2001 From: timparsons Date: Tue, 24 Jan 2023 11:06:18 -0500 Subject: [PATCH 12/12] [BI-1651] Updating script name --- ...g_methods.sql => V1.0.11__create_program_breeding_methods.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V1.0.10__create_program_breeding_methods.sql => V1.0.11__create_program_breeding_methods.sql} (100%) diff --git a/src/main/resources/db/migration/V1.0.10__create_program_breeding_methods.sql b/src/main/resources/db/migration/V1.0.11__create_program_breeding_methods.sql similarity index 100% rename from src/main/resources/db/migration/V1.0.10__create_program_breeding_methods.sql rename to src/main/resources/db/migration/V1.0.11__create_program_breeding_methods.sql