Skip to content

Commit

Permalink
Supporting germplasmDbIds param in /search/studies & /search/callsets
Browse files Browse the repository at this point in the history
  • Loading branch information
GuilhemSempere committed May 3, 2022
1 parent a82aa2b commit a840bd9
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 67 deletions.
88 changes: 64 additions & 24 deletions src/main/java/org/brapi/v2/api/CallsetsApiController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.brapi.v2.api;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -77,15 +79,19 @@ public ResponseEntity<CallSetsListResponse> searchCallsetsPost( @ApiParam(value
cslr.setMetadata(metadata);

boolean fTriedToAccessForbiddenData = false;
HashMap<String /*module*/, Query> sampleQueryByModule = new HashMap<>();
HashMap<String /*module*/, ArrayList<Criteria>> sampleCritByModule = new HashMap<>();

if ((body.getCallSetDbIds() == null || body.getCallSetDbIds().isEmpty()) && (body.getVariantSetDbIds() == null || body.getVariantSetDbIds().isEmpty())) {
status.setMessage("Some callSetDbIds or variantSetDbIds must be specified as parameter!");
boolean fFilterOnCallSets = body.getCallSetDbIds() != null && !body.getCallSetDbIds().isEmpty();
boolean fFilterOnGermplasm = body.getGermplasmDbIds() != null && !body.getGermplasmDbIds().isEmpty();
boolean fFilterOnVariantSets = body.getVariantSetDbIds() != null && !body.getVariantSetDbIds().isEmpty();

if (!fFilterOnCallSets && !fFilterOnVariantSets && !fFilterOnGermplasm) {
status.setMessage("Some callSetDbIds, germplasmDbIds or variantSetDbIds must be specified as parameter!");
metadata.addStatusItem(status);
httpCode = HttpStatus.BAD_REQUEST;
}
else {
if (body.getVariantSetDbIds() == null || body.getVariantSetDbIds().isEmpty()) { // no variantSets specified, but we have a list of callSets
if (fFilterOnCallSets) {
HashMap<String /*module*/, HashSet<Integer> /*samples, null means all*/> samplesByModule = new HashMap<>();
for (String csId : body.getCallSetDbIds()) {
String[] info = GigwaSearchVariantsRequest.getInfoFromId(csId, 3);
Expand All @@ -96,15 +102,16 @@ public ResponseEntity<CallSetsListResponse> searchCallsetsPost( @ApiParam(value
}
moduleSamples.add(Integer.parseInt(info[2]));
}
for (String module : samplesByModule.keySet()) { // make sure we filter out any samples that are from projects the user is not allowed to see
MongoTemplate mongoTemplate = MongoTemplateManager.get(module);
HashSet<Integer> moduleSamples = samplesByModule.get(module);
Query query = new Query(Criteria.where("_id").in(moduleSamples));

for (String db : samplesByModule.keySet()) { // make sure we filter out any samples that are from projects the user is not allowed to see
MongoTemplate mongoTemplate = MongoTemplateManager.get(db);
HashSet<Integer> moduleSamples = samplesByModule.get(db);
Criteria crit = Criteria.where("_id").in(moduleSamples);
HashMap<Integer, Boolean> projectAccessPermissions = new HashMap<>();
for (GenotypingSample sample : mongoTemplate.find(query, GenotypingSample.class)) {
for (GenotypingSample sample : mongoTemplate.find(new Query(crit), GenotypingSample.class)) {
Boolean fPjAllowed = projectAccessPermissions.get(sample.getProjectId());
if (fPjAllowed == null) {
fPjAllowed = tokenManager.canUserReadProject(token, module, sample.getProjectId());
fPjAllowed = tokenManager.canUserReadProject(token, db, sample.getProjectId());
projectAccessPermissions.put(sample.getProjectId(), fPjAllowed);
}
if (!fPjAllowed) {
Expand All @@ -113,25 +120,58 @@ public ResponseEntity<CallSetsListResponse> searchCallsetsPost( @ApiParam(value
}
}

if (moduleSamples.size() > 0)
sampleQueryByModule.put(module, query);
if (moduleSamples.size() > 0) {
ArrayList<Criteria> moduleCrit = sampleCritByModule.get(db);
if (moduleCrit == null) {
moduleCrit = new ArrayList<>();
sampleCritByModule.put(db, moduleCrit);
}
moduleCrit.add(crit);
}
}
}
else
}

if (fFilterOnGermplasm) {
HashMap<String, HashMap<Integer, Collection<String>>> dbProjectIndividuals = GermplasmApiController.readGermplasmIDs(body.getGermplasmDbIds());
for (String db : dbProjectIndividuals.keySet()) {
HashMap<Integer, Collection<String>> projectIndividuals = dbProjectIndividuals.get(db);
for (int nProjId : projectIndividuals.keySet()) { // make sure at least one germplasm exists in each project before returning it
if (tokenManager.canUserReadProject(token, db, nProjId)) {
ArrayList<Criteria> moduleCrit = sampleCritByModule.get(db);
if (moduleCrit == null) {
moduleCrit = new ArrayList<>();
sampleCritByModule.put(db, moduleCrit);
}
moduleCrit.add(new Criteria().andOperator(Criteria.where(GenotypingSample.FIELDNAME_PROJECT_ID).is(nProjId), Criteria.where(GenotypingSample.FIELDNAME_INDIVIDUAL).in(projectIndividuals.get(nProjId))));
}
}
}
}

if (fFilterOnVariantSets)
for (String variantSetDbId : body.getVariantSetDbIds()) {
String[] info = GigwaSearchVariantsRequest.getInfoFromId(variantSetDbId, 3);
int projId = Integer.parseInt(info[1]);
if (tokenManager.canUserReadProject(token, info[0], projId))
sampleQueryByModule.put(info[0], new Query(new Criteria().andOperator(Criteria.where(GenotypingSample.FIELDNAME_PROJECT_ID).is(projId), Criteria.where(GenotypingSample.FIELDNAME_RUN).is(info[2]))));
else
fTriedToAccessForbiddenData = true;
if (!sampleCritByModule.containsKey(info[0])) { // only look at variantSet IDs if we don't already have samples selected
int projId = Integer.parseInt(info[1]);
if (tokenManager.canUserReadProject(token, info[0], projId)) {
ArrayList<Criteria> moduleCrit = sampleCritByModule.get(info[0]);
if (moduleCrit == null) {
moduleCrit = new ArrayList<>();
sampleCritByModule.put(info[0], moduleCrit);
}
moduleCrit.add(new Criteria().andOperator(Criteria.where(GenotypingSample.FIELDNAME_PROJECT_ID).is(projId), Criteria.where(GenotypingSample.FIELDNAME_RUN).is(info[2])));
}
else
fTriedToAccessForbiddenData = true;
}
}

int nTotalCallSetsEncountered = 0;
for (String module : sampleQueryByModule.keySet()) {
MongoTemplate mongoTemplate = MongoTemplateManager.get(module);
for (String db : sampleCritByModule.keySet()) {
MongoTemplate mongoTemplate = MongoTemplateManager.get(db);
Map<String, Integer> indIdToSampleIdMap = new HashMap<>();
List<GenotypingSample> samples = mongoTemplate.find(sampleQueryByModule.get(module), GenotypingSample.class);
ArrayList<Criteria> critList = sampleCritByModule.get(db);
List<GenotypingSample> samples = mongoTemplate.find(new Query(new Criteria().orOperator(critList.toArray(new Criteria[critList.size()]))), GenotypingSample.class);
for (GenotypingSample sample : samples)
indIdToSampleIdMap.put(sample.getIndividual(), sample.getId());

Expand All @@ -148,10 +188,10 @@ public ResponseEntity<CallSetsListResponse> searchCallsetsPost( @ApiParam(value
GenotypingSample sample = samples.get(i);
nTotalCallSetsEncountered++;
CallSet callset = new CallSet();
callset.setCallSetDbId(module + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getIndividual() + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getId());
callset.setCallSetDbId(db + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getIndividual() + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getId());
callset.setCallSetName(callset.getCallSetDbId());
callset.setSampleDbId(callset.getCallSetDbId());
callset.setVariantSetIds(Arrays.asList(module + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getProjectId() + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getRun()));
callset.setVariantSetIds(Arrays.asList(db + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getProjectId() + GigwaGa4ghServiceImpl.ID_SEPARATOR + sample.getRun()));
final Individual ind = indMap.get(sample.getIndividual());
if (!ind.getAdditionalInfo().isEmpty())
callset.setAdditionalInfo(ind.getAdditionalInfo().keySet().stream().filter(k -> ind.getAdditionalInfo().get(k) != null).collect(Collectors.toMap(k -> k, k -> (List<String>) Arrays.asList(ind.getAdditionalInfo().get(k).toString()))));
Expand Down
57 changes: 25 additions & 32 deletions src/main/java/org/brapi/v2/api/GermplasmApiController.java
Original file line number Diff line number Diff line change
@@ -1,75 +1,46 @@
package org.brapi.v2.api;

import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.brapi.v2.model.Call;
import org.brapi.v2.model.CallListResponse;
import org.brapi.v2.model.ExternalReferences;
import org.brapi.v2.model.ExternalReferencesInner;
import org.brapi.v2.model.Germplasm;
import org.brapi.v2.model.GermplasmListResponse;
import org.brapi.v2.model.GermplasmListResponseResult;
import org.brapi.v2.model.GermplasmMCPD;
import org.brapi.v2.model.GermplasmNewRequest.BiologicalStatusOfAccessionCodeEnum;
import org.brapi.v2.model.GermplasmSearchRequest;
import org.brapi.v2.model.IndexPagination;
import org.brapi.v2.model.ListValue;
import org.brapi.v2.model.Metadata;
import org.brapi.v2.model.MetadataTokenPagination;
import org.brapi.v2.model.Status;
import org.brapi.v2.model.TokenPagination;
import org.brapi.v2.model.GermplasmNewRequest.BiologicalStatusOfAccessionCodeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.threeten.bp.LocalDate;
import org.threeten.bp.format.DateTimeParseException;

import com.fasterxml.jackson.databind.ObjectMapper;

import fr.cirad.io.brapi.BrapiService;
import fr.cirad.mgdb.model.mongo.maintypes.GenotypingProject;
import fr.cirad.mgdb.model.mongo.maintypes.GenotypingSample;
import fr.cirad.mgdb.model.mongo.maintypes.VariantData;
import fr.cirad.mgdb.model.mongo.maintypes.VariantRunData;
import fr.cirad.mgdb.model.mongo.maintypes.VariantRunData.VariantRunDataId;
import fr.cirad.mgdb.model.mongo.subtypes.AbstractVariantData;
import fr.cirad.mgdb.model.mongo.subtypes.SampleGenotype;
import fr.cirad.mgdb.model.mongodao.MgdbDao;
import fr.cirad.mgdb.service.GigwaGa4ghServiceImpl;
import fr.cirad.mgdb.service.IGigwaService;
import fr.cirad.model.GigwaSearchVariantsRequest;
import fr.cirad.tools.mongo.MongoTemplateManager;
import fr.cirad.tools.security.base.AbstractTokenManager;
import fr.cirad.web.controller.rest.BrapiRestController;
import io.swagger.annotations.ApiParam;
import jhi.brapi.api.germplasm.BrapiGermplasm;
import org.brapi.v2.model.ExternalReferences;
import org.brapi.v2.model.ExternalReferencesInner;
import org.brapi.v2.model.GermplasmNewRequestStorageTypes;
import org.brapi.v2.model.GermplasmNewRequestStorageTypes.CodeEnum;

@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2021-03-22T14:25:44.495Z[GMT]")
@CrossOrigin
Expand All @@ -96,6 +67,28 @@ public GermplasmApiController(ObjectMapper objectMapper, HttpServletRequest requ
this.objectMapper = objectMapper;
this.request = request;
}

public static HashMap<String, HashMap<Integer, Collection<String>>> readGermplasmIDs(Collection<String> germplasmDbIds) {
HashMap<String, HashMap<Integer, Collection<String>>> dbProjectIndividuals = new HashMap<>();
for (String gpId : germplasmDbIds) {
String[] info = GigwaSearchVariantsRequest.getInfoFromId(gpId, 3);
int projId = Integer.parseInt(info[1]);

HashMap<Integer, Collection<String>> projectIndividuals = dbProjectIndividuals.get(info[0]);
if (projectIndividuals == null) {
projectIndividuals = new HashMap<>();
dbProjectIndividuals.put(info[0], projectIndividuals);
}

Collection<String> individuals = projectIndividuals.get(projId);
if (individuals == null) {
individuals = new ArrayList<>();
projectIndividuals.put(projId, individuals);
}
individuals.add(info[2]);
}
return dbProjectIndividuals;
}

public ResponseEntity<GermplasmListResponse> searchGermplasmPost(HttpServletResponse response, @ApiParam(value = "Germplasm Search request") @Valid @RequestBody GermplasmSearchRequest body, @ApiParam(value = "HTTP HEADER - Token used for Authorization <strong> Bearer {token_string} </strong>") @RequestHeader(value = "Authorization", required = false) String authorization) throws Exception {
String token = ServerinfoApiController.readToken(authorization);
Expand Down
38 changes: 27 additions & 11 deletions src/main/java/org/brapi/v2/api/StudiesApiController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.brapi.v2.api;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -29,6 +30,7 @@
import org.springframework.web.bind.annotation.RequestHeader;

import fr.cirad.mgdb.model.mongo.maintypes.GenotypingProject;
import fr.cirad.mgdb.model.mongo.maintypes.GenotypingSample;
import fr.cirad.mgdb.service.IGigwaService;
import fr.cirad.model.GigwaSearchVariantsRequest;
import fr.cirad.tools.Helper;
Expand All @@ -52,6 +54,8 @@ public ResponseEntity<StudyListResponse> searchStudiesPost(@ApiParam(value = "St
try {
StudyListResponse slr = new StudyListResponse();
StudyListResponseResult result = new StudyListResponseResult();
Metadata metadata = new Metadata();
slr.setMetadata(metadata);

boolean fGotTrialIDs = body != null && body.getTrialDbIds() != null && !body.getTrialDbIds().isEmpty();
boolean fGotProgramIDs = body != null && body.getProgramDbIds() != null && !body.getProgramDbIds().isEmpty();
Expand All @@ -66,33 +70,45 @@ public ResponseEntity<StudyListResponse> searchStudiesPost(@ApiParam(value = "St
}
moduleProjects.add(Integer.parseInt(info[1]));
}
else if (body.getGermplasmDbIds() != null && !body.getGermplasmDbIds().isEmpty()) {
HashMap<String, HashMap<Integer, Collection<String>>> dbProjectIndividuals = GermplasmApiController.readGermplasmIDs(body.getGermplasmDbIds());
for (String db : dbProjectIndividuals.keySet()) {
HashMap<Integer, Collection<String>> projectIndividuals = dbProjectIndividuals.get(db);
for (int nProjId : projectIndividuals.keySet()) // make sure at least one germplasm exists in each project before returning it
if (MongoTemplateManager.get(db).count(new Query(new Criteria().andOperator(Criteria.where(GenotypingSample.FIELDNAME_PROJECT_ID).is(nProjId), Criteria.where(GenotypingSample.FIELDNAME_INDIVIDUAL).in(projectIndividuals.get(nProjId)))), GenotypingSample.class) > 0) {
HashSet<Integer> moduleProjects = projectsByModule.get(db);
if (moduleProjects == null) {
moduleProjects = new HashSet<>();
projectsByModule.put(db, moduleProjects);
}
moduleProjects.add(nProjId);
}
}
}

for (String module : MongoTemplateManager.getAvailableModules())
if (body.getCommonCropNames() == null || body.getCommonCropNames().isEmpty() || body.getCommonCropNames().contains(Helper.nullToEmptyString(MongoTemplateManager.getTaxonName(module)))) {
if ((!projectsByModule.isEmpty() && !projectsByModule.containsKey(module)) || (fGotTrialIDs && !body.getTrialDbIds().contains(module)) || (fGotProgramIDs && !body.getProgramDbIds().contains(module)))
continue;

for (GenotypingProject pj : MongoTemplateManager.get(module).find(projectsByModule.isEmpty() ? new Query() : new Query(Criteria.where("id_").in(projectsByModule.get(module))), GenotypingProject.class)) {

if (tokenManager.canUserReadProject(token, module, pj.getId()))
result.addDataItem(new Study() {{
setTrialDbId(module);
setStudyDbId(module + IGigwaService.ID_SEPARATOR + pj.getId());
setStudyType("genotype");
setStudyName(pj.getName()); /* variantSets in GA4GH correspond to projects, i.e. studies in BrAPI v2 */
setStudyDescription(pj.getDescription());
}} );
if (tokenManager.canUserReadProject(token, module, pj.getId()))
result.addDataItem(new Study() {{
setTrialDbId(module);
setStudyDbId(module + IGigwaService.ID_SEPARATOR + pj.getId());
setStudyType("genotype");
setStudyName(pj.getName()); /* variantSets in GA4GH correspond to projects, i.e. studies in BrAPI v2 */
setStudyDescription(pj.getDescription());
}} );
}
}

Metadata metadata = new Metadata();
IndexPagination pagination = new IndexPagination();
pagination.setPageSize(result.getData().size());
pagination.setCurrentPage(0);
pagination.setTotalPages(1);
pagination.setTotalCount(result.getData().size());
metadata.setPagination(pagination);
slr.setMetadata(metadata);

slr.setResult(result);
return new ResponseEntity<StudyListResponse>(slr, HttpStatus.OK);
Expand Down

0 comments on commit a840bd9

Please sign in to comment.