Commit d35cead5 authored by Jean-Baptiste Nizet's avatar Jean-Baptiste Nizet Committed by Exbrayat Cédric
Browse files

feat: filter variables of study by language

parent 9b69e8dd
......@@ -4,9 +4,11 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.collect.Lists;
import fr.inra.urgi.faidare.api.NotFoundException;
......@@ -31,6 +33,7 @@ import org.apache.logging.log4j.util.Strings;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -71,7 +74,7 @@ public class StudyController {
}
@GetMapping("/{studyId}")
public ModelAndView get(@PathVariable("studyId") String studyId) {
public ModelAndView get(@PathVariable("studyId") String studyId, Locale locale) {
StudyDetailVO study = studyRepository.getById(studyId);
if (study == null) {
......@@ -83,7 +86,7 @@ public class StudyController {
);
List<GermplasmVO> germplasms = getGermplasms(study);
List<ObservationVariableVO> variables = getVariables(study);
List<ObservationVariableVO> variables = getVariables(study, locale);
List<TrialVO> trials = getTrials(study);
LocationVO location = getLocation(study);
......@@ -139,14 +142,78 @@ public class StudyController {
}
}
private List<ObservationVariableVO> getVariables(StudyDetailVO study) {
private List<ObservationVariableVO> getVariables(StudyDetailVO study, Locale locale) {
Set<String> variableIds = studyRepository.getVariableIds(study.getStudyDbId());
return cropOntologyRepository.getVariableByIds(variableIds)
.stream()
List<ObservationVariableVO> variables = cropOntologyRepository.getVariableByIds(variableIds);
return filterVariablesForLocale(variables, locale)
.sorted(Comparator.comparing(ObservationVariableVO::getObservationVariableDbId))
.collect(Collectors.toList());
}
/**
* Filter the variables by language. The principles are the following. First, the languages of the variables
* are normalized (to transform FRA into fr for example).
* Then, several cases are possible.
*
* If there is no variable with the requested language, then we find the reference language.
* The reference language is en if there is at least one variable with that language.
* The reference is the first non null language found if there is no variable with the en language.
* Then, we keep all the variables with the reference language (if any), and all the variables without language.
*
* If there is at least one variable with the requested language, then we keep all the variables
* with the requested language, and all the variables without language.
*/
private Stream<ObservationVariableVO> filterVariablesForLocale(List<ObservationVariableVO> variables, Locale locale) {
if (variables.isEmpty()) {
return variables.stream();
}
String requestedLanguage = locale.getLanguage();
String referenceLanguage = findReferenceLanguage(requestedLanguage, variables);
return variables.stream()
.filter(variable ->
referenceLanguage == null
|| !StringUtils.hasText(variable.getLanguage())
|| normalizeLanguage(variable.getLanguage()).equals(referenceLanguage));
}
private String findReferenceLanguage(String requestedLanguage, List<ObservationVariableVO> variables) {
Set<String> normalizedVariableLanguages =
variables.stream()
.map(ObservationVariableVO::getLanguage)
.filter(StringUtils::hasText)
.map(this::normalizeLanguage)
.collect(Collectors.toSet());
String referenceLanguage = null;
if (normalizedVariableLanguages.contains(requestedLanguage)) {
referenceLanguage = requestedLanguage;
} else if (normalizedVariableLanguages.contains("en")) {
referenceLanguage = "en";
} else if (!normalizedVariableLanguages.isEmpty()) {
referenceLanguage = normalizedVariableLanguages.iterator().next();
}
return referenceLanguage;
}
private String normalizeLanguage(String language) {
// this is a hack trying to accomodate for languages not bein standard in the data
String languageInLowerCase = language.toLowerCase();
if (languageInLowerCase.length() == 3) {
switch (languageInLowerCase) {
case "fra":
return "fr";
case "esp":
case "spa":
return "es";
case "eng":
return "en";
}
}
return languageInLowerCase;
}
private List<TrialVO> getTrials(StudyDetailVO study) {
if (study.getTrialDbIds() == null || study.getTrialDbIds().isEmpty()) {
return Collections.emptyList();
......
......@@ -2,6 +2,7 @@ package fr.inra.urgi.faidare.web.study;
import static fr.inra.urgi.faidare.web.Fixtures.createSite;
import static fr.inra.urgi.faidare.web.Fixtures.htmlContent;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.when;
......@@ -12,6 +13,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import fr.inra.urgi.faidare.config.FaidareProperties;
......@@ -21,6 +23,7 @@ import fr.inra.urgi.faidare.domain.data.TrialVO;
import fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO;
import fr.inra.urgi.faidare.domain.data.study.StudyDetailVO;
import fr.inra.urgi.faidare.domain.data.study.StudySitemapVO;
import fr.inra.urgi.faidare.domain.data.variable.ObservationVariableVO;
import fr.inra.urgi.faidare.domain.datadiscovery.data.DataSource;
import fr.inra.urgi.faidare.domain.response.PaginatedList;
import fr.inra.urgi.faidare.domain.xref.XRefDocumentSearchCriteria;
......@@ -37,6 +40,7 @@ import fr.inra.urgi.faidare.web.site.SiteController;
import fr.inra.urgi.faidare.web.thymeleaf.CoordinatesDialect;
import fr.inra.urgi.faidare.web.thymeleaf.FaidareDialect;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
......@@ -45,6 +49,7 @@ import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.servlet.ModelAndView;
/**
* MVC tests for {@link StudyController}
......@@ -76,6 +81,9 @@ public class StudyControllerTest {
@MockBean
private LocationRepository mockLocationRepository;
@Autowired
private StudyController studyController;
private StudyDetailVO study;
private GermplasmVO germplasm;
private List<XRefDocumentVO> crossReferences;
......@@ -148,6 +156,78 @@ public class StudyControllerTest {
.andExpect(status().isNotFound());
}
@Nested
class Variables {
@Test
void shouldFilterVariablesByLanguageWhenRequestedLanguageIsFound() throws Exception {
ObservationVariableVO variableWithEnglishLanguage = Fixtures.createVariable();
variableWithEnglishLanguage.setLanguage("EN");
ObservationVariableVO variableWithFrenchLanguage = Fixtures.createVariable();
variableWithFrenchLanguage.setLanguage("FRA");
ObservationVariableVO variableWithNoLanguage = Fixtures.createVariable();
variableWithNoLanguage.setLanguage(null);
when(mockCropOntologyRepository.getVariableByIds(any())).thenReturn(
Arrays.asList(variableWithEnglishLanguage, variableWithFrenchLanguage, variableWithNoLanguage)
);
ModelAndView modelAndView = mockMvc.perform(get("/studies/{id}", study.getStudyDbId())
.locale(Locale.FRENCH))
.andReturn()
.getModelAndView();
StudyModel model = (StudyModel) modelAndView.getModel().get("model");
assertThat(model.getVariables()).containsOnly(variableWithFrenchLanguage, variableWithNoLanguage);
}
@Test
void shouldFilterVariablesByLanguageWhenRequestedLanguageIsNotFound() throws Exception {
ObservationVariableVO variableWithEnglishLanguage = Fixtures.createVariable();
variableWithEnglishLanguage.setLanguage("EN");
ObservationVariableVO variableWithFrenchLanguage = Fixtures.createVariable();
variableWithFrenchLanguage.setLanguage("FRA");
ObservationVariableVO variableWithNoLanguage = Fixtures.createVariable();
variableWithNoLanguage.setLanguage(null);
when(mockCropOntologyRepository.getVariableByIds(any())).thenReturn(
Arrays.asList(variableWithEnglishLanguage, variableWithFrenchLanguage, variableWithNoLanguage)
);
ModelAndView modelAndView = mockMvc.perform(get("/studies/{id}", study.getStudyDbId())
.locale(Locale.CHINA))
.andReturn()
.getModelAndView();
StudyModel model = (StudyModel) modelAndView.getModel().get("model");
assertThat(model.getVariables()).containsOnly(variableWithEnglishLanguage, variableWithNoLanguage);
}
@Test
void shouldFilterVariablesByLanguageWhenRequestedLanguageIsNotFoundAndEnglishAbsent() throws Exception {
ObservationVariableVO variableWithSpanishLanguage = Fixtures.createVariable();
variableWithSpanishLanguage.setLanguage("es");
ObservationVariableVO variableWithFrenchLanguage = Fixtures.createVariable();
variableWithFrenchLanguage.setLanguage("FRA");
ObservationVariableVO variableWithNoLanguage = Fixtures.createVariable();
variableWithNoLanguage.setLanguage(null);
when(mockCropOntologyRepository.getVariableByIds(any())).thenReturn(
Arrays.asList(variableWithSpanishLanguage, variableWithFrenchLanguage, variableWithNoLanguage)
);
ModelAndView modelAndView = mockMvc.perform(get("/studies/{id}", study.getStudyDbId())
.locale(Locale.CHINA))
.andReturn()
.getModelAndView();
StudyModel model = (StudyModel) modelAndView.getModel().get("model");
assertThat(model.getVariables()).hasSize(2).contains(variableWithNoLanguage);
}
}
private void testSitemap(int index, String expectedContent) throws Exception {
MvcResult mvcResult = mockMvc.perform(get("/faidare/studies/sitemap-" + index + ".txt")
.contextPath("/faidare"))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment