Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ public final class BrAPIAdditionalInfoFields {
public static final String OBSERVATION_DATASET_ID = "observationDatasetId";
public static final String FEMALE_PARENT_UNKNOWN = "femaleParentUnknown";
public static final String MALE_PARENT_UNKNOWN = "maleParentUnknown";

public static final String TREATMENTS = "treatments";
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@

package org.breedinginsight.brapps.importer.daos;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import io.micronaut.context.annotation.Property;
import org.brapi.client.v2.JSON;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.client.v2.modules.phenotype.ObservationUnitsApi;
import org.brapi.v2.model.pheno.BrAPIObservationTreatment;
import org.brapi.v2.model.pheno.BrAPIObservationUnit;
import org.brapi.v2.model.pheno.request.BrAPIObservationUnitSearchRequest;
import org.breedinginsight.brapi.v2.constants.BrAPIAdditionalInfoFields;
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.services.ExternalReferenceSource;
import org.breedinginsight.daos.ProgramDAO;
Expand All @@ -34,6 +41,7 @@
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Type;
import java.util.*;

@Singleton
Expand All @@ -46,6 +54,9 @@ public class BrAPIObservationUnitDAO {

private final String referenceSource;

private final Gson gson = new JSON().getGson();
private final Type treatmentlistType = new TypeToken<ArrayList<BrAPIObservationTreatment>>(){}.getType();

@Inject
public BrAPIObservationUnitDAO(ProgramDAO programDAO, ImportDAO importDAO, BrAPIDAOUtil brAPIDAOUtil, BrAPIEndpointProvider brAPIEndpointProvider, ProgramService programService, @Property(name = "brapi.server.reference-source") String referenceSource) {
this.programDAO = programDAO;
Expand All @@ -64,17 +75,19 @@ public List<BrAPIObservationUnit> getObservationUnitByName(List<String> observat
BrAPIObservationUnitSearchRequest observationUnitSearchRequest = new BrAPIObservationUnitSearchRequest();
observationUnitSearchRequest.programDbIds(List.of(program.getBrapiProgram().getProgramDbId()));
observationUnitSearchRequest.observationUnitNames(observationUnitNames);
ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationUnitsApi.class);
return brAPIDAOUtil.search(
api::searchObservationunitsPost,
api::searchObservationunitsSearchResultsDbIdGet,
observationUnitSearchRequest
);

return searchObservationUnitsAndProcess(observationUnitSearchRequest, program.getId());
}

/**
* Create observation units, mutates brAPIObservationUnitList
*/
public List<BrAPIObservationUnit> createBrAPIObservationUnits(List<BrAPIObservationUnit> brAPIObservationUnitList, UUID programId, ImportUpload upload) throws ApiException {
ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationUnitsApi.class);
return brAPIDAOUtil.post(brAPIObservationUnitList, upload, api::observationunitsPost, importDAO::update);
preprocessObservationUnits(brAPIObservationUnitList);
List<BrAPIObservationUnit> ous = brAPIDAOUtil.post(brAPIObservationUnitList, upload, api::observationunitsPost, importDAO::update);
processObservationUnits(ous);
return ous;
}

public List<BrAPIObservationUnit> getObservationUnitsById(Collection<String> observationUnitExternalIds, Program program) throws ApiException {
Expand All @@ -88,10 +101,7 @@ public List<BrAPIObservationUnit> getObservationUnitsById(Collection<String> obs
observationUnitSearchRequest.externalReferenceIDs(new ArrayList<>(observationUnitExternalIds));
observationUnitSearchRequest.externalReferenceSources(List.of(String.format("%s/%s", referenceSource, ExternalReferenceSource.OBSERVATION_UNITS.getName())));

ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationUnitsApi.class);
return brAPIDAOUtil.search(api::searchObservationunitsPost,
api::searchObservationunitsSearchResultsDbIdGet,
observationUnitSearchRequest);
return searchObservationUnitsAndProcess(observationUnitSearchRequest, program.getId());
}

public List<BrAPIObservationUnit> getObservationUnitsForStudyDbId(@NotNull String studyDbId, Program program) throws ApiException {
Expand All @@ -100,10 +110,7 @@ public List<BrAPIObservationUnit> getObservationUnitsForStudyDbId(@NotNull Strin
.getProgramDbId()));
observationUnitSearchRequest.studyDbIds(List.of(studyDbId));

ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationUnitsApi.class);
return brAPIDAOUtil.search(api::searchObservationunitsPost,
api::searchObservationunitsSearchResultsDbIdGet,
observationUnitSearchRequest);
return searchObservationUnitsAndProcess(observationUnitSearchRequest, program.getId());
}
public List<BrAPIObservationUnit> getObservationUnitsForTrialDbId(@NotNull UUID programId, @NotNull String trialDbId) throws ApiException, DoesNotExistException {
Program program = programService.getById(programId).orElseThrow(() -> new DoesNotExistException("Program id does not exist"));
Expand All @@ -113,9 +120,47 @@ public List<BrAPIObservationUnit> getObservationUnitsForTrialDbId(@NotNull UUID
.getProgramDbId()));
observationUnitSearchRequest.trialDbIds(List.of(trialDbId));

ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationUnitsApi.class);
return brAPIDAOUtil.search(api::searchObservationunitsPost,
return searchObservationUnitsAndProcess(observationUnitSearchRequest, programId);
}


/**
* Perform observation unit search and process returned observation units to handle any modifications to the data
* to be returned by bi-api
*/
private List<BrAPIObservationUnit> searchObservationUnitsAndProcess(BrAPIObservationUnitSearchRequest request, UUID programId) throws ApiException {

ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationUnitsApi.class);
List<BrAPIObservationUnit> brapiObservationUnits = brAPIDAOUtil.search(api::searchObservationunitsPost,
api::searchObservationunitsSearchResultsDbIdGet,
observationUnitSearchRequest);
request);

processObservationUnits(brapiObservationUnits);
return brapiObservationUnits;
}

private void processObservationUnits(List<BrAPIObservationUnit> brapiObservationUnits) {

// if has treatments in additionalInfo, copy to treatments property
for (BrAPIObservationUnit ou : brapiObservationUnits) {
JsonObject additionalInfo = ou.getAdditionalInfo();
if (additionalInfo != null) {
JsonElement treatmentsElement = additionalInfo.get(BrAPIAdditionalInfoFields.TREATMENTS);
if (treatmentsElement != null) {
List<BrAPIObservationTreatment> treatments = gson.fromJson(treatmentsElement, treatmentlistType);
ou.setTreatments(treatments);
}
}
}
}

private void preprocessObservationUnits(List<BrAPIObservationUnit> brapiObservationUnits) {
// add treatments to additional info
for (BrAPIObservationUnit obsUnit : brapiObservationUnits) {
List<BrAPIObservationTreatment> treatments = obsUnit.getTreatments();
if (treatments != null) {
obsUnit.putAdditionalInfoItem(BrAPIAdditionalInfoFields.TREATMENTS, treatments);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package org.breedinginsight.brapps.importer.daos;

import com.google.gson.Gson;
import io.kowalski.fannypack.FannyPack;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import lombok.SneakyThrows;
import org.brapi.client.v2.JSON;
import org.brapi.v2.model.pheno.BrAPIObservationTreatment;
import org.brapi.v2.model.pheno.BrAPIObservationUnit;
import org.breedinginsight.BrAPITest;
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.ImportProgress;
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.dao.db.tables.pojos.SpeciesEntity;
import org.breedinginsight.daos.SpeciesDAO;
import org.breedinginsight.daos.UserDAO;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.User;
import org.breedinginsight.services.ProgramService;
import org.jooq.DSLContext;
import org.junit.jupiter.api.*;

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

import static org.breedinginsight.TestUtils.insertAndFetchTestProgram;
import static org.junit.jupiter.api.Assertions.assertEquals;

@MicronautTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BrAPIObservationUnitDAOTest extends BrAPITest {

private FannyPack fp;

@Inject
private DSLContext dsl;

@Inject
private SpeciesDAO speciesDAO;

@Inject
private UserDAO userDAO;

@Inject
private BrAPIObservationUnitDAO obsUnitDAO;

@Inject
private ProgramService programService;

private Program validProgram;

private Gson gson;
private ImportUpload upload;

private BrAPIObservationTreatment testTreatment;

@Inject
@Client("/${micronaut.bi.api.version}")
RxHttpClient biClient;

@BeforeAll
@SneakyThrows
public void setup() {

ImportProgress progress = ImportProgress.builder().build();

upload = ImportUpload.uploadBuilder()
.progress(progress)
.build();

gson = new JSON().getGson();

// Add species needed to create program
fp = FannyPack.fill("src/test/resources/sql/brapi/species.sql");
super.getBrapiDsl().execute(fp.get("InsertSpecies"));
SpeciesEntity validSpecies = speciesDAO.findAll().get(0);

// Insert system admin role so can create program
FannyPack securityFp = FannyPack.fill("src/test/resources/sql/ProgramSecuredAnnotationRuleIntegrationTest.sql");
User testUser = userDAO.getUserByOrcId(TestTokenValidator.TEST_USER_ORCID).get();
dsl.execute(securityFp.get("InsertSystemRoleAdmin"), testUser.getId().toString());

SpeciesRequest speciesRequest = SpeciesRequest.builder()
.commonName(validSpecies.getCommonName())
.id(validSpecies.getId())
.build();

ProgramRequest program = ProgramRequest.builder()
.name("Test Program")
.species(speciesRequest)
.key("TEST")
.build();

// create test program
validProgram = insertAndFetchTestProgram(gson, biClient, program);
// updated with brapi db id
validProgram = programService.getById(validProgram.getId()).get();

testTreatment = new BrAPIObservationTreatment();
testTreatment.setFactor("ou1 treatment");
}

@Test
@SneakyThrows
@Order(1)
public void testCreateObservationUnitAdditionalInfoSingleTreatmentFactor() {
// create observation unit with treatments only in additional info to simulate breedbase not populating
// treatments field
BrAPIObservationUnit ou1 = new BrAPIObservationUnit();
ou1.setObservationUnitName("test1");
ou1.putAdditionalInfoItem(BrAPIAdditionalInfoFields.TREATMENTS, List.of(testTreatment));
Copy link
Member

Choose a reason for hiding this comment

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

Should this test be updated to set the treatments in the Treatments field rather than in the additionalInfo?

Copy link
Member Author

Choose a reason for hiding this comment

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

In this test I wanted to simulate what breedbase would do which would be to only have the treatments in the additionalinfo and not the treatments field.

ou1.setProgramDbId(validProgram.getBrapiProgram().getProgramDbId());

List<BrAPIObservationUnit> ous = List.of(ou1);
List<BrAPIObservationUnit> createdOus = obsUnitDAO.createBrAPIObservationUnits(ous, validProgram.getId(), upload);
singleTreatmentAsserts(createdOus, testTreatment);
}

@Test
@SneakyThrows
@Order(2)
public void testGetObservationUnitAdditionalInfoSingleTreatmentFactor() {
List<BrAPIObservationUnit> createdOus = obsUnitDAO.getObservationUnitByName(List.of("test1"), validProgram);
singleTreatmentAsserts(createdOus, testTreatment);
}

private void singleTreatmentAsserts(List<BrAPIObservationUnit> obsUnits, BrAPIObservationTreatment expectedTreatment) {
assertEquals(1, obsUnits.size(), "Expected 1 observation unit");

BrAPIObservationUnit ou = obsUnits.get(0);
List<BrAPIObservationTreatment> treatments = ou.getTreatments();
assertEquals(1, treatments.size(), "Expected treatments property");

BrAPIObservationTreatment treatment = treatments.get(0);
assertEquals(expectedTreatment, treatment, "Expected treatments to be same");
}

}