package org.genedb.web.mvc.controller; //import org.genedb.db.taxon.TaxonNode; import org.genedb.db.taxon.TaxonNodeList; //import org.genedb.querying.core.LuceneQuery; import org.genedb.querying.core.Query; import org.genedb.querying.core.QueryException; import org.genedb.querying.core.QueryFactory; import org.genedb.querying.tmpquery.GeneSummary; import org.genedb.querying.tmpquery.TaxonQuery; import org.genedb.util.MutableInteger; //import org.genedb.web.mvc.controller.WebConstants; //import org.genedb.web.mvc.controller.download.ResultEntry; //import org.genedb.web.mvc.model.ResultsCacheFactory; import org.apache.log4j.Logger; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; //import org.springframework.util.StringUtils; import org.springframework.validation.BindingResult; import org.springframework.validation.DataBinder; //import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; //import org.springframework.web.bind.annotation.RequestParam; import java.util.List; import java.util.Map; //import java.util.Map.Entry; //import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import com.google.common.collect.Lists; import com.google.common.collect.Maps; //import com.sleepycat.collections.StoredMap; @Controller @RequestMapping("/ws") public class WsQueryController implements ApplicationContextAware { private static final Logger logger = Logger.getLogger(WsQueryController.class); private ApplicationContext applicationContext; //@Autowired private QueryFactory queryFactory; //private ResultsCacheFactory resultsCacheFactory; public void setQueryFactory(QueryFactory queryFactory) { this.queryFactory = queryFactory; } private static Map<String, String> maps = Maps.newLinkedHashMap(); private PathMatcher pathMatcher = new AntPathMatcher(); static { maps.put("proteinLengthQuery", "/from/{min}/to/{max}"); maps.put("b", "/{min}/to/{max}"); maps.put("c", "/{min}/{max}"); maps.put("d", "/size/{min}/to/{max}"); maps.put("e", "/size/{min}"); } private Map<String, MutableInteger> numQueriesRun = Maps.newHashMap(); @RequestMapping(method = RequestMethod.GET, value="/**") public String process( HttpServletRequest request, HttpSession session, Model model) throws QueryException { String path = request.getPathInfo(); logger.error(path); String queryName = lookupQuery(path); if (queryName == null) { // 404 return null; } Map<String, String> params = pathMatcher.extractUriTemplateVariables(maps.get(queryName), path); logger.error("Map is "+params); if (params == null) { // ? 500 return null; } //Query query = queryFactory.retrieveQuery(queryName); Query query = applicationContext.getBean(queryName, Query.class); logger.error(String.format("The '%s' has generated '%s'", queryName, query)); BindingResult errors = populateQuery(query, params); logger.error("Errors are "+errors); //Validate initialised form //query.validate(query, errors); if (errors.hasErrors()) { logger.error("Validator found errors"); model.addAttribute(BindingResult.MODEL_KEY_PREFIX + "query", errors); return "search/"+queryName; } logger.debug("Validator found no errors"); @SuppressWarnings("unchecked") List<Object> results = query.getResults(); logger.error(String.format("The number of results is '%d'", results.size())); //Dispatch request to appropriate view return findDestinationView(queryName, query, model, results, session); } private BindingResult populateQuery(Query query, Map<String, String> params) { DataBinder db = new DataBinder(query); MutablePropertyValues mpvs = new MutablePropertyValues(params); db.bind(mpvs); return db.getBindingResult(); } private String lookupQuery(String path) { List<String> matches = Lists.newArrayList(); for (Map.Entry<String, String> entry : maps.entrySet()) { String template = entry.getValue(); if (pathMatcher.matchStart(template, path)) { matches.add(entry.getKey()); logger.error(String.format("Match '%s' fits", (Object) entry.getValue())); } } if (matches.size() > 1) { logger.error("Ambiguous match"); return null; } if (matches.size() == 0) { logger.error("No match"); return null; } return matches.get(0); } /** * Work out the correct view destination * @param queryName * @param query * @param taxonName * @param model * @param results * @param session * @return */ private String findDestinationView( String queryName, Query query, Model model, List<Object> results, HttpSession session){ //Get the current taxon name String taxonName = findTaxonName(query); switch (results.size()) { case 0: logger.debug("No results found for query"); model.addAttribute("taxonNodeName", taxonName); return "search/"+queryName; case 1: List<GeneSummary> gs = possiblyConvertList(results); return "redirect:/gene/" + gs.get(0).getSystematicId(); default: List<GeneSummary> gs2 = possiblyConvertList(results); model.addAttribute("results", results); //model.addAttribute("taxonNodeName", taxonName); return "redirect:/Results"; } } @ManagedAttribute(description="The no. of times each query has been attempted to be run") public Map<String, MutableInteger> getNumQueriesRun() { return numQueriesRun; } protected List<GeneSummary> possiblyConvertList(List results) { List<GeneSummary> gs; Object firstItem = results.get(0); if (firstItem instanceof GeneSummary) { gs = results; } else { gs = Lists.newArrayListWithExpectedSize(results.size()); for (Object o : results) { gs.add(new GeneSummary((String) o)); } } return gs; } protected String findTaxonName(Query query){ String taxonName = null; if (query instanceof TaxonQuery) { TaxonNodeList nodes = ((TaxonQuery) query).getTaxons(); if (nodes != null && nodes.getNodeCount() > 0) { taxonName = nodes.getNodes().get(0).getLabel(); } // FIXME } return taxonName; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }