diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptDecoratorService.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptDecoratorService.java new file mode 100644 index 0000000..08a56a3 --- /dev/null +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptDecoratorService.java @@ -0,0 +1,66 @@ +package edu.harvard.dbmi.avillach.dictionary.concept; + +import edu.harvard.dbmi.avillach.dictionary.concept.model.Concept; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +@Service +public class ConceptDecoratorService { + + private static final Logger LOG = LoggerFactory.getLogger(ConceptDecoratorService.class); + private final boolean enabled; + private final ConceptService conceptService; + + private static final int COMPLIANT = 4, NON_COMPLIANT_TABLED = 3, NON_COMPLIANT_UNTABLED = 2; + + @Autowired + public ConceptDecoratorService( + @Value("${dashboard.enable.extra_details}") boolean enabled, + @Lazy ConceptService conceptService // circular dep + ) { + this.enabled = enabled; + this.conceptService = conceptService; + } + + + public Concept populateParentConcepts(Concept concept) { + if (!enabled) { + return concept; + } + + // In some environments, certain parent concepts have critical details that we need to add to the detailed response + List conceptNodes = Stream.of(concept.conceptPath() + .split("\\\\")).filter(Predicate.not(String::isBlank)).toList(); // you have to double escape the slash. Once for strings, and once for regex + + return switch (conceptNodes.size()) { + case COMPLIANT, NON_COMPLIANT_TABLED -> populateTabledConcept(concept, conceptNodes); + case NON_COMPLIANT_UNTABLED -> populateNonCompliantTabledConcept(concept, conceptNodes); + default -> { + LOG.warn("Ignoring decoration request for weird concept path {}", concept.conceptPath()); + yield concept; + } + }; + } + + private Concept populateTabledConcept(Concept concept, List conceptNodes) { + String studyPath = "\\" + String.join("\\", conceptNodes.subList(0, 1)) + "\\"; + String tablePath = "\\" + String.join("\\", conceptNodes.subList(0, 2)) + "\\"; + Concept study = conceptService.conceptDetailWithoutAncestors(concept.dataset(), studyPath).orElse(null); + Concept table = conceptService.conceptDetailWithoutAncestors(concept.dataset(), tablePath).orElse(null); + return concept.withStudy(study).withTable(table); + } + + private Concept populateNonCompliantTabledConcept(Concept concept, List conceptNodes) { + String studyPath = String.join("\\", conceptNodes.subList(0, 1)); + Concept study = conceptService.conceptDetail(concept.dataset(), studyPath).orElse(null); + return concept.withStudy(study); + } +} diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptService.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptService.java index 9e7dca0..67db7b6 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptService.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptService.java @@ -12,17 +12,18 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; @Service public class ConceptService { private final ConceptRepository conceptRepository; + private final ConceptDecoratorService conceptDecoratorService; + @Autowired - public ConceptService(ConceptRepository conceptRepository) { + public ConceptService(ConceptRepository conceptRepository, ConceptDecoratorService conceptDecoratorService) { this.conceptRepository = conceptRepository; + this.conceptDecoratorService = conceptDecoratorService; } public List listConcepts(Filter filter, Pageable page) { @@ -44,19 +45,28 @@ public long countConcepts(Filter filter) { } public Optional conceptDetail(String dataset, String conceptPath) { - return conceptRepository.getConcept(dataset, conceptPath) + return getConcept(dataset, conceptPath, true); + } + + private Optional getConcept(String dataset, String conceptPath, boolean addAncestors) { + Optional concept = conceptRepository.getConcept(dataset, conceptPath) .map(core -> { - var meta = conceptRepository.getConceptMeta(dataset, conceptPath); - return switch (core) { - case ContinuousConcept cont -> new ContinuousConcept(cont, meta); - case CategoricalConcept cat -> new CategoricalConcept(cat, meta); - case ConceptShell ignored -> throw new RuntimeException("Concept shell escaped to API"); - }; - } - ); + var meta = conceptRepository.getConceptMeta(dataset, conceptPath); + return switch (core) { + case ContinuousConcept cont -> new ContinuousConcept(cont, meta); + case CategoricalConcept cat -> new CategoricalConcept(cat, meta); + case ConceptShell ignored -> throw new RuntimeException("Concept shell escaped to API"); + }; + } + ); + return addAncestors ? concept.map(conceptDecoratorService::populateParentConcepts) : concept; } public Optional conceptTree(String dataset, String conceptPath, int depth) { return conceptRepository.getConceptTree(dataset, conceptPath, depth); } + + public Optional conceptDetailWithoutAncestors(String dataset, String conceptPath) { + return getConcept(dataset, conceptPath, false); + } } diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/CategoricalConcept.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/CategoricalConcept.java index ef3b60c..1b9283c 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/CategoricalConcept.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/CategoricalConcept.java @@ -16,10 +16,23 @@ public record CategoricalConcept( List children, @Nullable - Map meta + Map meta, + + @Nullable + Concept table, + + @Nullable + Concept study ) implements Concept { + public CategoricalConcept( + String conceptPath, String name, String display, String dataset, String description, List values, + @Nullable List children, @Nullable Map meta + ) { + this(conceptPath, name, display, dataset, description, values, children, meta, null, null); + } + public CategoricalConcept(CategoricalConcept core, Map meta) { this(core.conceptPath, core.name, core.display, core.dataset, core.description, core.values, core.children, meta); } @@ -44,6 +57,20 @@ public CategoricalConcept withChildren(List children) { return new CategoricalConcept(this, children); } + @Override + public Concept withTable(Concept table) { + return new CategoricalConcept( + conceptPath, name, display, dataset, description, values, children, meta, table, study + ); + } + + @Override + public Concept withStudy(Concept study) { + return new CategoricalConcept( + conceptPath, name, display, dataset, description, values, children, meta, table, study + ); + } + @Override public boolean equals(Object object) { return conceptEquals(object); diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/Concept.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/Concept.java index 17d70dd..ac9998b 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/Concept.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/Concept.java @@ -49,6 +49,10 @@ public sealed interface Concept */ ConceptType type(); + Concept table(); + + Concept study(); + Map meta(); @Nullable @@ -56,6 +60,10 @@ public sealed interface Concept Concept withChildren(List children); + Concept withTable(Concept table); + + Concept withStudy(Concept study); + default boolean conceptEquals(Object object) { if (this == object) return true; if (!(object instanceof Concept)) return false; diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptShell.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptShell.java index d904632..41b909e 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptShell.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptShell.java @@ -22,6 +22,16 @@ public ConceptType type() { return ConceptType.Continuous; } + @Override + public Concept table() { + return null; + } + + @Override + public Concept study() { + return null; + } + @Override public Map meta() { return Map.of(); @@ -37,6 +47,16 @@ public ConceptShell withChildren(List children) { return this; } + @Override + public Concept withTable(Concept table) { + return this; + } + + @Override + public Concept withStudy(Concept study) { + return this; + } + @Override public boolean equals(Object object) { return conceptEquals(object); diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ContinuousConcept.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ContinuousConcept.java index 48a9f2f..0e84545 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ContinuousConcept.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ContinuousConcept.java @@ -14,9 +14,22 @@ public record ContinuousConcept( @Nullable Integer min, @Nullable Integer max, Map meta, @Nullable - List children + List children, + + @Nullable + Concept table, + + @Nullable + Concept study ) implements Concept { + public ContinuousConcept( + String conceptPath, String name, String display, String dataset, String description, + @Nullable Integer min, @Nullable Integer max, Map meta, @Nullable List children + ) { + this(conceptPath, name, display, dataset, description, min, max, meta, children, null, null); + } + public ContinuousConcept(ContinuousConcept core, Map meta) { this(core.conceptPath, core.name, core.display, core.dataset, core.description, core.min, core.max, meta, core.children); } @@ -47,6 +60,20 @@ public ContinuousConcept withChildren(List children) { return new ContinuousConcept(this, children); } + @Override + public Concept withTable(Concept table) { + return new ContinuousConcept( + conceptPath, name, display, dataset, description, min, max, meta, children, table, study + ); + } + + @Override + public Concept withStudy(Concept study) { + return new ContinuousConcept( + conceptPath, name, display, dataset, description, min, max, meta, children, table, study + ); + } + @Override public boolean equals(Object object) { return conceptEquals(object); diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardConfig.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardConfig.java index c2e0bc6..024e9b3 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardConfig.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardConfig.java @@ -31,8 +31,8 @@ public List getColumns() { } private int calculateOrder(DashboardColumn column) { - if (columnOrder.contains(column.label())) { - return columnOrder.indexOf(column.label()); + if (columnOrder.contains(column.dataElement())) { + return columnOrder.indexOf(column.dataElement()); } else { return Integer.MAX_VALUE; } diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRowResultSetExtractor.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRowResultSetExtractor.java index 83b5245..7198063 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRowResultSetExtractor.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRowResultSetExtractor.java @@ -23,7 +23,7 @@ public class DashboardRowResultSetExtractor implements ResultSetExtractor columns) { template = columns.stream() - .collect(Collectors.toMap(DashboardColumn::label, (ignored) -> "")); + .collect(Collectors.toMap(DashboardColumn::dataElement, (ignored) -> "")); } @Override diff --git a/src/main/resources/application-bdc.properties b/src/main/resources/application-bdc.properties index 3660041..f3d1d65 100644 --- a/src/main/resources/application-bdc.properties +++ b/src/main/resources/application-bdc.properties @@ -4,3 +4,5 @@ spring.datasource.driver-class-name=com.amazonaws.secretsmanager.sql.AWSSecretsM spring.datasource.url=jdbc-secretsmanager:postgresql://${DATASOURCE_URL}/picsure?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&autoReconnectForPools=true¤tSchema=dict spring.datasource.username=${DATASOURCE_USERNAME} server.port=80 + +dashboard.enable.extra_details=true \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 656fc1f..127664a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,4 +7,5 @@ server.port=80 dashboard.columns={abbreviation:'Abbreviation',name:'Name',clinvars:'Clinical Variables'} dashboard.column-order=abbreviation,name,clinvars -dashboard.nonmeta-columns=abbreviation,name \ No newline at end of file +dashboard.nonmeta-columns=abbreviation,name +dashboard.enable.extra_details=true \ No newline at end of file diff --git a/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptDecoratorServiceTest.java b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptDecoratorServiceTest.java new file mode 100644 index 0000000..435aefb --- /dev/null +++ b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptDecoratorServiceTest.java @@ -0,0 +1,79 @@ +package edu.harvard.dbmi.avillach.dictionary.concept; + +import edu.harvard.dbmi.avillach.dictionary.concept.model.CategoricalConcept; +import edu.harvard.dbmi.avillach.dictionary.concept.model.Concept; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import java.util.Optional; + + +@SpringBootTest +class ConceptDecoratorServiceTest { + + @MockBean + ConceptService conceptService; + + @Autowired + ConceptDecoratorService subject; + + @Test + void shouldPopulateCompliantStudy() { + CategoricalConcept concept = new CategoricalConcept("\\study\\table\\idk\\concept\\", "dataset"); + CategoricalConcept table = new CategoricalConcept("\\study\\table\\", "dataset"); + CategoricalConcept study = new CategoricalConcept("\\study\\", "dataset"); + + Mockito.when(conceptService.conceptDetail("dataset", table.dataset())) + .thenReturn(Optional.of(table)); + Mockito.when(conceptService.conceptDetail("dataset", study.dataset())) + .thenReturn(Optional.of(study)); + + Concept actual = subject.populateParentConcepts(concept); + Concept expected = concept.withStudy(study).withTable(table); + + Assertions.assertEquals(expected, actual); + } + + @Test + void shouldPopulateNonCompliantTabledStudy() { + CategoricalConcept concept = new CategoricalConcept("\\study\\table\\concept\\", "dataset"); + CategoricalConcept table = new CategoricalConcept("\\study\\table\\", "dataset"); + CategoricalConcept study = new CategoricalConcept("\\study\\", "dataset"); + + Mockito.when(conceptService.conceptDetail("dataset", table.dataset())) + .thenReturn(Optional.of(table)); + Mockito.when(conceptService.conceptDetail("dataset", study.dataset())) + .thenReturn(Optional.of(study)); + + Concept actual = subject.populateParentConcepts(concept); + Concept expected = concept.withStudy(study).withTable(table); + + Assertions.assertEquals(expected, actual); + } + + @Test + void shouldPopulateNonCompliantUnTabledStudy() { + CategoricalConcept concept = new CategoricalConcept("\\study\\concept\\", "dataset"); + CategoricalConcept study = new CategoricalConcept("\\study\\", "dataset"); + + Mockito.when(conceptService.conceptDetail("dataset", study.dataset())) + .thenReturn(Optional.of(study)); + + Concept actual = subject.populateParentConcepts(concept); + Concept expected = concept.withStudy(study); + + Assertions.assertEquals(expected, actual); + } + + @Test + void shouldNotPopulateWeirdConcept() { + CategoricalConcept concept = new CategoricalConcept("\\1\\2\\3\\4\\5\\6\\", "dataset"); + Concept actual = subject.populateParentConcepts(concept); + + Assertions.assertEquals(concept, actual); + } +} \ No newline at end of file diff --git a/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceIntegrationTest.java b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceIntegrationTest.java new file mode 100644 index 0000000..bf1112c --- /dev/null +++ b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceIntegrationTest.java @@ -0,0 +1,73 @@ +package edu.harvard.dbmi.avillach.dictionary.concept; + +import edu.harvard.dbmi.avillach.dictionary.concept.model.CategoricalConcept; +import edu.harvard.dbmi.avillach.dictionary.concept.model.Concept; +import edu.harvard.dbmi.avillach.dictionary.concept.model.ContinuousConcept; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.MountableFile; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Testcontainers +@SpringBootTest +class ConceptServiceIntegrationTest { + + @Autowired + ConceptService subject; + + @Container + static final PostgreSQLContainer databaseContainer = + new PostgreSQLContainer<>("postgres:16") + .withReuse(true) + .withCopyFileToContainer( + MountableFile.forClasspathResource("seed.sql"), "/docker-entrypoint-initdb.d/seed.sql" + ); + + @DynamicPropertySource + static void mySQLProperties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", databaseContainer::getJdbcUrl); + registry.add("spring.datasource.username", databaseContainer::getUsername); + registry.add("spring.datasource.password", databaseContainer::getPassword); + registry.add("spring.datasource.db", databaseContainer::getDatabaseName); + } + + @Test + void shouldGetDetails() { + Optional actual = subject.conceptDetail("phs000007", "\\phs000007\\pht000021\\phv00003844\\FL200\\"); + + CategoricalConcept table = new CategoricalConcept( + "\\phs000007\\pht000021\\", "pht000021", "ex0_19s", "phs000007", + "Clinic Exam, Original Cohort Exam 19", + List.of(), null, Map.of("description", "Clinic Exam, Original Cohort Exam 19"), null, null + ); + CategoricalConcept study = new CategoricalConcept( + "\\phs000007\\", "", "", "phs000007", null, List.of(), null, Map.of(), null, null + ); + ContinuousConcept expected = new ContinuousConcept( + "\\phs000007\\pht000021\\phv00003844\\FL200\\", "phv00003844", "FL200", "phs000007", + "# 12 OZ CUPS OF CAFFEINATED COLA / DAY", 0, 3, + Map.of( + "unique_identifier", "no", + "stigmatizing", "no", + "bdc_open_access", "yes", + "values", "[0, 3]", + "description", "# 12 OZ CUPS OF CAFFEINATED COLA / DAY", + "free_text", "no" + ), + null, table, study + ); + + Assertions.assertTrue(actual.isPresent()); + Assertions.assertEquals(expected, actual.get()); + } +} \ No newline at end of file diff --git a/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceTest.java b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceTest.java index 1757774..b7cedf3 100644 --- a/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceTest.java +++ b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/ConceptServiceTest.java @@ -24,6 +24,9 @@ class ConceptServiceTest { @MockBean ConceptRepository repository; + @MockBean + ConceptDecoratorService decoratorService; + @Autowired ConceptService subject; @@ -59,6 +62,8 @@ void shouldShowDetailForContinuous() { Map meta = Map.of("MIN", "0", "MAX", "1", "stigmatizing", "true"); Mockito.when(repository.getConcept("dataset", "path")) .thenReturn(Optional.of(concept)); + Mockito.when(decoratorService.populateParentConcepts(Mockito.any())) + .thenAnswer(i -> i.getArguments()[0]); Mockito.when(repository.getConceptMeta("dataset", "path")) .thenReturn(meta); @@ -74,6 +79,8 @@ void shouldShowDetailForCategorical() { Map meta = Map.of("VALUES", "a", "stigmatizing", "true"); Mockito.when(repository.getConcept("dataset", "path")) .thenReturn(Optional.of(concept)); + Mockito.when(decoratorService.populateParentConcepts(Mockito.any())) + .thenAnswer(i -> i.getArguments()[0]); Mockito.when(repository.getConceptMeta("dataset", "path")) .thenReturn(meta); @@ -111,4 +118,18 @@ void shouldShowDetailForMultiple() { Assertions.assertEquals(expected, actual); } + + @Test + void shouldGetTree() { + CategoricalConcept concept = new CategoricalConcept("ds", "\\A\\B\\C\\").withChildren( + List.of(new CategoricalConcept("ds", "\\A\\B\\C\\1\\"), new ContinuousConcept("ds", "\\A\\B\\C\\2\\")) + ); + Mockito.when(repository.getConceptTree("ds", "\\A\\B\\C\\", 2)) + .thenReturn(Optional.of(concept)); + + Optional actual = subject.conceptTree("ds", "\\A\\B\\C\\", 2); + + Assertions.assertTrue(actual.isPresent()); + Assertions.assertEquals(concept, actual.get()); + } } \ No newline at end of file diff --git a/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptTest.java b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptTest.java index 9181493..fec3731 100644 --- a/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptTest.java +++ b/src/test/java/edu/harvard/dbmi/avillach/dictionary/concept/model/ConceptTest.java @@ -75,7 +75,7 @@ void shouldIncludeTypeInList() throws JsonProcessingException { ); String actual = new ObjectMapper().writeValueAsString(concepts); - String expected = "[{\"conceptPath\":\"/foo//baz\",\"name\":\"baz\",\"display\":\"Baz\",\"dataset\":\"study_a\",\"description\":null,\"min\":0,\"max\":1,\"meta\":{},\"children\":null,\"type\":\"Continuous\"},{\"conceptPath\":\"/foo//bar\",\"name\":\"bar\",\"display\":\"Bar\",\"dataset\":\"study_a\",\"description\":null,\"values\":[\"a\",\"b\"],\"children\":null,\"meta\":{},\"type\":\"Categorical\"}]"; + String expected = "[{\"conceptPath\":\"/foo//baz\",\"name\":\"baz\",\"display\":\"Baz\",\"dataset\":\"study_a\",\"description\":null,\"min\":0,\"max\":1,\"meta\":{},\"children\":null,\"table\":null,\"study\":null,\"type\":\"Continuous\"},{\"conceptPath\":\"/foo//bar\",\"name\":\"bar\",\"display\":\"Bar\",\"dataset\":\"study_a\",\"description\":null,\"values\":[\"a\",\"b\"],\"children\":null,\"meta\":{},\"table\":null,\"study\":null,\"type\":\"Categorical\"}]"; Assertions.assertEquals(expected, actual); } diff --git a/src/test/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRepositoryTest.java b/src/test/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRepositoryTest.java index 8775ad0..b2d744d 100644 --- a/src/test/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRepositoryTest.java +++ b/src/test/java/edu/harvard/dbmi/avillach/dictionary/dashboard/DashboardRepositoryTest.java @@ -41,15 +41,15 @@ static void mySQLProperties(DynamicPropertyRegistry registry) { void shouldGetDashboardRows() { List> actual = subject.getRows(); List> expected = List.of( - Map.of("name", "phs000007", "abbreviation", "FHS", "melast", "", "clinvars", "", "participants", ""), - Map.of("name", "phs000284", "abbreviation", "CFS", "melast", "", "clinvars", "12546", "participants", "3435"), - Map.of("name", "phs001963", "abbreviation", "DEMENTIA-SEQ", "melast", "", "clinvars", "12321", "participants", "867876"), - Map.of("name", "phs002385", "abbreviation", "HCT_for_SCD", "melast", "", "clinvars", "653", "participants", "65"), - Map.of("name", "phs002715", "abbreviation", "NSRR CFS", "melast", "", "clinvars", "7567", "participants", "33"), - Map.of("name", "phs002808", "abbreviation", "nuMoM2b", "melast", "", "clinvars", "500", "participants", "23432"), - Map.of("name", "phs003463", "abbreviation", "RECOVER_Adult", "melast", "", "clinvars", "2", "participants", "111"), - Map.of("name", "phs003543", "abbreviation", "NSRR_HSHC", "melast", "", "clinvars", "654645", "participants", "6654"), - Map.of("name", "phs003566", "abbreviation", "SPRINT", "melast", "", "clinvars", "434", "participants", "53435") + Map.of("name", "DEMENTIA-SEQ: WGS in Lewy Body Dementia and Frontotemporal Dementia", "abbreviation", "DEMENTIA-SEQ", "melast", "", "clinvars", "653", "participants", "65"), + Map.of("name", "Framingham Cohort", "abbreviation", "FHS", "melast", "", "clinvars", "12546", "participants", "3435"), + Map.of("name", "Hematopoietic Cell Transplant for Sickle Cell Disease (HCT for SCD)", "abbreviation", "HCT_for_SCD", "melast", "", "clinvars", "7567", "participants", "33"), + Map.of("name", "National Sleep Research Resource (NSRR): Cleveland Family Study (CFS)", "abbreviation", "NSRR CFS", "melast", "", "clinvars", "500", "participants", "23432"), + Map.of("name", "National Sleep Research Resource (NSRR): (HSHC)", "abbreviation", "NSRR_HSHC", "melast", "", "clinvars", "434", "participants", "53435"), + Map.of("name", "NHLBI Cleveland Family Study (CFS) Candidate Gene Association Resource (CARe)", "abbreviation", "CFS", "melast", "", "clinvars", "12321", "participants", "867876"), + Map.of("name", "Nulliparous Pregnancy Outcomes Study: Monitoring Mothers-to-be Heart Health Study (nuMoM2b Heart Health Study)", "abbreviation", "nuMoM2b", "melast", "", "clinvars", "2", "participants", "111"), + Map.of("name", "Researching COVID to Enhance Recovery (RECOVER): Adult Observational Cohort Study", "abbreviation", "RECOVER_Adult", "melast", "", "clinvars", "654645", "participants", "6654"), + Map.of("name", "Systolic Blood Pressure Intervention Trial (SPRINT-Imaging)", "abbreviation", "SPRINT", "melast", "", "clinvars", "333", "participants", "2222") ); Assertions.assertEquals(expected, actual); } diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index f5db8d5..bda1b5f 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -7,3 +7,5 @@ spring.datasource.driver-class-name=org.postgresql.Driver dashboard.columns={abbreviation:'Abbreviation',melast:'This one goes last',name:'Name',clinvars:'Clinical Variables',participants:'Participants'} dashboard.column-order=abbreviation,name,clinvars dashboard.nonmeta-columns=abbreviation,name + +dashboard.enable.extra_details=true \ No newline at end of file