/* * Copyright 2015-2016 OpenCB * * 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. */ package org.opencb.opencga.catalog.db.mongodb; import com.mongodb.MongoWriteException; import com.mongodb.client.MongoCursor; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; import com.mongodb.client.model.Updates; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; import org.bson.Document; import org.bson.conversions.Bson; import org.opencb.commons.datastore.core.ObjectMap; import org.opencb.commons.datastore.core.Query; import org.opencb.commons.datastore.core.QueryOptions; import org.opencb.commons.datastore.core.QueryResult; import org.opencb.commons.datastore.mongodb.GenericDocumentComplexConverter; import org.opencb.commons.datastore.mongodb.MongoDBCollection; import org.opencb.commons.datastore.mongodb.MongoDBQueryUtils; import org.opencb.opencga.catalog.db.api.CohortDBAdaptor; import org.opencb.opencga.catalog.db.api.DBIterator; import org.opencb.opencga.catalog.db.mongodb.converters.CohortConverter; import org.opencb.opencga.catalog.exceptions.CatalogDBException; import org.opencb.opencga.catalog.models.*; import org.opencb.opencga.catalog.models.acls.permissions.CohortAclEntry; import org.opencb.opencga.core.common.TimeUtils; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.util.*; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; import static org.opencb.opencga.catalog.db.mongodb.MongoDBUtils.*; public class CohortMongoDBAdaptor extends AnnotationMongoDBAdaptor implements CohortDBAdaptor { private final MongoDBCollection cohortCollection; private CohortConverter cohortConverter; private AclMongoDBAdaptor<CohortAclEntry> aclDBAdaptor; public CohortMongoDBAdaptor(MongoDBCollection cohortCollection, MongoDBAdaptorFactory dbAdaptorFactory) { super(LoggerFactory.getLogger(CohortMongoDBAdaptor.class)); this.dbAdaptorFactory = dbAdaptorFactory; this.cohortCollection = cohortCollection; this.cohortConverter = new CohortConverter(); this.aclDBAdaptor = new AclMongoDBAdaptor<>(cohortCollection, cohortConverter, logger); } @Override protected GenericDocumentComplexConverter<? extends Annotable> getConverter() { return cohortConverter; } @Override protected MongoDBCollection getCollection() { return cohortCollection; } @Override public QueryResult<Cohort> insert(Cohort cohort, long studyId, QueryOptions options) throws CatalogDBException { long startTime = startQuery(); dbAdaptorFactory.getCatalogStudyDBAdaptor().checkId(studyId); checkCohortNameExists(studyId, cohort.getName()); long newId = dbAdaptorFactory.getCatalogMetaDBAdaptor().getNewAutoIncrementId(); cohort.setId(newId); Document cohortObject = cohortConverter.convertToStorageType(cohort); cohortObject.append(PRIVATE_STUDY_ID, studyId); cohortObject.append(PRIVATE_ID, newId); try { cohortCollection.insert(cohortObject, null); } catch (MongoWriteException e) { throw ifDuplicateKeyException(() -> CatalogDBException.alreadyExists("Cohort", studyId, "name", cohort.getName(), e), e); } return endQuery("createCohort", startTime, get(newId, options)); } @Override public QueryResult<Cohort> get(long cohortId, QueryOptions options) throws CatalogDBException { return get(new Query(QueryParams.ID.key(), cohortId).append(QueryParams.STATUS_NAME.key(), "!=" + Status.DELETED), options); } @Override public QueryResult<Cohort> getAllInStudy(long studyId, QueryOptions options) throws CatalogDBException { return get(new Query(QueryParams.STUDY_ID.key(), studyId), options); } @Override public QueryResult<Cohort> update(long cohortId, ObjectMap parameters, QueryOptions options) throws CatalogDBException { long startTime = startQuery(); update(new Query(QueryParams.ID.key(), cohortId), parameters); return endQuery("Modify cohort", startTime, get(cohortId, options)); } @Override @Deprecated public QueryResult<AnnotationSet> annotate(long cohortId, AnnotationSet annotationSet, boolean overwrite) throws CatalogDBException { long startTime = startQuery(); QueryResult<Long> count = cohortCollection.count(new Document("annotationSets.name", annotationSet.getName()) .append(PRIVATE_ID, cohortId)); if (overwrite) { if (count.getResult().get(0) == 0) { throw CatalogDBException.idNotFound("AnnotationSet", annotationSet.getName()); } } else { if (count.getResult().get(0) > 0) { throw CatalogDBException.alreadyExists("AnnotationSet", "name", annotationSet.getName()); } } Document object = getMongoDBDocument(annotationSet, "AnnotationSet"); Bson query = new Document(PRIVATE_ID, cohortId); if (overwrite) { ((Document) query).put("annotationSets.name", annotationSet.getName()); } else { ((Document) query).put("annotationSets.name", new Document("$ne", annotationSet.getName())); } Bson update; if (overwrite) { update = Updates.set("annotationSets.$", object); } else { update = Updates.push("annotationSets", object); } QueryResult<UpdateResult> queryResult = cohortCollection.update(query, update, null); if (queryResult.first().getModifiedCount() != 1) { throw CatalogDBException.alreadyExists("AnnotationSet", "name", annotationSet.getName()); } return endQuery("", startTime, Collections.singletonList(annotationSet)); } @Override @Deprecated public QueryResult<AnnotationSet> deleteAnnotation(long cohortId, String annotationId) throws CatalogDBException { long startTime = startQuery(); Cohort cohort = get(cohortId, new QueryOptions("include", "projects.studies.cohorts.annotationSets")).first(); AnnotationSet annotationSet = null; for (AnnotationSet as : cohort.getAnnotationSets()) { if (as.getName().equals(annotationId)) { annotationSet = as; break; } } if (annotationSet == null) { throw CatalogDBException.idNotFound("AnnotationSet", annotationId); } Bson query = new Document(PRIVATE_ID, cohortId); Bson update = Updates.pull("annotationSets", new Document("name", annotationId)); QueryResult<UpdateResult> resultQueryResult = cohortCollection.update(query, update, null); if (resultQueryResult.first().getModifiedCount() < 1) { throw CatalogDBException.idNotFound("AnnotationSet", annotationId); } return endQuery("Delete annotation", startTime, Collections.singletonList(annotationSet)); } // // @Deprecated // @Override // public QueryResult<CohortAclEntry> getCohortAcl(long cohortId, List<String> members) throws CatalogDBException { // long startTime = startQuery(); // // checkId(cohortId); // // Bson match = Aggregates.match(Filters.eq(PRIVATE_ID, cohortId)); // Bson unwind = Aggregates.unwind("$" + QueryParams.ACL.key()); // Bson match2 = Aggregates.match(Filters.in(QueryParams.ACL_MEMBER.key(), members)); // Bson project = Aggregates.project(Projections.include(QueryParams.ID.key(), QueryParams.ACL.key())); // // List<CohortAclEntry> cohortAcl = null; // QueryResult<Document> aggregate = cohortCollection.aggregate(Arrays.asList(match, unwind, match2, project), null); // Cohort cohort = cohortConverter.convertToDataModelType(aggregate.first()); // // if (cohort != null) { // cohortAcl = cohort.getAcl(); // } // // return endQuery("get cohort Acl", startTime, cohortAcl); // } // // @Deprecated // @Override // public QueryResult<CohortAclEntry> setCohortAcl(long cohortId, CohortAclEntry acl, boolean override) throws CatalogDBException { // long startTime = startQuery(); // long studyId = getStudyId(cohortId); // // String member = acl.getMember(); // // // If there is a group in acl.getMember(), we will obtain all the users belonging to the groups and will check if any of them // // already have permissions on its own. // if (member.startsWith("@")) { // Group group = dbAdaptorFactory.getCatalogStudyDBAdaptor().getGroup(studyId, member, Collections.emptyList()).first(); // // // Check if any user already have permissions set on their own. // QueryResult<CohortAclEntry> fileAcl = getAcl(cohortId, group.getUserIds()); // if (fileAcl.getNumResults() > 0) { // throw new CatalogDBException("Error when adding permissions in cohort. At least one user in " + group.getName() // + " has already defined permissions for cohort " + cohortId); // } // } else { // // Check if the members of the new acl already have some permissions set // QueryResult<CohortAclEntry> cohortAcls = getAcl(cohortId, acl.getMember()); // // if (cohortAcls.getNumResults() > 0 && override) { // unsetCohortAcl(cohortId, Arrays.asList(member), Collections.emptyList()); // } else if (cohortAcls.getNumResults() > 0 && !override) { // throw new CatalogDBException("setCohortAcl: " + member + " already had an Acl set. If you " // + "still want to set a new Acl and remove the old one, please use the override parameter."); // } // } // // // Push the new acl to the list of acls. // Document queryDocument = new Document(PRIVATE_ID, cohortId); // Document update = new Document("$push", new Document(QueryParams.ACL.key(), getMongoDBDocument(acl, "CohortAcl"))); // QueryResult<UpdateResult> updateResult = cohortCollection.update(queryDocument, update, null); // // if (updateResult.first().getModifiedCount() == 0) { // throw new CatalogDBException("setCohortAcl: An error occurred when trying to share cohort " + cohortId + " with " + member); // } // // return endQuery("setCohortAcl", startTime, Arrays.asList(acl)); // } // @Override // public void unsetCohortAcl(long cohortId, List<String> members, List<String> permissions) throws CatalogDBException { // // Check that all the members (users) are correct and exist. // checkMembers(dbAdaptorFactory, getStudyId(cohortId), members); // // // Remove the permissions the members might have had // for (String member : members) { // Document query = new Document(PRIVATE_ID, cohortId).append(QueryParams.ACL_MEMBER.key(), member); // Bson update; // if (permissions.size() == 0) { // update = new Document("$pull", new Document("acl", new Document("member", member))); // } else { // update = new Document("$pull", new Document("acl.$.permissions", new Document("$in", permissions))); // } // QueryResult<UpdateResult> updateResult = cohortCollection.update(query, update, null); // if (updateResult.first().getModifiedCount() == 0) { // throw new CatalogDBException("unsetCohortAcl: An error occurred when trying to stop sharing cohort " + cohortId // + " with other " + member + "."); // } // } // //// // Remove possible cohortAcls that might have permissions defined but no users //// Bson queryBson = new Document(QueryParams.ID.key(), cohortId) //// .append(QueryParams.ACL_MEMBER.key(), //// new Document("$exists", true).append("$eq", Collections.emptyList())); //// Bson update = new Document("$pull", new Document("acls", new Document("users", Collections.emptyList()))); //// cohortCollection.update(queryBson, update, null); // } // @Deprecated // @Override // public void unsetCohortAclsInStudy(long studyId, List<String> members) throws CatalogDBException { // // Check that all the members (users) are correct and exist. // checkMembers(dbAdaptorFactory, studyId, members); // // // Remove the permissions the members might have had // for (String member : members) { // Document query = new Document(PRIVATE_STUDY_ID, studyId).append(QueryParams.ACL_MEMBER.key(), member); // Bson update = new Document("$pull", new Document("acl", new Document("member", member))); // cohortCollection.update(query, update, new QueryOptions(MongoDBCollection.MULTI, true)); // } // //// // Remove possible CohortAcls that might have permissions defined but no users //// Bson queryBson = new Document(PRIVATE_STUDY_ID, studyId) //// .append(CatalogSampleDBAdaptor.QueryParams.ACL_MEMBER.key(), //// new Document("$exists", true).append("$eq", Collections.emptyList())); //// Bson update = new Document("$pull", new Document("acls", new Document("users", Collections.emptyList()))); //// cohortCollection.update(queryBson, update, new QueryOptions(MongoDBCollection.MULTI, true)); // } @Override public long getStudyId(long cohortId) throws CatalogDBException { checkId(cohortId); QueryResult queryResult = nativeGet(new Query(QueryParams.ID.key(), cohortId), new QueryOptions(MongoDBCollection.INCLUDE, PRIVATE_STUDY_ID)); if (queryResult.getResult().isEmpty()) { throw CatalogDBException.idNotFound("Cohort", cohortId); } else { return ((Document) queryResult.first()).getLong(PRIVATE_STUDY_ID); } } @Override public QueryResult<Long> count(Query query) throws CatalogDBException { long startTime = startQuery(); return endQuery("Count cohort", startTime, cohortCollection.count(parseQuery(query, false))); } @Override public QueryResult distinct(Query query, String field) throws CatalogDBException { Bson bson = parseQuery(query, false); return cohortCollection.distinct(field, bson); } @Override public QueryResult stats(Query query) { return null; } @Override public QueryResult<Cohort> get(Query query, QueryOptions options) throws CatalogDBException { long startTime = startQuery(); if (!query.containsKey(QueryParams.STATUS_NAME.key())) { query.append(QueryParams.STATUS_NAME.key(), "!=" + Status.TRASHED + ";!=" + Status.DELETED); } Bson bson = parseQuery(query, false); QueryOptions qOptions; if (options != null) { qOptions = options; } else { qOptions = new QueryOptions(); } qOptions = filterOptions(qOptions, FILTER_ROUTE_COHORTS); QueryResult<Cohort> cohortQueryResult = cohortCollection.find(bson, cohortConverter, qOptions); return endQuery("Get cohort", startTime, cohortQueryResult); } @Override public QueryResult nativeGet(Query query, QueryOptions options) throws CatalogDBException { Bson bson = parseQuery(query, false); if (!query.containsKey(QueryParams.STATUS_NAME.key())) { query.append(QueryParams.STATUS_NAME.key(), "!=" + Status.TRASHED + ";!=" + Status.DELETED); } QueryOptions qOptions; if (options != null) { qOptions = options; } else { qOptions = new QueryOptions(); } qOptions = filterOptions(qOptions, FILTER_ROUTE_COHORTS); return cohortCollection.find(bson, qOptions); } @Override public QueryResult<Cohort> update(long id, ObjectMap parameters) throws CatalogDBException { long startTime = startQuery(); update(new Query(QueryParams.ID.key(), id), parameters); return endQuery("Update cohort", startTime, get(id, new QueryOptions())); } @Override public QueryResult<Long> update(Query query, ObjectMap parameters) throws CatalogDBException { long startTime = startQuery(); Map<String, Object> cohortParams = new HashMap<>(); String[] acceptedParams = {QueryParams.DESCRIPTION.key(), QueryParams.NAME.key(), QueryParams.CREATION_DATE.key()}; filterStringParams(parameters, cohortParams, acceptedParams); Map<String, Class<? extends Enum>> acceptedEnums = Collections.singletonMap(QueryParams.TYPE.key(), Study.Type.class); filterEnumParams(parameters, cohortParams, acceptedEnums); String[] acceptedLongListParams = {QueryParams.SAMPLES.key()}; filterLongListParams(parameters, cohortParams, acceptedLongListParams); if (parameters.containsKey(QueryParams.SAMPLES.key())) { for (Long sampleId : parameters.getAsLongList(QueryParams.SAMPLES.key())) { if (!dbAdaptorFactory.getCatalogSampleDBAdaptor().exists(sampleId)) { throw CatalogDBException.idNotFound("Sample", sampleId); } } } String[] acceptedMapParams = {QueryParams.ATTRIBUTES.key(), QueryParams.STATS.key()}; filterMapParams(parameters, cohortParams, acceptedMapParams); //Map<String, Class<? extends Enum>> acceptedEnumParams = Collections.singletonMap(QueryParams.STATUS_NAME.key(), // Cohort.CohortStatus.class); //filterEnumParams(parameters, cohortParams, acceptedEnumParams); if (parameters.containsKey(QueryParams.STATUS_NAME.key())) { cohortParams.put(QueryParams.STATUS_NAME.key(), parameters.get(QueryParams.STATUS_NAME.key())); cohortParams.put(QueryParams.STATUS_DATE.key(), TimeUtils.getTime()); } if (parameters.containsKey("status")) { throw new CatalogDBException("Unable to modify cohort. Use parameter \"" + QueryParams.STATUS_NAME.key() + "\" instead of \"status\""); } if (!cohortParams.isEmpty()) { QueryResult<UpdateResult> update = cohortCollection.update(parseQuery(query, false), new Document("$set", cohortParams), null); return endQuery("Update cohort", startTime, Arrays.asList(update.getNumTotalResults())); } return endQuery("Update cohort", startTime, new QueryResult<>()); } @Override public void delete(long id) throws CatalogDBException { Query query = new Query(QueryParams.ID.key(), id); delete(query); } @Override public void delete(Query query) throws CatalogDBException { QueryResult<DeleteResult> remove = cohortCollection.remove(parseQuery(query, false), null); if (remove.first().getDeletedCount() == 0) { throw CatalogDBException.deleteError("Cohort"); } } @Override public QueryResult<Cohort> delete(long id, QueryOptions queryOptions) throws CatalogDBException { long startTime = startQuery(); checkId(id); // Check if the cohort is active Query query = new Query(QueryParams.ID.key(), id) .append(QueryParams.STATUS_NAME.key(), "!=" + Status.TRASHED + ";!=" + Status.DELETED); if (count(query).first() == 0) { query.put(QueryParams.STATUS_NAME.key(), Status.TRASHED + "," + Status.DELETED); QueryOptions options = new QueryOptions(MongoDBCollection.INCLUDE, QueryParams.STATUS_NAME.key()); Cohort cohort = get(query, options).first(); throw new CatalogDBException("The cohort {" + id + "} was already " + cohort.getStatus().getName()); } // Change the status of the cohort to deleted setStatus(id, Status.TRASHED); query = new Query(QueryParams.ID.key(), id).append(QueryParams.STATUS_NAME.key(), Status.TRASHED); return endQuery("Delete cohort", startTime, get(query, null)); } @Override public QueryResult<Long> delete(Query query, QueryOptions queryOptions) throws CatalogDBException { long startTime = startQuery(); query.append(QueryParams.STATUS_NAME.key(), "!=" + Status.TRASHED + ";!=" + Status.DELETED); QueryResult<Cohort> cohortQueryResult = get(query, new QueryOptions(MongoDBCollection.INCLUDE, QueryParams.ID.key())); for (Cohort cohort : cohortQueryResult.getResult()) { delete(cohort.getId(), queryOptions); } return endQuery("Delete cohort", startTime, Collections.singletonList(cohortQueryResult.getNumTotalResults())); } QueryResult<Cohort> setStatus(long cohortId, String status) throws CatalogDBException { return update(cohortId, new ObjectMap(QueryParams.STATUS_NAME.key(), status)); } QueryResult<Long> setStatus(Query query, String status) throws CatalogDBException { return update(query, new ObjectMap(QueryParams.STATUS_NAME.key(), status)); } @Override public QueryResult<Cohort> remove(long id, QueryOptions queryOptions) throws CatalogDBException { throw new UnsupportedOperationException("Operation not yet supported."); // long startTime = startQuery(); // if (queryOptions == null) { // queryOptions = new QueryOptions(); // } // QueryResult<Long> remove = remove(new Query(QueryParams.ID.key(), id), queryOptions); // if (remove.getResult().get(0) != 1L) { // throw CatalogDBException.removeError("Cohort"); // } // Query query = new Query(QueryParams.ID.key(), id).append(QueryParams.STATUS_NAME.key(), Cohort.CohortStatus.DELETED); // return endQuery("Remove cohort", startTime, get(query, new QueryOptions())); } @Override public QueryResult<Long> remove(Query query, QueryOptions queryOptions) throws CatalogDBException { throw new UnsupportedOperationException("Operation not yet supported."); // long startTime = startQuery(); // query.append(QueryParams.STATUS_NAME.key(), Cohort.CohortStatus.NONE + "," + Cohort.CohortStatus.TRASHED); // // // First we obtain the ids of the cohorts that will be removed. // List<Cohort> cohorts = get(query, new QueryOptions(MongoDBCollection.INCLUDE, // Arrays.asList(QueryParams.ID.key(), QueryParams.STATUS_NAME))).getResult(); // // QueryResult<Long> removed = update(query, new ObjectMap(QueryParams.STATUS_NAME.key(), Cohort.CohortStatus.DELETED)); // // if (removed.first() != cohorts.size()) { // throw CatalogDBException.removeError("Cohort"); // } // // // Remove the instances to cohort that are stored in study // dbAdaptorFactory.getCatalogStudyDBAdaptor().removeCohortDependencies( // cohorts.stream() // .filter(c -> c.getName().getName() != Cohort.CohortStatus.TRASHED) // .map(Cohort::getId).collect(Collectors.toList()) // ); // // return endQuery("Remove cohorts", startTime, Collections.singletonList(removed.first())); } @Override public QueryResult<Cohort> restore(long id, QueryOptions queryOptions) throws CatalogDBException { long startTime = startQuery(); checkId(id); // Check if the cohort is active Query query = new Query(QueryParams.ID.key(), id) .append(QueryParams.STATUS_NAME.key(), Status.TRASHED); if (count(query).first() == 0) { throw new CatalogDBException("The cohort {" + id + "} is not deleted"); } // Change the status of the cohort to deleted setStatus(id, Cohort.CohortStatus.NONE); query = new Query(QueryParams.ID.key(), id); return endQuery("Restore cohort", startTime, get(query, null)); } @Override public QueryResult<Long> restore(Query query, QueryOptions queryOptions) throws CatalogDBException { long startTime = startQuery(); query.put(QueryParams.STATUS_NAME.key(), Status.TRASHED); return endQuery("Restore cohorts", startTime, setStatus(query, Cohort.CohortStatus.NONE)); } // @Override // public QueryResult<Long> updateStatus(Query query, String status) throws CatalogDBException { // long startTime = startQuery(); // QueryResult<UpdateResult> update = cohortCollection.update(parseQuery(query), // Updates.combine( // Updates.set(QueryParams.STATUS_NAME.key(), status), // Updates.set(QueryParams.STATUS_DATE.key(), TimeUtils.getTimeMillis())) // , new QueryOptions()); // return endQuery("Update cohort status", startTime, Collections.singletonList(update.first().getModifiedCount())); // } @Override public DBIterator<Cohort> iterator(Query query, QueryOptions options) throws CatalogDBException { Bson bson = parseQuery(query, false); MongoCursor<Document> iterator = cohortCollection.nativeQuery().find(bson, options).iterator(); return new MongoDBIterator<>(iterator, cohortConverter); } @Override public DBIterator nativeIterator(Query query, QueryOptions options) throws CatalogDBException { Bson bson = parseQuery(query, false); MongoCursor<Document> iterator = cohortCollection.nativeQuery().find(bson, options).iterator(); return new MongoDBIterator<>(iterator); } @Override public QueryResult rank(Query query, String field, int numResults, boolean asc) throws CatalogDBException { Bson bsonQuery = parseQuery(query, false); return rank(cohortCollection, bsonQuery, field, "name", numResults, asc); } @Override public QueryResult groupBy(Query query, String field, QueryOptions options) throws CatalogDBException { Bson bsonQuery = parseQuery(query, false); return groupBy(cohortCollection, bsonQuery, field, "name", options); } @Override public QueryResult groupBy(Query query, List<String> fields, QueryOptions options) throws CatalogDBException { Bson bsonQuery = parseQuery(query, false); return groupBy(cohortCollection, bsonQuery, fields, "name", options); } @Override public void forEach(Query query, Consumer<? super Object> action, QueryOptions options) throws CatalogDBException { Objects.requireNonNull(action); DBIterator<Cohort> catalogDBIterator = iterator(query, options); while (catalogDBIterator.hasNext()) { action.accept(catalogDBIterator.next()); } catalogDBIterator.close(); } private void checkCohortNameExists(long studyId, String cohortName) throws CatalogDBException { QueryResult<Long> count = cohortCollection.count(Filters.and( Filters.eq(PRIVATE_STUDY_ID, studyId), Filters.eq(QueryParams.NAME.key(), cohortName))); if (count.getResult().get(0) > 0) { throw CatalogDBException.alreadyExists("Cohort", "name", cohortName); } } private Bson parseQuery(Query query, boolean isolated) throws CatalogDBException { List<Bson> andBsonList = new ArrayList<>(); List<Bson> annotationList = new ArrayList<>(); // We declare variableMap here just in case we have different annotation queries Map<String, Variable> variableMap = null; if (isolated) { andBsonList.add(new Document("$isolated", 1)); } if (query.containsKey(QueryParams.ANNOTATION.key())) { fixAnnotationQuery(query); } for (Map.Entry<String, Object> entry : query.entrySet()) { String key = entry.getKey().split("\\.")[0]; QueryParams queryParam = QueryParams.getParam(entry.getKey()) != null ? QueryParams.getParam(entry.getKey()) : QueryParams.getParam(key); if (queryParam == null) { continue; } try { switch (queryParam) { case ID: addOrQuery(PRIVATE_ID, queryParam.key(), query, queryParam.type(), andBsonList); break; case STUDY_ID: addOrQuery(PRIVATE_STUDY_ID, queryParam.key(), query, queryParam.type(), andBsonList); break; case ATTRIBUTES: addAutoOrQuery(entry.getKey(), entry.getKey(), query, queryParam.type(), andBsonList); break; case BATTRIBUTES: String mongoKey = entry.getKey().replace(QueryParams.BATTRIBUTES.key(), QueryParams.ATTRIBUTES.key()); addAutoOrQuery(mongoKey, entry.getKey(), query, queryParam.type(), andBsonList); break; case NATTRIBUTES: mongoKey = entry.getKey().replace(QueryParams.NATTRIBUTES.key(), QueryParams.ATTRIBUTES.key()); addAutoOrQuery(mongoKey, entry.getKey(), query, queryParam.type(), andBsonList); break; case VARIABLE_SET_ID: addOrQuery(queryParam.key(), queryParam.key(), query, queryParam.type(), annotationList); break; case ANNOTATION: if (variableMap == null) { long variableSetId = query.getLong(QueryParams.VARIABLE_SET_ID.key()); if (variableSetId > 0) { variableMap = dbAdaptorFactory.getCatalogStudyDBAdaptor().getVariableSet(variableSetId, null).first() .getVariables().stream().collect(Collectors.toMap(Variable::getName, Function.identity())); } } addAnnotationQueryFilter(entry.getKey(), query, variableMap, annotationList); break; case ANNOTATION_SET_NAME: addOrQuery("name", queryParam.key(), query, queryParam.type(), annotationList); break; case SAMPLES: addQueryFilter(queryParam.key(), queryParam.key(), query, queryParam.type(), MongoDBQueryUtils.ComparisonOperator.IN, MongoDBQueryUtils.LogicalOperator.OR, andBsonList); break; case NAME: case TYPE: case CREATION_DATE: case STATUS_NAME: case STATUS_MSG: case STATUS_DATE: case DESCRIPTION: case ACL: case ACL_MEMBER: case ACL_PERMISSIONS: case ANNOTATION_SETS: case VARIABLE_NAME: addAutoOrQuery(queryParam.key(), queryParam.key(), query, queryParam.type(), andBsonList); break; default: break; } } catch (Exception e) { throw new CatalogDBException(e); } } if (annotationList.size() > 0) { Bson projection = Projections.elemMatch(QueryParams.ANNOTATION_SETS.key(), Filters.and(annotationList)); andBsonList.add(projection); } if (andBsonList.size() > 0) { return Filters.and(andBsonList); } else { return new Document(); } } public MongoDBCollection getCohortCollection() { return cohortCollection; } public QueryResult<Long> extractSamplesFromCohorts(Query query, List<Long> sampleIds) throws CatalogDBException { long startTime = startQuery(); QueryResult<Cohort> cohortQueryResult = get(query, new QueryOptions(QueryOptions.INCLUDE, QueryParams.ID.key())); if (cohortQueryResult.getNumResults() > 0) { Bson bsonQuery = parseQuery(query, false); Bson update = new Document("$pull", new Document(QueryParams.SAMPLES.key(), new Document("$in", sampleIds))); QueryOptions multi = new QueryOptions(MongoDBCollection.MULTI, true); QueryResult<UpdateResult> updateQueryResult = cohortCollection.update(bsonQuery, update, multi); // Now we set all the cohorts where a sample has been taken out to status INVALID List<Long> ids = cohortQueryResult.getResult().stream().map(Cohort::getId).collect(Collectors.toList()); setStatus(new Query(QueryParams.ID.key(), ids), Cohort.CohortStatus.INVALID); return endQuery("Extract samples from cohorts", startTime, Collections.singletonList(updateQueryResult.first().getModifiedCount())); } return endQuery("Extract samples from cohorts", startTime, Collections.singletonList(0L)); } @Override public QueryResult<CohortAclEntry> createAcl(long id, CohortAclEntry acl) throws CatalogDBException { long startTime = startQuery(); // CatalogMongoDBUtils.setAcl(id, acl, cohortCollection, "CohortAcl"); return endQuery("create cohort Acl", startTime, Arrays.asList(aclDBAdaptor.createAcl(id, acl))); } @Override public void createAcl(Query query, List<CohortAclEntry> aclEntryList) throws CatalogDBException { Bson queryDocument = parseQuery(query, true); aclDBAdaptor.setAcl(queryDocument, aclEntryList); } @Override public QueryResult<CohortAclEntry> getAcl(long id, List<String> members) throws CatalogDBException { long startTime = startQuery(); // // List<CohortAclEntry> acl = null; // QueryResult<Document> aggregate = CatalogMongoDBUtils.getAcl(id, members, cohortCollection, logger); // Cohort cohort = cohortConverter.convertToDataModelType(aggregate.first()); // // if (cohort != null) { // acl = cohort.getAcl(); // } return endQuery("get cohort Acl", startTime, aclDBAdaptor.getAcl(id, members)); } @Override public void removeAcl(long id, String member) throws CatalogDBException { aclDBAdaptor.removeAcl(id, member); // CatalogMongoDBUtils.removeAcl(id, member, cohortCollection); } @Override public QueryResult<CohortAclEntry> setAclsToMember(long id, String member, List<String> permissions) throws CatalogDBException { long startTime = startQuery(); // CatalogMongoDBUtils.setAclsToMember(id, member, permissions, cohortCollection); return endQuery("Set Acls to member", startTime, Arrays.asList(aclDBAdaptor.setAclsToMember(id, member, permissions))); } @Override public QueryResult<CohortAclEntry> addAclsToMember(long id, String member, List<String> permissions) throws CatalogDBException { long startTime = startQuery(); // CatalogMongoDBUtils.addAclsToMember(id, member, permissions, cohortCollection); return endQuery("Add Acls to member", startTime, Arrays.asList(aclDBAdaptor.addAclsToMember(id, member, permissions))); } @Override public void addAclsToMember(Query query, List<String> members, List<String> permissions) throws CatalogDBException { QueryResult<Cohort> cohortQueryResult = get(query, new QueryOptions(QueryOptions.INCLUDE, QueryParams.ID.key())); List<Long> cohortIds = cohortQueryResult.getResult().stream().map(cohort -> cohort.getId()).collect(Collectors.toList()); if (cohortIds == null || cohortIds.size() == 0) { throw new CatalogDBException("No matches found for query when attempting to add new permissions"); } aclDBAdaptor.addAclsToMembers(cohortIds, members, permissions); } @Override public QueryResult<CohortAclEntry> removeAclsFromMember(long id, String member, List<String> permissions) throws CatalogDBException { // CatalogMongoDBUtils.removeAclsFromMember(id, member, permissions, cohortCollection); long startTime = startQuery(); return endQuery("Remove Acls from member", startTime, Arrays.asList(aclDBAdaptor.removeAclsFromMember(id, member, permissions))); } @Override public void removeAclsFromMember(Query query, List<String> members, @Nullable List<String> permissions) throws CatalogDBException { QueryResult<Cohort> cohortQueryResult = get(query, new QueryOptions(QueryOptions.INCLUDE, QueryParams.ID.key())); List<Long> cohortIds = cohortQueryResult.getResult().stream().map(Cohort::getId).collect(Collectors.toList()); if (cohortIds == null || cohortIds.size() == 0) { throw new CatalogDBException("No matches found for query when attempting to remove permissions"); } aclDBAdaptor.removeAclsFromMembers(cohortIds, members, permissions); } public void removeAclsFromStudy(long studyId, String member) throws CatalogDBException { aclDBAdaptor.removeAclsFromStudy(studyId, member); } }