diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/DictionaryApplication.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/DictionaryApplication.java index c12b6eb..40fee56 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/DictionaryApplication.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/DictionaryApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication +@EnableCaching public class DictionaryApplication { public static void main(String[] args) { 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 f22b65e..edd1e4d 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 @@ -6,6 +6,7 @@ import edu.harvard.dbmi.avillach.dictionary.concept.model.ContinuousConcept; import edu.harvard.dbmi.avillach.dictionary.filter.Filter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -26,6 +27,7 @@ public ConceptService(ConceptRepository conceptRepository, ConceptDecoratorServi this.conceptDecoratorService = conceptDecoratorService; } + @Cacheable("concepts") public List listConcepts(Filter filter, Pageable page) { return conceptRepository.getConcepts(filter, page); } @@ -40,6 +42,7 @@ public List listDetailedConcepts(Filter filter, Pageable page) { }).toList(); } + @Cacheable("concepts_count") public long countConcepts(Filter filter) { return conceptRepository.countConcepts(filter); } diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FacetService.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FacetService.java index b330865..3ad2aac 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FacetService.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FacetService.java @@ -2,6 +2,7 @@ import edu.harvard.dbmi.avillach.dictionary.filter.Filter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.List; @@ -17,6 +18,7 @@ public FacetService(FacetRepository repository) { this.repository = repository; } + @Cacheable("facets") public List getFacets(Filter filter) { return repository.getFacets(filter); } diff --git a/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessor.java b/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessor.java index 483dc02..98357dc 100644 --- a/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessor.java +++ b/src/main/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessor.java @@ -10,6 +10,10 @@ import java.io.IOException; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.function.Function; @ControllerAdvice public class FilterPreProcessor implements RequestBodyAdvice { @@ -30,8 +34,23 @@ public Object afterBodyRead( Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType ) { - if (body instanceof Filter filter && StringUtils.hasLength(filter.search())) { - return new Filter(filter.facets(), filter.search().replaceAll("_", "/"), filter.consents()); + if (body instanceof Filter filter) { + List newFacets = filter.facets(); + List newConsents = filter.consents(); + if (filter.facets() != null) { + newFacets = new ArrayList<>(filter.facets()); + newFacets.sort(Comparator.comparing(Facet::name)); + } + if (filter.consents() != null) { + newConsents = new ArrayList<>(newConsents); + newConsents.sort(Comparator.comparing(Function.identity())); + } + filter = new Filter(newFacets, filter.search(), newConsents); + + if (StringUtils.hasLength(filter.search())) { + filter = new Filter(filter.facets(), filter.search().replaceAll("_", "/"), filter.consents()); + } + return filter; } return body; } diff --git a/src/test/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessorTest.java b/src/test/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessorTest.java index 5fa6150..6d3d452 100644 --- a/src/test/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessorTest.java +++ b/src/test/java/edu/harvard/dbmi/avillach/dictionary/facet/FilterPreProcessorTest.java @@ -18,6 +18,19 @@ class FilterPreProcessorTest { @Autowired private FilterPreProcessor subject; + @Test + void shouldSortFilter() { + Filter filter = new Filter(List.of(new Facet("b", ""), new Facet("a", "")), "", List.of("c", "b", "a")); + Filter actual = (Filter) subject.afterBodyRead( + filter, Mockito.mock(HttpInputMessage.class), Mockito.mock(MethodParameter.class), SimpleType.constructUnsafe(Filter.class), + null + ); + + Filter expected = new Filter(List.of(new Facet("a", ""), new Facet("b", "")), "", List.of("a", "b", "c")); + Assertions.assertEquals(expected, actual); + + } + @Test void shouldProcessFilter() { Object processedFilter = subject.afterBodyRead(