/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package uk.ac.ebi.ep.controller;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import uk.ac.ebi.ep.data.common.CommonSpecies;
import uk.ac.ebi.ep.data.domain.UniprotEntry;
import uk.ac.ebi.ep.data.search.model.Compound;
import uk.ac.ebi.ep.data.search.model.Disease;
import uk.ac.ebi.ep.data.search.model.EcNumber;
import uk.ac.ebi.ep.data.search.model.SearchFilters;
import uk.ac.ebi.ep.data.search.model.SearchModel;
import uk.ac.ebi.ep.data.search.model.SearchParams;
import uk.ac.ebi.ep.data.search.model.SearchResults;
import uk.ac.ebi.ep.data.search.model.Species;
/**
*
* @author joseph
*/
@Controller
public class ControllerAdvisor extends AbstractController {
protected static final String FILTER_BY_FACETS = "/search-enzymes/filter";
private static final String RESULT = "/searches";
private static final int SEARCH_PAGESIZE = 10;
@RequestMapping(value = FILTER_BY_FACETS, method = RequestMethod.POST)
public String filterByFacetsPost(@ModelAttribute("searchModel") SearchModel searchModel, @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
@RequestParam(value = "ec", required = false) String ec, @RequestParam(value = "ecname", required = false) String ecname,
@RequestParam(value = "taxId", required = false) Long taxId, @RequestParam(value = "organismName", required = false) String organismName,
Model model, HttpServletRequest request, HttpSession session, RedirectAttributes attributes) {
return filterByFacets(searchModel, pageNumber, ec, ecname, taxId, organismName, model, request, session, attributes);
}
@RequestMapping(value = FILTER_BY_FACETS, method = RequestMethod.GET)
public String filterByFacets(@ModelAttribute("searchModel") SearchModel searchModel, @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
@RequestParam(value = "ec", required = true) String ec, @RequestParam(value = "ecname", required = false) String ecname,
@RequestParam(value = "taxId", required = false) Long taxId, @RequestParam(value = "organismName", required = false) String organismName,
Model model, HttpServletRequest request, HttpSession session, RedirectAttributes attributes) {
if (pageNumber < 1) {
pageNumber = 1;
}
if (!StringUtils.isEmpty(ec)) {
return filterByFacetsEC(searchModel, pageNumber, ec, ecname, model, request, session, attributes);
} else {
return filterByFacetsTaxonomy(searchModel, pageNumber, taxId, organismName, model, request, session, attributes);
}
}
//@RequestMapping(value = FILTER_BY_FACETS, method = RequestMethod.GET)
private String filterByFacetsEC(@ModelAttribute("searchModel") SearchModel searchModel, @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
@RequestParam(value = "ec", required = true) String ec, @RequestParam(value = "ecname", required = false) String ecname,
Model model, HttpServletRequest request, HttpSession session, RedirectAttributes attributes) {
if (pageNumber < 1) {
pageNumber = 1;
}
Pageable pageable = new PageRequest(pageNumber - 1, SEARCH_PAGESIZE, Sort.Direction.ASC, "entryType", "function");
Page<UniprotEntry> page = new PageImpl<>(new ArrayList<>(), pageable, 0);
List<Species> species = enzymePortalService.findSpeciesByEcNumber(ec);
List<Compound> compouds = enzymePortalService.findCompoundsByEcNumber(ec);
List<Disease> diseases = enzymePortalService.findDiseasesByEcNumber(ec);
List<EcNumber> enzymeFamilies = enzymePortalService.findEnzymeFamiliesByEcNumber(ec);
SearchFilters filters = new SearchFilters();
//Set<Species> speciesFilter = species.stream().collect(Collectors.toSet());
List<Species> speciesFacets = applySpeciesFilter(species);
filters.setSpecies(speciesFacets);
filters.setCompounds(compouds);
filters.setDiseases(diseases);
filters.setEcNumbers(enzymeFamilies);
SearchParams searchParams = searchModel.getSearchparams();
searchParams.setText(ec);
searchParams.setSize(SEARCH_PAGESIZE);
searchParams.setType(SearchParams.SearchType.KEYWORD);
searchParams.setPrevioustext("");
searchModel.setSearchparams(searchParams);
SearchResults searchResults = new SearchResults();
searchResults.setSearchfilters(filters);
searchModel.setSearchresults(searchResults);
SearchParams searchParameters = searchModel.getSearchparams();
String compound_autocompleteFilter = request.getParameter("searchparams.compounds");
String specie_autocompleteFilter = request.getParameter("_ctempList_selected");
String diseases_autocompleteFilter = request.getParameter("_DtempList_selected");
// Filter:
List<String> specieFilter = searchParameters.getSpecies();
List<String> compoundFilter = searchParameters.getCompounds();
List<String> diseaseFilter = searchParameters.getDiseases();
List<Integer> ecFilter = searchParameters.getEcFamilies();
//remove empty string in the filter to avoid unsual behavior of the filter facets
if (specieFilter.contains("")) {
specieFilter.remove("");
}
if (compoundFilter.contains("")) {
compoundFilter.remove("");
}
if (diseaseFilter.contains("")) {
diseaseFilter.remove("");
}
//to ensure that the seleted item is used in species filter, add the selected to the list. this is a workaround. different JS were used for auto complete and normal filter
if ((specie_autocompleteFilter != null && StringUtils.hasLength(specie_autocompleteFilter) == true) && StringUtils.isEmpty(compound_autocompleteFilter) && StringUtils.isEmpty(diseases_autocompleteFilter)) {
specieFilter.add(specie_autocompleteFilter);
}
if ((diseases_autocompleteFilter != null && StringUtils.hasLength(diseases_autocompleteFilter) == true) && StringUtils.isEmpty(compound_autocompleteFilter) && StringUtils.isEmpty(specie_autocompleteFilter)) {
diseaseFilter.add(diseases_autocompleteFilter);
}
//both from auto complete and normal selection. selected items are displayed on top the list and returns back to the orignial list when not selected.
//SearchResults searchResults = resultSet;
List<Species> defaultSpeciesList = searchResults.getSearchfilters().getSpecies();
resetSelectedSpecies(defaultSpeciesList);
searchParameters.getSpecies().stream().forEach((selectedItems) -> {
defaultSpeciesList.stream().filter((theSpecies) -> (selectedItems.equals(theSpecies.getScientificname()))).forEach((theSpecies) -> {
theSpecies.setSelected(true);
});
});
List<Compound> defaultCompoundList = searchResults.getSearchfilters().getCompounds();
resetSelectedCompounds(defaultCompoundList);
searchParameters.getCompounds().stream().forEach((SelectedCompounds) -> {
defaultCompoundList.stream().filter((theCompound) -> (SelectedCompounds.equals(theCompound.getId()))).forEach((theCompound) -> {
theCompound.setSelected(true);
});
});
List<Disease> defaultDiseaseList = searchResults.getSearchfilters().getDiseases();
resetSelectedDisease(defaultDiseaseList);
searchParameters.getDiseases().stream().forEach((selectedDisease) -> {
defaultDiseaseList.stream().filter((disease) -> (selectedDisease.equals(disease.getName()))).forEach((disease) -> {
disease.setSelected(true);
});
});
List<EcNumber> defaultEcNumberList = searchResults.getSearchfilters().getEcNumbers();
resetSelectedEcNumber(defaultEcNumberList);
searchParameters.getEcFamilies().stream().forEach((selectedEcFamily) -> {
defaultEcNumberList.stream().filter((ecn) -> (selectedEcFamily.equals(ecn.getEc()))).forEach((ecn) -> {
ecn.setSelected(true);
});
});
//methods
//ec only
if (specieFilter.isEmpty() && compoundFilter.isEmpty() && diseaseFilter.isEmpty() && !StringUtils.isEmpty(ec)) {
page = enzymePortalService.filterByEc(ec, pageable);
// page = this.enzymePortalService.findEnzymeViewByEc(ec, pageable);
}
//specie only
if (!specieFilter.isEmpty() && compoundFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndSpecies(ec, specieFilter, pageable);
//page = enzymePortalService.findEnzymeViewByEcAndSpecies(ec, specieFilter, pageable);
}
// compounds only
if (!compoundFilter.isEmpty() && specieFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndCompounds(ec, compoundFilter, pageable);
}
// disease only
if (specieFilter.isEmpty() && compoundFilter.isEmpty() && !diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndDiseases(ec, diseaseFilter, pageable);
}
//species, compound and ec
if (!specieFilter.isEmpty() && !compoundFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndSpeciesAndCompound(ec, specieFilter, compoundFilter, pageable);
}
//species, disease and ec
if (!specieFilter.isEmpty() && compoundFilter.isEmpty() && !diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndSpeciesAndDiseases(ec, specieFilter, diseaseFilter, pageable);
}
//species,compounds, disease and ec
if (!specieFilter.isEmpty() && !compoundFilter.isEmpty() && !diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndSpeciesAndCompoundAndDiseases(ec, specieFilter, compoundFilter, diseaseFilter, pageable);
}
//compound, diseases and ec
if (specieFilter.isEmpty() && !compoundFilter.isEmpty() && !diseaseFilter.isEmpty()) {
page = enzymePortalService.filterByEcAndCompoundAndDiseases(ec, compoundFilter, diseaseFilter, pageable);
}
List<UniprotEntry> result = page.getContent();//.stream().map(EnzymePortal::new).distinct().map(EnzymePortal::unwrapProtein).filter(Objects::nonNull).collect(Collectors.toList());
int current = page.getNumber() + 1;
int begin = Math.max(1, current - 5);
int end = Math.min(begin + 10, page.getTotalPages());
model.addAttribute("page", page);
model.addAttribute("beginIndex", begin);
model.addAttribute("endIndex", end);
model.addAttribute("currentIndex", current);
model.addAttribute("ecname", ecname);
model.addAttribute("ec", ec);
model.addAttribute("summaryEntries", result);
searchResults.setTotalfound(page.getTotalElements());
searchResults.setSearchfilters(filters);
searchResults.setSummaryentries(result);
searchModel.setSearchresults(searchResults);
String searchKey = getSearchKey(searchModel.getSearchparams());
cacheSearch(session.getServletContext(), searchKey, searchResults);
setLastSummaries(session, searchResults.getSummaryentries());
clearHistory(session);
addToHistory(session, searchModel.getSearchparams().getType(),
searchKey);
model.addAttribute("searchFilter", filters);
model.addAttribute(BROWSE_VIDEO, BROWSE_VIDEO);
request.setAttribute("searchTerm", searchModel.getSearchparams().getText());
model.addAttribute("searchModel", searchModel);
model.addAttribute("searchConfig", searchConfig);
return RESULT;
}
private String filterByFacetsTaxonomy(@ModelAttribute("searchModel") SearchModel searchModel, @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
@RequestParam(value = "taxId", required = true) Long taxId,
@RequestParam(value = "organismName", required = false) String organismName,
Model model, HttpServletRequest request, HttpSession session, RedirectAttributes attributes) {
List<Species> species = enzymePortalService.findSpeciesByTaxId(taxId);
List<Compound> compouds = enzymePortalService.findCompoundsByTaxId(taxId);
List<Disease> diseases = enzymePortalService.findDiseasesByTaxId(taxId);
List<EcNumber> enzymeFamilies = enzymePortalService.findEnzymeFamiliesByTaxId(taxId);
SearchFilters filters = new SearchFilters();
filters.setSpecies(species);
filters.setCompounds(compouds);
filters.setDiseases(diseases);
filters.setEcNumbers(enzymeFamilies);
SearchParams searchParams = searchModel.getSearchparams();
searchParams.setText(organismName);
searchParams.setSize(SEARCH_PAGESIZE);
searchModel.setSearchparams(searchParams);
SearchResults searchResults = new SearchResults();
searchResults.setSearchfilters(filters);
searchModel.setSearchresults(searchResults);
SearchParams searchParameters = searchModel.getSearchparams();
String compound_autocompleteFilter = request.getParameter("searchparams.compounds");
String specie_autocompleteFilter = request.getParameter("_ctempList_selected");
String diseases_autocompleteFilter = request.getParameter("_DtempList_selected");
// Filter:
List<String> specieFilter = searchParameters.getSpecies();
List<String> compoundFilter = searchParameters.getCompounds();
List<String> diseaseFilter = searchParameters.getDiseases();
List<Integer> ecFilter = searchParameters.getEcFamilies();
//remove empty string in the filter to avoid unsual behavior of the filter facets
if (specieFilter.contains("")) {
specieFilter.remove("");
}
if (compoundFilter.contains("")) {
compoundFilter.remove("");
}
if (diseaseFilter.contains("")) {
diseaseFilter.remove("");
}
//to ensure that the seleted item is used in species filter, add the selected to the list. this is a workaround. different JS were used for auto complete and normal filter
if ((specie_autocompleteFilter != null && StringUtils.hasLength(specie_autocompleteFilter) == true) && StringUtils.isEmpty(compound_autocompleteFilter) && StringUtils.isEmpty(diseases_autocompleteFilter)) {
specieFilter.add(specie_autocompleteFilter);
}
if ((diseases_autocompleteFilter != null && StringUtils.hasLength(diseases_autocompleteFilter) == true) && StringUtils.isEmpty(compound_autocompleteFilter) && StringUtils.isEmpty(specie_autocompleteFilter)) {
diseaseFilter.add(diseases_autocompleteFilter);
}
//both from auto complete and normal selection. selected items are displayed on top the list and returns back to the orignial list when not selected.
//SearchResults searchResults = resultSet;
List<Species> defaultSpeciesList = searchResults.getSearchfilters().getSpecies();
resetSelectedSpecies(defaultSpeciesList);
searchParameters.getSpecies().stream().forEach((selectedItems) -> {
defaultSpeciesList.stream().filter((theSpecies) -> (selectedItems.equals(theSpecies.getScientificname()))).forEach((theSpecies) -> {
theSpecies.setSelected(true);
});
});
List<Compound> defaultCompoundList = searchResults.getSearchfilters().getCompounds();
resetSelectedCompounds(defaultCompoundList);
searchParameters.getCompounds().stream().forEach((SelectedCompounds) -> {
defaultCompoundList.stream().filter((theCompound) -> (SelectedCompounds.equals(theCompound.getName()))).forEach((theCompound) -> {
theCompound.setSelected(true);
});
});
List<Disease> defaultDiseaseList = searchResults.getSearchfilters().getDiseases();
resetSelectedDisease(defaultDiseaseList);
searchParameters.getDiseases().stream().forEach((selectedDisease) -> {
defaultDiseaseList.stream().filter((disease) -> (selectedDisease.equals(disease.getName()))).forEach((disease) -> {
disease.setSelected(true);
});
});
List<EcNumber> defaultEcNumberList = searchResults.getSearchfilters().getEcNumbers();
resetSelectedEcNumber(defaultEcNumberList);
searchParameters.getEcFamilies().stream().forEach((selectedEcFamily) -> {
defaultEcNumberList.stream().filter((ec) -> (selectedEcFamily.equals(ec.getEc()))).forEach((ec) -> {
ec.setSelected(true);
});
});
Pageable pageable = new PageRequest(pageNumber - 1, SEARCH_PAGESIZE, Sort.Direction.ASC, "function", "entryType");
Page<UniprotEntry> page = new PageImpl<>(new ArrayList<>(), pageable, 0);
//specie only
if (specieFilter.isEmpty() && compoundFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterBySpecie(taxId, pageable);
}
//specie only
if (!specieFilter.isEmpty() && compoundFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterBySpecie(taxId, pageable);
}
// compounds only
if (!compoundFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndCompounds(taxId, compoundFilter, pageable);
}
// disease only
if (compoundFilter.isEmpty() && !diseaseFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndDiseases(taxId, diseaseFilter, pageable);
}
//ec only
if (compoundFilter.isEmpty() && diseaseFilter.isEmpty() && !ecFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndEc(taxId, ecFilter, pageable);
}
//compound and diseases
if (!compoundFilter.isEmpty() && !diseaseFilter.isEmpty() && ecFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndCompoundsAndDiseases(taxId, compoundFilter, diseaseFilter, pageable);
}
//compound and ec
if (!compoundFilter.isEmpty() && !ecFilter.isEmpty() && diseaseFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndCompoundsAndEc(taxId, compoundFilter, ecFilter, pageable);
}
//disease and ec
if (!ecFilter.isEmpty() && !diseaseFilter.isEmpty() && compoundFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndDiseasesAndEc(taxId, diseaseFilter, ecFilter, pageable);
}
//disease and compounds and ec
if (!ecFilter.isEmpty() && !diseaseFilter.isEmpty() && !compoundFilter.isEmpty()) {
page = enzymePortalService.filterBySpecieAndCompoundsAndDiseasesAndEc(taxId, compoundFilter, diseaseFilter, ecFilter, pageable);
}
model.addAttribute("searchFilter", filters);
List<UniprotEntry> result = page.getContent();
int current = page.getNumber() + 1;
int begin = Math.max(1, current - 5);
int end = Math.min(begin + 10, page.getTotalPages());
model.addAttribute("page", page);
model.addAttribute("beginIndex", begin);
model.addAttribute("endIndex", end);
model.addAttribute("currentIndex", current);
model.addAttribute("organismName", organismName);
model.addAttribute("taxId", taxId);
model.addAttribute("summaryEntries", result);
searchResults.setTotalfound(page.getTotalElements());
searchResults.setSearchfilters(filters);
searchResults.setSummaryentries(result);
searchModel.setSearchresults(searchResults);
model.addAttribute("searchModel", searchModel);
model.addAttribute("searchConfig", searchConfig);
String searchKey = getSearchKey(searchModel.getSearchparams());
cacheSearch(session.getServletContext(), searchKey, searchResults);
setLastSummaries(session, searchResults.getSummaryentries());
clearHistory(session);
addToHistory(session, searchModel.getSearchparams().getType(),
searchKey);
request.setAttribute("searchTerm", searchModel.getSearchparams().getText());
return RESULT;
}
protected List<Species> applySpeciesFilter(List<Species> uniqueSpecies) {
// String[] commonSpecie = {"HUMAN", "MOUSE", "RAT", "Fruit fly", "WORM", "Yeast", "ECOLI"};
// CommonSpecies [] commonSpecie = {"Homo sapiens","Mus musculus","Rattus norvegicus", "Drosophila melanogaster","Saccharomyces cerevisiae"};
// List<String> commonSpecieList = Arrays.asList(commonSpecie);
List<String> commonSpecieList = new ArrayList<>();
for (CommonSpecies commonSpecies : CommonSpecies.values()) {
commonSpecieList.add(commonSpecies.getScientificName());
}
Map<Integer, Species> priorityMapper = new TreeMap<>();
AtomicInteger key = new AtomicInteger(50);
AtomicInteger customKey = new AtomicInteger(6);
uniqueSpecies.stream().forEach((sp) -> {
if (commonSpecieList.contains(sp.getScientificname().split("\\(")[0].trim())) {
// HUMAN, MOUSE, RAT, Fly, WORM, Yeast, ECOLI
// "Homo sapiens","Mus musculus","Rattus norvegicus", "Drosophila melanogaster","WORM","Saccharomyces cerevisiae","ECOLI"
if (sp.getScientificname().equalsIgnoreCase(CommonSpecies.HUMAN.getScientificName())) {
priorityMapper.put(1, sp);
} else if (sp.getScientificname().equalsIgnoreCase(CommonSpecies.MOUSE.getScientificName())) {
priorityMapper.put(2, sp);
} else if (sp.getScientificname().equalsIgnoreCase(CommonSpecies.RAT.getScientificName())) {
priorityMapper.put(3, sp);
} else if (sp.getScientificname().equalsIgnoreCase(CommonSpecies.FRUIT_FLY.getScientificName())) {
priorityMapper.put(4, sp);
} else if (sp.getScientificname().equalsIgnoreCase(CommonSpecies.WORM.getScientificName())) {
priorityMapper.put(5, sp);
} else if (sp.getScientificname().equalsIgnoreCase(CommonSpecies.ECOLI.getScientificName())) {
priorityMapper.put(6, sp);
} else if (sp.getScientificname().split("\\(")[0].trim().equalsIgnoreCase(CommonSpecies.BAKER_YEAST.getScientificName())) {
priorityMapper.put(customKey.getAndIncrement(), sp);
}
} else {
priorityMapper.put(key.getAndIncrement(), sp);
}
});
List<Species> speciesFilters = new LinkedList<>();
priorityMapper.entrySet().stream().forEach(map -> {
speciesFilters.add(map.getValue());
});
return speciesFilters;
}
}