Skip to content
Open
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
<guava.version>31.0.1-jre</guava.version>
<okhttp.version>4.9.3</okhttp.version>
<mockito.version>4.3.1</mockito.version>
<brapi-java-client.version>2.1-SNAPSHOT</brapi-java-client.version>
<brapi-java-client.version>2.2-SNAPSHOT</brapi-java-client.version>
<commons-io.version>2.11.0</commons-io.version>
<tika-app.version>2.2.1</tika-app.version>
<!-- Version of apache-poi depends on version of tika. Tika uses these. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,38 @@
import com.google.gson.Gson;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.server.exceptions.InternalServerException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.brapi.client.v2.ApiResponse;
import org.brapi.client.v2.JSON;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.client.v2.modules.phenotype.ObservationLevelNamesApi;
import org.brapi.client.v2.modules.phenotype.ObservationUnitsApi;
import org.brapi.v2.model.pheno.BrAPIObservationUnitHierarchyLevel;
import org.brapi.v2.model.pheno.BrAPIObservationUnitLevelRelationship;
import org.brapi.v2.model.pheno.response.BrAPIObservationLevelListResponse;
import org.brapi.v2.model.pheno.response.BrAPIObservationLevelListResponseResult;
import org.brapi.v2.model.pheno.response.BrAPIObservationLevelSingleResponse;
import org.breedinginsight.daos.ProgramDAO;
import org.breedinginsight.model.DatasetLevel;
import org.breedinginsight.model.Program;
import org.breedinginsight.services.brapi.BrAPIEndpointProvider;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.utilities.BrAPIDAOUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.breedinginsight.utilities.Utilities;

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

@Slf4j
@Singleton
Expand All @@ -46,12 +61,19 @@ public class BrAPIObservationLevelDAO {
private final BrAPIDAOUtil brAPIDAOUtil;
private final Gson gson = new JSON().getGson();

private final BrAPIEndpointProvider brAPIEndpointProvider;
private final ProgramDAO programDAO;

@Inject
public BrAPIObservationLevelDAO(BrAPIDAOUtil brAPIDAOUtil) {
public BrAPIObservationLevelDAO(BrAPIDAOUtil brAPIDAOUtil,
BrAPIEndpointProvider brAPIEndpointProvider,
ProgramDAO programDAO) {
this.brAPIDAOUtil = brAPIDAOUtil;
this.brAPIEndpointProvider = brAPIEndpointProvider;
this.programDAO = programDAO;
}

public HttpResponse<String> createObservationLevelName(Program program, String levelName, DatasetLevel levelOrder, String programDbId) throws ApiException {
public HttpResponse<String> createObservationLevelName(Program program, String levelName, DatasetLevel levelOrder, String programDbId) {
HttpUrl url = HttpUrl.parse(brAPIDAOUtil.getProgramBrAPIBaseUrl(program.getId()))
.newBuilder()
.addPathSegment("observationlevelnames")
Expand All @@ -75,25 +97,90 @@ public HttpResponse<String> createObservationLevelName(Program program, String l
return brAPIDAOUtil.makeCall(request);
}

public BrAPIObservationUnitHierarchyLevel createLevelName(Program program,
String programDbId,
String levelName,
DatasetLevel levelOrder) throws ApiException {
ObservationLevelNamesApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationLevelNamesApi.class);

ApiResponse<BrAPIObservationLevelListResponse> response;


BrAPIObservationUnitHierarchyLevel level = new BrAPIObservationUnitHierarchyLevel();

level.setLevelName(levelName.toLowerCase());
level.setLevelOrder(levelOrder.getValue());
level.setProgramDbId(programDbId);

try {
response = api.observationLevelNamesPost(List.of(level));
} catch (ApiException e) {
log.warn(Utilities.generateApiExceptionLogMessage(e));
throw new InternalServerException("Error making BrAPI call", e);
}

return Optional.of(response)
.map(ApiResponse::getBody)
.map(BrAPIObservationLevelListResponse::getResult)
.map(BrAPIObservationLevelListResponseResult::getData)
.flatMap(data -> data.stream().findFirst())
.orElseThrow(() -> new ApiException(String.format("BrAPI indicated level name [%s] was created but no levelNameDbId was returned upon its creation", levelName)));
}

public List<BrAPIObservationUnitHierarchyLevel> getObservationLevelNamesByProgramId(Program program, String programDbId) {
ObservationLevelNamesApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationLevelNamesApi.class);

ApiResponse<BrAPIObservationLevelListResponse> response;

int pageSize = 100;

try {
response = api.observationLevelNamesGet(programDbId,
false,
0,
pageSize);
} catch (ApiException e) {
log.warn(Utilities.generateApiExceptionLogMessage(e));
throw new InternalServerException("Error making BrAPI call", e);
}

if (response.getBody().getMetadata().getPagination().getTotalCount() > 100) {
throw new InternalServerException(String.format("More level names exist than requested [%s]", pageSize));
}

return response.getBody().getResult().getData();
}

public List<BrAPIObservationUnitHierarchyLevel> getGlobalObservationLevelNames(Program program) {
return getObservationLevelNamesByProgramId(program, null);
}

public void deleteObservationLevelName(Program program, String levelDbId) {
HttpUrl url = HttpUrl.parse(brAPIDAOUtil.getProgramBrAPIBaseUrl(program.getId()))
.newBuilder()
.addPathSegment("observationlevelnames")
.addPathSegment(levelDbId)
.build();
var request = new Request.Builder()
.url(url)
.delete()
.addHeader("Content-Type", "application/json")
.build();
ObservationLevelNamesApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationLevelNamesApi.class);

try {
HttpResponse<String> response = brAPIDAOUtil.makeCall(request);
if (response.getStatus() != HttpStatus.OK && response.getStatus() != HttpStatus.NO_CONTENT && response.getStatus() != HttpStatus.ACCEPTED) {
log.warn("Observation level delete returned status {} for {}", response.getStatus(), levelDbId);
}
} catch (Exception e) {
log.warn("Failed to delete observation level {}", levelDbId, e);
api.observationLevelNameDbIdDelete(levelDbId);
} catch (ApiException e) {
log.warn(Utilities.generateApiExceptionLogMessage(e));
throw new InternalServerException("Error making BrAPI call", e);
}
}

public BrAPIObservationUnitHierarchyLevel updateObservationLevelName(Program program,
String levelNameDbId,
BrAPIObservationUnitHierarchyLevel level) {
ObservationLevelNamesApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(program.getId()), ObservationLevelNamesApi.class);

ApiResponse<BrAPIObservationLevelSingleResponse> response;

try {
response = api.observationLevelNameDbIdPut(levelNameDbId, level);
} catch (ApiException e) {
log.warn(Utilities.generateApiExceptionLogMessage(e));
throw new InternalServerException("Error making BrAPI call", e);
}

return response.getBody().getResult();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.breedinginsight.brapi.v2.services;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.brapi.client.v2.ApiResponse;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.brapi.client.v2.modules.phenotype.ObservationUnitsApi;
import org.brapi.v2.model.pheno.BrAPIObservationUnitHierarchyLevel;
import org.brapi.v2.model.pheno.BrAPIObservationUnitLevelRelationship;
import org.brapi.v2.model.pheno.response.BrAPIObservationLevelListResponse;
import org.breedinginsight.brapi.v2.dao.BrAPIObservationLevelDAO;
import org.breedinginsight.model.DatasetLevel;
import org.breedinginsight.model.Program;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.services.exceptions.DoesNotExistException;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Singleton
public class BrAPIObservationLevelService {
private final BrAPIObservationLevelDAO brAPIObservationLevelDAO;
private final ProgramService programService;


@Inject
public BrAPIObservationLevelService(BrAPIObservationLevelDAO brAPIObservationLevelDAO,
ProgramService programService) {
this.brAPIObservationLevelDAO = brAPIObservationLevelDAO;
this.programService = programService;
}

/**
* @return Pair[GlobalLevelNames, ProgrammaticLevelNames]
*/
public Pair<List<BrAPIObservationUnitHierarchyLevel>, List<BrAPIObservationUnitHierarchyLevel>> getGlobalAndProgrammaticLevelNames(Program program, String brapiProgramDbId) {
List<BrAPIObservationUnitHierarchyLevel> globalLevels = brAPIObservationLevelDAO.getGlobalObservationLevelNames(program);
List<BrAPIObservationUnitHierarchyLevel> programmaticLevels = brAPIObservationLevelDAO.getObservationLevelNamesByProgramId(program, brapiProgramDbId);


return new ImmutablePair<>(globalLevels, programmaticLevels);
}

public List<BrAPIObservationUnitHierarchyLevel> getProgrammaticLevelNames(Program program, String brapiProgramDbId) {
return brAPIObservationLevelDAO.getObservationLevelNamesByProgramId(program, brapiProgramDbId);
}

public BrAPIObservationUnitHierarchyLevel createObservationLevel(Program program,
String brapiProgramDbId,
String levelName,
DatasetLevel levelOrder) throws ApiException {
return brAPIObservationLevelDAO.createLevelName(program, brapiProgramDbId, levelName, levelOrder);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import com.github.filosganga.geogson.model.positions.SinglePosition;
import com.google.gson.JsonObject;
import io.micronaut.context.annotation.Property;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
import io.micronaut.http.server.exceptions.InternalServerException;
import io.micronaut.http.server.types.files.StreamedFile;
Expand Down Expand Up @@ -81,6 +79,7 @@ public class BrAPITrialService {
private final DistributedLockService lockService;
private static final String SHEET_NAME = "Data";
private final DatasetService datasetService;
private final BrAPIObservationLevelService observationLevelService;

@Inject
public BrAPITrialService(@Property(name = "brapi.server.reference-source") String referenceSource,
Expand All @@ -96,7 +95,8 @@ public BrAPITrialService(@Property(name = "brapi.server.reference-source") Strin
BrAPIGermplasmDAO germplasmDAO,
FileMappingUtil fileMappingUtil,
DistributedLockService lockService,
DatasetService datasetService) {
DatasetService datasetService,
BrAPIObservationLevelService observationLevelService) {

this.referenceSource = referenceSource;
this.trialDAO = trialDAO;
Expand All @@ -112,6 +112,7 @@ public BrAPITrialService(@Property(name = "brapi.server.reference-source") Strin
this.fileMappingUtil = fileMappingUtil;
this.lockService = lockService;
this.datasetService = datasetService;
this.observationLevelService = observationLevelService;
}

public List<BrAPITrial> getExperiments(UUID programId) throws ApiException, DoesNotExistException {
Expand Down Expand Up @@ -466,14 +467,13 @@ public Dataset createSubEntityDataset(Program program, UUID experimentId, SubEnt
}

String programBrapiDbId = program.getBrapiProgram() != null ? program.getBrapiProgram().getProgramDbId() : null;
HttpResponse<String> levelResponse = observationLevelDAO.createObservationLevelName(program, datasetName, DatasetLevel.SUB_OBS_UNIT, programBrapiDbId);

// 409 and 200 are expected response codes, anything else error out
// 409 means level already exists so we just use the name in OUs
// 200 means level was created successfully and can use the name in OUs
if (levelResponse.getStatus() != HttpStatus.CONFLICT && levelResponse.getStatus() != HttpStatus.OK) {
throw new ApiException(levelResponse.getStatus().getCode(), "Unable to create observation level: " + levelResponse.getStatus().getReason());
}
String subEntityLevelNameDbId = datasetService.getOrCreateLevelNameForDataset(program,
programBrapiDbId,
datasetName,
DatasetLevel.SUB_OBS_UNIT
);


List<BrAPIObservationUnit> expOUs = ouDAO.getObservationUnitsForDataset(topLevelDataset.getId().toString(), program);
for (BrAPIObservationUnit expUnit : expOUs) {
Expand All @@ -484,14 +484,14 @@ public Dataset createSubEntityDataset(Program program, UUID experimentId, SubEnt
for (int i=1; i<=request.getRepeatedMeasures(); i++) {
subObsUnits.add(
createSubObservationUnit(
datasetName,
Integer.toString(i),
program,
envSeqValue,
expUnit,
this.referenceSource,
subEntityDatasetId,
UUID.randomUUID()
UUID.randomUUID(),
subEntityLevelNameDbId
)
);
}
Expand Down Expand Up @@ -529,14 +529,14 @@ public Dataset createSubEntityDataset(Program program, UUID experimentId, SubEnt
}

public BrAPIObservationUnit createSubObservationUnit(
String subEntityDatasetName,
String subUnitId,
Program program,
String seqVal,
BrAPIObservationUnit expUnit,
String referenceSource,
UUID datasetId,
UUID id
UUID id,
String subEntityLevelNameDbId
) {

BrAPIObservationUnit observationUnit = new BrAPIObservationUnit();
Expand Down Expand Up @@ -612,42 +612,39 @@ public BrAPIObservationUnit createSubObservationUnit(

// ObservationLevel entry for Sub-Obs Unit.
BrAPIObservationUnitLevelRelationship level = new BrAPIObservationUnitLevelRelationship();
level.setLevelName(subEntityDatasetName);
level.setLevelNameDbId(subEntityLevelNameDbId);
level.setLevelCode(Utilities.appendProgramKey(subUnitId, program.getKey(), seqVal));
level.setLevelOrder(DatasetLevel.SUB_OBS_UNIT.getValue());
position.setObservationLevel(level);

// ObservationLevelRelationships.
List<BrAPIObservationUnitLevelRelationship> levelRelationships = new ArrayList<>();
// TODO: Figure out if we actually need to add the sub entity level to the level relationships BI-2823
levelRelationships.add(level);
// ObservationLevelRelationships for block.
BrAPIObservationUnitLevelRelationship expBlockLevel = expUnit.getObservationUnitPosition()
.getObservationLevelRelationships().stream()
.filter(x -> x.getLevelName().equals(BrAPIConstants.REPLICATE.getValue())).findFirst().orElse(null);
if (expBlockLevel != null) {
BrAPIObservationUnitLevelRelationship blockLevel = new BrAPIObservationUnitLevelRelationship();
blockLevel.setLevelName(expBlockLevel.getLevelName());
blockLevel.setLevelCode(expBlockLevel.getLevelCode());
blockLevel.setLevelOrder(expBlockLevel.getLevelOrder());
levelRelationships.add(blockLevel);
}
// ObservationLevelRelationships for rep.
BrAPIObservationUnitLevelRelationship expRepLevel = expUnit.getObservationUnitPosition()
.getObservationLevelRelationships().stream()
.filter(x -> x.getLevelName().equals(BrAPIConstants.BLOCK.getValue())).findFirst().orElse(null);
.filter(x -> x.getLevelName().equals(BrAPIConstants.REPLICATE.getValue())).findFirst().orElse(null);
if (expRepLevel != null) {
BrAPIObservationUnitLevelRelationship repLevel = new BrAPIObservationUnitLevelRelationship();
repLevel.setLevelName(expRepLevel.getLevelName());
repLevel.setLevelNameDbId(expRepLevel.getLevelNameDbId());
repLevel.setLevelCode(expRepLevel.getLevelCode());
repLevel.setLevelOrder(expRepLevel.getLevelOrder());
levelRelationships.add(repLevel);
}
// ObservationLevelRelationships for block.
BrAPIObservationUnitLevelRelationship expBlockLevel = expUnit.getObservationUnitPosition()
.getObservationLevelRelationships().stream()
.filter(x -> x.getLevelName().equals(BrAPIConstants.BLOCK.getValue())).findFirst().orElse(null);
if (expBlockLevel != null) {
BrAPIObservationUnitLevelRelationship blockLevel = new BrAPIObservationUnitLevelRelationship();
blockLevel.setLevelNameDbId(expBlockLevel.getLevelNameDbId());
blockLevel.setLevelCode(expBlockLevel.getLevelCode());
levelRelationships.add(blockLevel);
}
// ObservationLevelRelationships for top-level Exp Unit linking.
BrAPIObservationUnitLevelRelationship expUnitLevel = new BrAPIObservationUnitLevelRelationship();
expUnitLevel.setLevelName(expUnit.getObservationUnitPosition().getObservationLevel().getLevelName().toLowerCase());
expUnitLevel.setLevelNameDbId(expUnit.getObservationUnitPosition().getObservationLevel().getLevelNameDbId());
String expUnitUUID = Utilities.getExternalReference(expUnit.getExternalReferences(), referenceSource, ExternalReferenceSource.OBSERVATION_UNITS).orElseThrow().getReferenceId();
expUnitLevel.setLevelCode(Utilities.appendProgramKey(expUnitUUID, program.getKey(), seqVal));
expUnitLevel.setLevelOrder(DatasetLevel.EXP_UNIT.getValue());
levelRelationships.add(expUnitLevel);
position.setObservationLevelRelationships(levelRelationships);

Expand Down
Loading