diff --git a/build.gradle.kts b/build.gradle.kts index 7d841d5..c75e94c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { annotationProcessor("org.projectlombok:lombok") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("de.flapdoodle.embed:de.flapdoodle.embed.mongo.spring30x:4.6.1") + } //dependencyManagement { @@ -61,12 +62,6 @@ testing { implementation("org.springframework.boot:spring-boot-starter-web") } -// sources { -// java { -// setSrcDirs(listOf("src/integrationTest/java")) -// } -// } - targets { all { testTask.configure { diff --git a/erd.md b/erd.md new file mode 100644 index 0000000..289c57e --- /dev/null +++ b/erd.md @@ -0,0 +1,33 @@ +```mermaid +erDiagram + Cohort { + string name + number enrollment + + } + + Dataset { + string name + URL url + } + + StandardField { + string name + type type + ontology ontology + } + + CohortField { + string category + string name + type type + range range + MappingStrategy mappingStrategy + } + + + + CohortField 1--1 StandardField: "" + Cohort 1--1+ CohortField: "" + Cohort 1--1+ Dataset: "" +``` \ No newline at end of file diff --git a/src/integrationTest/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepositoryIntegrationTest.java b/src/integrationTest/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepositoryIntegrationTest.java index d83f881..a3eb1de 100644 --- a/src/integrationTest/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepositoryIntegrationTest.java +++ b/src/integrationTest/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepositoryIntegrationTest.java @@ -19,7 +19,7 @@ class CohortSearchRepositoryIntegrationTest { @Autowired private CohortService cohortService; @Autowired - private CohortSearchRepository cohortSearchRepository; + private CohortRepository cohortSearchRepository; @Test @@ -36,7 +36,7 @@ void findPage() { cohort.setAcronym("CHILD"); cohortService.saveCohort(cohort); - Page page = cohortSearchRepository.findPageWithFilters(PageRequest.of(0, 5), "CohortSearchRepositoryIntegrationTest", "cohortName", Collections.emptyList()); + Page page = cohortSearchRepository.findByFilters(PageRequest.of(0, 5), "CohortSearchRepositoryIntegrationTest", "cohortName", Collections.emptyList()); Assertions.assertTrue(page.getSize() > 1); Assertions.assertEquals("SearchRepositoryIntegrationTest_freeTextSearch_1", page.getContent().get(0).getCohortName()); } diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortRepository.java index 039d0d2..384caec 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortRepository.java @@ -8,6 +8,6 @@ import uk.ac.ebi.biosamples.cohortatlas.model.Cohort; @Repository -public interface CohortRepository extends MongoRepository { +public interface CohortRepository extends MongoRepository, SearchRepository { Page findAllBy(TextCriteria criteria, Pageable pageable); } diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepository.java index e634c9c..2ff751c 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/CohortSearchRepository.java @@ -1,24 +1,23 @@ package uk.ac.ebi.biosamples.cohortatlas.repository; +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.support.PageableExecutionUtils; -import org.springframework.stereotype.Repository; import uk.ac.ebi.biosamples.cohortatlas.model.Cohort; import java.util.List; -@Repository -public class CohortSearchRepository extends SearchRepository { +@RequiredArgsConstructor +public class CohortSearchRepository implements SearchRepository { - public CohortSearchRepository(MongoTemplate mongoTemplate) { - super(mongoTemplate); - } + private final SearchQueryHelper searchQueryHelper = new SearchQueryHelper(); + protected MongoTemplate mongoTemplate; - public Page findPageWithFilters(Pageable page, String text, String sort, List filters) { - Query query = getSearchQuery(page, text, sort, filters); + public Page findByFilters(Pageable page, String text, String sort, List filters) { + Query query = searchQueryHelper.getSearchQuery(page, text, sort, filters); List cohorts = mongoTemplate.find(query, Cohort.class); return PageableExecutionUtils.getPage(cohorts, page, diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldRepository.java index 6f0be77..53b2726 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldRepository.java @@ -8,7 +8,7 @@ import java.util.List; import java.util.Map; -public interface FieldRepository extends MongoRepository { +public interface FieldRepository extends MongoRepository, SearchRepository { List findByCohort(String cohort); @Aggregation(pipeline = { diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldSearchRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldSearchRepository.java index 5d41cba..ec528dc 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldSearchRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/FieldSearchRepository.java @@ -1,5 +1,6 @@ package uk.ac.ebi.biosamples.cohortatlas.repository; +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.core.MongoTemplate; @@ -10,14 +11,13 @@ import java.util.List; -@Repository -public class FieldSearchRepository extends SearchRepository { - public FieldSearchRepository(MongoTemplate mongoTemplate) { - super(mongoTemplate); - } +@RequiredArgsConstructor +public class FieldSearchRepository implements SearchRepository { + protected MongoTemplate mongoTemplate; + private final SearchQueryHelper searchQueryHelper = new SearchQueryHelper(); - public Page findFieldPageWithFilters(Pageable page, String text, String sort, List filters) { - Query query = getSearchQuery(page, text, sort, filters); + public Page findByFilters(Pageable page, String text, String sort, List filters) { + Query query = searchQueryHelper.getSearchQuery(page, text, sort, filters); List cohorts = mongoTemplate.find(query, DictionaryField.class); return PageableExecutionUtils.getPage(cohorts, page, diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipRepository.java index 1530a43..4253169 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipRepository.java @@ -4,6 +4,6 @@ import uk.ac.ebi.biosamples.cohortatlas.model.DictionaryField; import uk.ac.ebi.biosamples.cohortatlas.model.Relationship; -public interface RelationshipRepository extends MongoRepository { +public interface RelationshipRepository extends MongoRepository, SearchRepository { } diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipSearchRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipSearchRepository.java index 82b28b7..061e42f 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipSearchRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/RelationshipSearchRepository.java @@ -1,5 +1,6 @@ package uk.ac.ebi.biosamples.cohortatlas.repository; +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.core.MongoTemplate; @@ -10,14 +11,13 @@ import java.util.List; -@Repository -public class RelationshipSearchRepository extends CohortSearchRepository { - public RelationshipSearchRepository(MongoTemplate mongoTemplate) { - super(mongoTemplate); - } +@RequiredArgsConstructor +public class RelationshipSearchRepository implements SearchRepository { + private final SearchQueryHelper searchQueryHelper = new SearchQueryHelper(); + protected MongoTemplate mongoTemplate; - public Page findFieldPageWithFilters(Pageable page, String text, String sort, List filters) { - Query query = getSearchQuery(page, text, sort, filters); + public Page findByFilters(Pageable page, String text, String sort, List filters) { + Query query = searchQueryHelper.getSearchQuery(page, text, sort, filters); List relationships = mongoTemplate.find(query, Relationship.class); return PageableExecutionUtils.getPage(relationships, page, diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchQueryHelper.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchQueryHelper.java new file mode 100644 index 0000000..337e67a --- /dev/null +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchQueryHelper.java @@ -0,0 +1,53 @@ +package uk.ac.ebi.biosamples.cohortatlas.repository; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.TextCriteria; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.util.List; + +public class SearchQueryHelper { + public SearchQueryHelper() { + } + + public Query getSearchQuery(Pageable page, String text, String sort, List filters) { + Query query = new Query().with(page); + populateQueryWithSort(query, sort); + populateQueryWithFreeTextSearch(query, text); + populateQueryWithFilters(query, filters); + return query; + } + + void populateQueryWithSort(Query query, String sort) { + if (StringUtils.hasText(sort)) { + query.with(Sort.by(sort).ascending()); + } + } + + void populateQueryWithFreeTextSearch(Query query, String text) { + if (StringUtils.hasText(text)) { + query.addCriteria(TextCriteria.forDefaultLanguage().matchingAny(text)); + } + } + + void populateQueryWithFilters(Query query, List filters) { + if (CollectionUtils.isEmpty(filters)) { + return; + } + + for (String filter : filters) { + String[] filterParts = filter.split(":"); + if (filterParts.length > 1) { + String field = filterParts[0]; + String value = filterParts[1]; + query.addCriteria(Criteria.where(field).is(value)); + } else { + throw new IllegalArgumentException("filter should contain a colon"); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchRepository.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchRepository.java index 62bdf52..2275ab7 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchRepository.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/repository/SearchRepository.java @@ -2,60 +2,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -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.data.mongodb.core.query.TextCriteria; -import org.springframework.data.support.PageableExecutionUtils; -import org.springframework.stereotype.Repository; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; import uk.ac.ebi.biosamples.cohortatlas.model.Cohort; import java.util.List; -@Repository -public abstract class SearchRepository { - protected final MongoTemplate mongoTemplate; +public interface SearchRepository { - public SearchRepository(MongoTemplate mongoTemplate) { - this.mongoTemplate = mongoTemplate; - } + Page findByFilters(Pageable page, String text, String sort, List filters); - protected Query getSearchQuery(Pageable page, String text, String sort, List filters) { - Query query = new Query().with(page); - populateQueryWithSort(query, sort); - populateQueryWithFreeTextSearch(query, text); - populateQueryWithFilters(query, filters); - return query; - } - - private void populateQueryWithSort(Query query, String sort) { - if (StringUtils.hasText(sort)) { - query.with(Sort.by(sort).ascending()); - } - } - - private void populateQueryWithFreeTextSearch(Query query, String text) { - if (StringUtils.hasText(text)) { - query.addCriteria(TextCriteria.forDefaultLanguage().matchingAny(text)); - } - } - - private void populateQueryWithFilters(Query query, List filters) { - if (CollectionUtils.isEmpty(filters)) { - return; - } - - for (String filter : filters) { - String[] filterParts = filter.split(":"); - if (filterParts.length > 1) { - String field = filterParts[0]; - String value = filterParts[1]; - query.addCriteria(Criteria.where(field).is(value)); - } - } - } } diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortService.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortService.java index faa3a4a..863b169 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortService.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortService.java @@ -14,11 +14,9 @@ @Service public class CohortService { private final CohortRepository cohortRepository; - private final CohortSearchRepository cohortSearchRepository; - public CohortService(CohortRepository cohortRepository, CohortSearchRepository cohortSearchRepository) { + public CohortService(CohortRepository cohortRepository) { this.cohortRepository = cohortRepository; - this.cohortSearchRepository = cohortSearchRepository; } public Cohort saveCohort(Cohort cohort) { @@ -26,7 +24,7 @@ public Cohort saveCohort(Cohort cohort) { } public Page searchCohorts(Pageable pageRequest, String text, List filters, String sort) { - return cohortSearchRepository.findPageWithFilters(pageRequest, text, sort, filters); + return cohortRepository.findByFilters(pageRequest, text, sort, filters); } @NonNull diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldService.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldService.java index f410e56..0c0a460 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldService.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldService.java @@ -1,5 +1,6 @@ package uk.ac.ebi.biosamples.cohortatlas.service; +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -11,21 +12,17 @@ import java.util.Map; @Service +@RequiredArgsConstructor public class FieldService { private final FieldRepository fieldRepository; private final FieldSearchRepository fieldSearchRepository; - public FieldService(FieldRepository fieldRepository, FieldSearchRepository fieldSearchRepository) { - this.fieldRepository = fieldRepository; - this.fieldSearchRepository = fieldSearchRepository; - } - public List searchFields(String cohort) { return fieldRepository.findByCohort(cohort); } public Page searchFields(Pageable pageRequest, String text, List filters, String sort) { - return fieldSearchRepository.findFieldPageWithFilters(pageRequest, text, sort, filters); + return fieldSearchRepository.findByFilters(pageRequest, text, sort, filters); } public List> fieldCountGroupByCohort() { diff --git a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/RelationshipService.java b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/RelationshipService.java index 9cbe0d0..b05ddbf 100644 --- a/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/RelationshipService.java +++ b/src/main/java/uk/ac/ebi/biosamples/cohortatlas/service/RelationshipService.java @@ -12,15 +12,13 @@ @Service public class RelationshipService { private final RelationshipRepository relationshipRepository; - private final RelationshipSearchRepository relationshipSearchRepository; public RelationshipService(RelationshipRepository relationshipRepository, RelationshipSearchRepository relationshipSearchRepository) { this.relationshipRepository = relationshipRepository; - this.relationshipSearchRepository = relationshipSearchRepository; } public Page searchRelationships(Pageable pageRequest, String text, List filters, String sort) { - return relationshipSearchRepository.findFieldPageWithFilters(pageRequest, text, sort, filters); + return relationshipRepository.findByFilters(pageRequest, text, sort, filters); } } diff --git a/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortServiceTest.java b/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortServiceTest.java index b2cf172..6b87847 100644 --- a/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortServiceTest.java +++ b/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/CohortServiceTest.java @@ -37,7 +37,7 @@ public void search_should_return_a_list_of_cohorts() { String sort = ""; Page cohortPage = new PageImpl<>(getTestCohorts(), pageRequest, getTestCohorts().size()); - Mockito.when(cohortSearchRepository.findPageWithFilters(pageRequest, text, sort, filters)).thenReturn(cohortPage); + Mockito.when(cohortSearchRepository.findByFilters(pageRequest, text, sort, filters)).thenReturn(cohortPage); Page cohorts = cohortService.searchCohorts(pageRequest, text, filters, sort); Assertions.assertNotNull(cohorts); diff --git a/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldServiceTest.java b/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldServiceTest.java index f385d1a..04a68d9 100644 --- a/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldServiceTest.java +++ b/src/test/java/uk/ac/ebi/biosamples/cohortatlas/service/FieldServiceTest.java @@ -38,7 +38,7 @@ public void search_should_return_a_list_of_fields() { String sort = ""; Page fieldPage = new PageImpl<>(getTestFields(), pageRequest, getTestFields().size()); - Mockito.when(fieldSearchRepository.findFieldPageWithFilters(pageRequest, text, sort, filters)).thenReturn(fieldPage); + Mockito.when(fieldSearchRepository.findByFilters(pageRequest, text, sort, filters)).thenReturn(fieldPage); Page fields = fieldService.searchFields(pageRequest, text, filters, sort); Assertions.assertNotNull(fields);