package uk.ac.ebi.ep.controller; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import uk.ac.ebi.ep.base.comparison.EnzymeComparison; import uk.ac.ebi.ep.data.domain.UniprotEntry; import uk.ac.ebi.ep.data.enzyme.model.EnzymeModel; import uk.ac.ebi.ep.data.exceptions.EnzymeRetrieverException; import uk.ac.ebi.ep.data.search.model.SearchModel; import uk.ac.ebi.ep.data.search.model.SearchParams; /** * Controller for basket actions. * * @author rafa * @since 1.1.0 */ @Controller public class BasketController extends AbstractController { private static final Logger LOGGER = Logger.getLogger(BasketController.class); /** * Updates the basket with enzymes (summaries) to compare or download. * * @param response the HTTP response to write to. * @param id the basket ID to add/remove (see * {@link Functions#getSummaryBasketId(EnzymeSummary)}. It may be a * semicolon-separated list of basket IDs, which will be processed in block. * @param checked if <code>true</code>, add the accession; if * <code>false</code>, remove it. * @param session the user session. * @return a string with the current number of enzymes in the basket. */ @RequestMapping(value = "/ajax/basket") @ResponseBody protected String updateBasket(HttpServletResponse response, @RequestParam String id, @RequestParam Boolean checked, HttpSession session) { @SuppressWarnings("unchecked") Map<String, UniprotEntry> lastSummaries = (Map<String, UniprotEntry>) session.getAttribute(Attribute.lastSummaries.name()); @SuppressWarnings("unchecked") Map<String, UniprotEntry> basket = (Map<String, UniprotEntry>) session.getAttribute(Attribute.basket.name()); if (basket == null) { basket = Collections.synchronizedMap( new LinkedHashMap<String, UniprotEntry>()); session.setAttribute(Attribute.basket.name(), basket); } for (String basketId : id.split(";")) { if (checked && lastSummaries != null) { final UniprotEntry summary = lastSummaries.get(basketId); if (summary != null) { basket.put(basketId, summary); } if (summary == null) { // build a fresh one: // TODO } } else { basket.remove(basketId); } } response.setContentType("text/plain"); return String.valueOf(basket.size()); } @RequestMapping(value = "/basket") protected String getBasket(Model model) { model.addAttribute("searchModel", newEmptySearchModel()); model.addAttribute("searchConfig", searchConfig); return Attribute.basket.name(); } /** * Compares the two enzymes (accessions) stored in the user session (see * {@link #Attribute.basket.name()}. * * @param model the model to populate with the comparison. * @param session the user session containing the enzymes' accessions. * @param accs UniProt accessions of the enzymes to be compared (exactly 2). * @return <code>"comparison"</code> if everything goes well, * <code>"error"</code> otherwise (less than two enzymes selected to * compare, for example). * @throws EnzymeRetrieverException in case of problem retrieving the * enzymes, before the comparison. */ @RequestMapping(value = "/compare") protected String getComparison(Model model, HttpSession session, @RequestParam(value = "acc") String[] accs) throws EnzymeRetrieverException { model.addAttribute("searchModel", newEmptySearchModel()); // Filter the incoming accessions, keep only two non-empty: String[] theAccs = new String[2]; int j = 0; for (String acc : accs) { if (acc.length() == 0) { continue; } theAccs[j++] = acc; if (j == 2) { break; } } ExecutorService pool = null; try { EnzymeModel models[] = new EnzymeModel[2]; LOGGER.debug("Getting enzyme models..."); pool = Executors.newFixedThreadPool(2); CompletionService<EnzymeModel> cs = new ExecutorCompletionService<>(pool); for (String acc : theAccs) { cs.submit(new EnzymeModelCallable(acc)); } for (int i = 0; i < 2; i++) { EnzymeModel em = cs.take().get(); if (em.getUniprotaccessions().get(0).equals(theAccs[0])) { models[0] = em; } else { models[1] = em; } } LOGGER.debug("Comparison started..."); EnzymeComparison comparison = new EnzymeComparison(models[0], models[1]); LOGGER.debug("Comparison finished"); model.addAttribute("comparison", comparison); //pdbImgUrl = http://www.ebi.ac.uk/pdbe/static/entry/{0}_deposited_chain_front_image-200x200.png model.addAttribute("pdbImgUrl", pdbImgUrl); model.addAttribute("pdbStructureCompareUrl", pdbStructureCompareUrl); model.addAttribute("uniprotAlignUrl", uniprotAlignUrl); model.addAttribute("reactomeConfig", reactomeConfig); model.addAttribute("intenzConfig", intenzConfig); return "comparison"; } catch (InterruptedException | ExecutionException e) { String errorParam = theAccs[0] + "," + theAccs[1]; LOGGER.error("Unable to compare enzymes: " + errorParam, e); model.addAttribute("errorCode", "comparison"); model.addAttribute("errorParam", errorParam); return "error"; } finally { if (pool != null) { pool.shutdownNow(); } } } private SearchModel newEmptySearchModel() { SearchModel searchModelForm = new SearchModel(); SearchParams searchParams = new SearchParams(); searchParams.setStart(0); searchParams.setType(SearchParams.SearchType.KEYWORD); searchParams.setPrevioustext(""); searchModelForm.setSearchparams(searchParams); return searchModelForm; } private class EnzymeModelCallable implements Callable<EnzymeModel> { private final String acc; public EnzymeModelCallable(String acc) { this.acc = acc; } @Override public EnzymeModel call() throws Exception { enzymeRetriever.setEnzymePortalService(enzymePortalService); enzymeRetriever.setLiteratureService(literatureService); enzymeRetriever.setIntenzAdapter(intenzAdapter); enzymeRetriever.setChebiAdapter(chebiAdapter); return enzymeRetriever.getWholeModel(acc); } } }