From: <rv...@us...> - 2009-07-02 10:43:55
|
Revision: 159 http://treebase.svn.sourceforge.net/treebase/?rev=159&view=rev Author: rvos Date: 2009-07-02 10:43:46 +0000 (Thu, 02 Jul 2009) Log Message: ----------- Major refactoring to facilitate CQL queries and RSS1.0 result sets Modified Paths: -------------- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/MatrixSearchController.java trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/PhyloWSController.java trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/SearchController.java trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/StudySearchController.java trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TaxonSearchController.java trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TreeSearchController.java Modified: trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/MatrixSearchController.java =================================================================== --- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/MatrixSearchController.java 2009-07-02 10:41:25 UTC (rev 158) +++ trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/MatrixSearchController.java 2009-07-02 10:43:46 UTC (rev 159) @@ -20,13 +20,16 @@ package org.cipres.treebase.web.controllers; +import java.io.IOException; import java.util.Collection; import java.util.HashSet; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.cipres.treebase.TreebaseUtil; import org.cipres.treebase.RangeExpression.MalformedRangeExpression; import org.cipres.treebase.domain.matrix.CharacterMatrix; import org.cipres.treebase.domain.matrix.Matrix; @@ -34,11 +37,21 @@ import org.cipres.treebase.domain.search.MatrixSearchResults; import org.cipres.treebase.domain.search.SearchResults; import org.cipres.treebase.domain.search.SearchResultsType; +import org.cipres.treebase.domain.search.TreeSearchResults; import org.cipres.treebase.web.Constants; import org.cipres.treebase.web.util.RequestMessageSetter; import org.cipres.treebase.web.util.SearchMessageSetter; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; +import org.z3950.zing.cql.CQLAndNode; +import org.z3950.zing.cql.CQLBooleanNode; +import org.z3950.zing.cql.CQLNode; +import org.z3950.zing.cql.CQLNotNode; +import org.z3950.zing.cql.CQLOrNode; +import org.z3950.zing.cql.CQLParseException; +import org.z3950.zing.cql.CQLParser; +import org.z3950.zing.cql.CQLRelation; +import org.z3950.zing.cql.CQLTermNode; /** * MatrixSearchController.java @@ -72,50 +85,162 @@ clearMessages(request); String formName = request.getParameter("formName"); + String query = request.getParameter("query"); LOGGER.info("formName is '" + formName + "'"); - + if ( ! TreebaseUtil.isEmpty(query) ) { + /* + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<Matrix> queryResults = doCQLQuery(root, new HashSet<Matrix>(),request, response, errors); + MatrixSearchResults tsr = new MatrixSearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return new ModelAndView("search/matrixSearch", Constants.RESULT_SET, tsr); + } + else { + return this.searchResultsAsRDF(tsr, request, root); + } + */ + return this.handleQueryRequest(request, response, errors); + } + if (formName.equals("matrixSimple")) { String buttonName = request.getParameter("searchButton"); - + Set<Matrix> matches = new HashSet<Matrix>(); + String searchTerm = convertStars(request.getParameter("searchTerm")); + SearchMessageSetter mSetter = new RequestMessageSetter(request); + MatrixSearchResults oldRes; + { + SearchResults<?> sr = searchResults(request); + if (sr != null) { + oldRes = (MatrixSearchResults) sr.convertToMatrices(); + } else { + oldRes = new MatrixSearchResults (); // TODO: Convert existing search results to new type + } + } if (buttonName.equals("matrixID")) { - return doSearch(request, response, SearchType.byID, errors); + matches.addAll(doSearch(request, response, SearchType.byID, errors,searchTerm)); } else if (buttonName.equals("matrixTitle")) { - return doSearch(request, response, SearchType.byTitle, errors); + matches.addAll(doSearch(request, response, SearchType.byTitle, errors,searchTerm)); } else if (buttonName.equals("matrixType")) { - return doSearch(request, response, SearchType.byType, errors); + matches.addAll(doSearch(request, response, SearchType.byType, errors,searchTerm)); } else if (buttonName.equals("matrixNTAX")) { - return doSearch(request, response, SearchType.byNTAX, errors); + matches.addAll(doSearch(request, response, SearchType.byNTAX, errors,searchTerm)); } else if (buttonName.equals("matrixNCHAR")) { - return doSearch(request, response, SearchType.byNCHAR, errors); + matches.addAll(doSearch(request, response, SearchType.byNCHAR, errors,searchTerm)); } else { throw new Error("Unknown search button name '" + buttonName + "'"); } - } else { + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + SearchResults<Matrix> newRes = intersectSearchResults(oldRes, + new MatrixSearchResults(matches), mSetter, "No matching matrices found"); + saveSearchResults(request, newRes); + return new ModelAndView("search/matrixSearch", Constants.RESULT_SET, newRes); + } + else { + return this.searchResultsAsRDF(new MatrixSearchResults(matches), request, null, "matrix", "matrix"); + } + } + + else { return super.onSubmit(request, response, command, errors); } } - private ModelAndView doSearch( + private Set<Matrix> doCQLQuery( + CQLNode node, + Set<Matrix> results, + HttpServletRequest request, + HttpServletResponse response, + BindException errors + ) throws InstantiationException { + if ( node instanceof CQLBooleanNode ) { + Set<Matrix> resultsLeft = doCQLQuery(((CQLBooleanNode)node).left,results, request, response, errors); + Set<Matrix> resultsRight = doCQLQuery(((CQLBooleanNode)node).right,results, request, response, errors); + if ( node instanceof CQLNotNode ) { + for ( Matrix rightMatrix : resultsRight ) { + if ( resultsLeft.contains(rightMatrix) ) + resultsLeft.remove(rightMatrix); + } + } + else if ( node instanceof CQLOrNode ) { + resultsLeft.addAll(resultsRight); + } + else if ( node instanceof CQLAndNode ) { + Set<Matrix> resultsUnion = new HashSet<Matrix>(); + for ( Matrix leftMatrix : resultsLeft ) { + if ( resultsRight.contains(leftMatrix) ) + resultsUnion.add(leftMatrix); + } + resultsLeft = resultsUnion; + } + results = resultsLeft; + } + else if ( node instanceof CQLTermNode ) { + CQLTermNode term = (CQLTermNode)node; + String index = term.getIndex(); + if ( index.startsWith("tb.title") ) { + results.addAll(doSearch(request, response, SearchType.byTitle, errors, term.getTerm())); + } else if ( index.startsWith("tb.identifier") ) { + results.addAll(doSearch(request, response, SearchType.byID, errors, term.getTerm())); + } else if ( index.startsWith("tb.type") ) { + results.addAll(doSearch(request, response, SearchType.byType, errors, term.getTerm())); + } else if ( index.startsWith("tb.ntax") ) { + results.addAll(doSearch(request, response, SearchType.byNTAX, errors, term.getTerm())); + } else if ( index.startsWith("tb.nchar") ) { + results.addAll(doSearch(request, response, SearchType.byNTAX, errors, term.getTerm())); + } else { + // issue warnings + addMessage(request, "Unsupported index: " + index); + } + } + logger.debug(node); + return results; + } + + private CQLNode normalizeParseTree(CQLNode node) { + if ( node instanceof CQLBooleanNode ) { + ((CQLBooleanNode)node).left = normalizeParseTree(((CQLBooleanNode)node).left); + ((CQLBooleanNode)node).right = normalizeParseTree(((CQLBooleanNode)node).right); + return node; + } + else if ( node instanceof CQLTermNode ) { + String index = ((CQLTermNode)node).getIndex(); + String term = ((CQLTermNode)node).getTerm(); + CQLRelation relation = ((CQLTermNode)node).getRelation(); + index = index.replaceAll("dcterms.title", "tb.title.matrix"); + index = index.replaceAll("dcterms.identifier", "tb.identifier.matrix"); + index = index.replaceAll("dcterms.extent", "tb.ntax.matrix"); + return new CQLTermNode(index,relation,term); + } + logger.debug(node); + return node; + } + + @SuppressWarnings("unchecked") + private Collection<Matrix> doSearch( HttpServletRequest request, HttpServletResponse response, SearchType searchType, - BindException errors) throws InstantiationException { + BindException errors, + String searchTerm) throws InstantiationException { - String searchTerm = convertStars(request.getParameter("searchTerm")); - String keywordSearchTerm = "%" + searchTerm + "%"; - SearchMessageSetter mSetter = new RequestMessageSetter(request); +// String searchTerm = convertStars(request.getParameter("searchTerm")); +// String keywordSearchTerm = "%" + searchTerm + "%"; +// SearchMessageSetter mSetter = new RequestMessageSetter(request); - MatrixSearchResults oldRes; - { - SearchResults<?> sr = searchResults(request); - if (sr != null) { - oldRes = (MatrixSearchResults) sr.convertToMatrices(); - } else { - oldRes = new MatrixSearchResults (); // TODO: Convert existing search results to new type - } - } +// MatrixSearchResults oldRes; +// { +// SearchResults<?> sr = searchResults(request); +// if (sr != null) { +// oldRes = (MatrixSearchResults) sr.convertToMatrices(); +// } else { +// oldRes = new MatrixSearchResults (); // TODO: Convert existing search results to new type +// } +// } Collection<Matrix> matches = null; MatrixService matrixService = getSearchService().getMatrixService(); @@ -164,13 +289,14 @@ } } matches.removeAll(orphanedMatrices); - - SearchResults<Matrix> newRes = intersectSearchResults(oldRes, - new MatrixSearchResults(matches), mSetter, "No matching matrices found"); - - saveSearchResults(request, newRes); + return matches; - return new ModelAndView("search/matrixSearch", Constants.RESULT_SET, newRes); +// SearchResults<Matrix> newRes = intersectSearchResults(oldRes, +// new MatrixSearchResults(matches), mSetter, "No matching matrices found"); +// +// saveSearchResults(request, newRes); +// +// return new ModelAndView("search/matrixSearch", Constants.RESULT_SET, newRes); } @@ -183,4 +309,36 @@ return "matrixSearch.html"; } + @Override + protected ModelAndView handleQueryRequest(HttpServletRequest request,HttpServletResponse response,BindException errors) throws CQLParseException, IOException, InstantiationException { + String query = request.getParameter("query"); + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<Matrix> queryResults = doCQLQuery(root, new HashSet<Matrix>(),request, response, errors); + MatrixSearchResults tsr = new MatrixSearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return new ModelAndView("search/matrixSearch", Constants.RESULT_SET, tsr); + } + else { + SearchResults<?> res = tsr; + String schema = null, original = "matrix"; + if ( ! TreebaseUtil.isEmpty(request.getParameter("recordSchema")) ) { + schema = request.getParameter("recordSchema"); + if ( schema.equals("tree") ) { + res = tsr.convertToTrees(); + } + else if ( schema.equals("taxon") ) { + res = tsr.convertToTaxa(); + } + else if ( schema.equals("study") ) { + res = tsr.convertToStudies(); + } + } + this.saveSearchResults(request, res); + return this.searchResultsAsRDF(res, request, root, schema, original); + } + } + } Modified: trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/PhyloWSController.java =================================================================== --- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/PhyloWSController.java 2009-07-02 10:41:25 UTC (rev 158) +++ trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/PhyloWSController.java 2009-07-02 10:43:46 UTC (rev 159) @@ -70,29 +70,33 @@ + "', should be /${class}/${NamespacedGUID}"); } String[] pathComponents = pathInfo.split("/"); - String rawNamespacedGUID = pathComponents[pathComponents.length-1]; - if ( rawNamespacedGUID.startsWith("uBio:") ) { - url = uBioBaseUrl + rawNamespacedGUID.substring("uBio:".length()); - } - else if ( rawNamespacedGUID.startsWith("NCBI:") ) { - url = ncbiBaseUrl + rawNamespacedGUID.substring("NCBI:".length()); - } - else { - NamespacedGUID namespacedGUID = new NamespacedGUID(rawNamespacedGUID); - TreebaseIDString tbID = namespacedGUID.getTreebaseIDString(); - if ( hasWebPage(pathComponents) ) { - if ( TreebaseUtil.isEmpty(req.getParameter(format)) ) { - url = domain + "/treebase-web/search/study/anyObjectAsRDF.html?namespacedGUID=" + namespacedGUID.toString(); - } - else if ( req.getParameter(format).equals("html") ) { - url = domain + createUrl(tbID.getTypePrefix(),tbID.getId()); - } - else { - url = domain + createDownloadUrl(tbID.getTypePrefix(),tbID.getId(),req.getParameter(format)); - } + if ( pathComponents[pathComponents.length-1].equals("find") ) { + url = domain + createSearchUrl(pathComponents[pathComponents.length-2],req); + } else { + String rawNamespacedGUID = pathComponents[pathComponents.length-1]; + if ( rawNamespacedGUID.startsWith("uBio:") ) { + url = uBioBaseUrl + rawNamespacedGUID.substring("uBio:".length()); } + else if ( rawNamespacedGUID.startsWith("NCBI:") ) { + url = ncbiBaseUrl + rawNamespacedGUID.substring("NCBI:".length()); + } else { - url = domain + "/treebase-web/search/study/anyObjectAsRDF.html?namespacedGUID=" + namespacedGUID.toString(); + NamespacedGUID namespacedGUID = new NamespacedGUID(rawNamespacedGUID); + TreebaseIDString tbID = namespacedGUID.getTreebaseIDString(); + if ( hasWebPage(pathComponents) ) { + if ( TreebaseUtil.isEmpty(req.getParameter(format)) ) { + url = domain + "/treebase-web/search/study/anyObjectAsRDF.html?namespacedGUID=" + namespacedGUID.toString(); + } + else if ( req.getParameter(format).equals("html") ) { + url = domain + createUrl(tbID.getTypePrefix(),tbID.getId()); + } + else { + url = domain + createDownloadUrl(tbID.getTypePrefix(),tbID.getId(),req.getParameter(format)); + } + } + else { + url = domain + "/treebase-web/search/study/anyObjectAsRDF.html?namespacedGUID=" + namespacedGUID.toString(); + } } } } catch ( MalformedTreebaseIDString e ) { @@ -109,6 +113,20 @@ return null; } + private String createSearchUrl(String path,HttpServletRequest request) { + StringBuilder sb = new StringBuilder(); + sb + .append("/treebase-web/search/") + .append(path) + .append("Search.html?query=") + .append(request.getParameter("query")) + .append("&format=") + .append(request.getParameter("format")) + .append("&recordSchema=") + .append(request.getParameter("recordSchema")); + return sb.toString(); + } + private boolean hasWebPage(String[] pathComponents) { for ( int i = ( pathComponents.length - 1 ); i >= 0; i-- ) { for ( int j = 0; j < classesWithPages.length; j++ ) { Modified: trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/SearchController.java =================================================================== --- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/SearchController.java 2009-07-02 10:41:25 UTC (rev 158) +++ trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/SearchController.java 2009-07-02 10:43:46 UTC (rev 159) @@ -22,6 +22,9 @@ package org.cipres.treebase.web.controllers; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -50,6 +53,8 @@ import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.RedirectView; +import org.z3950.zing.cql.CQLNode; +import org.z3950.zing.cql.CQLParseException; /** @@ -65,6 +70,8 @@ protected String formView; private TaxonLabelService mTaxonLabelService; + + protected abstract ModelAndView handleQueryRequest(HttpServletRequest request,HttpServletResponse response,BindException errors) throws CQLParseException, IOException, InstantiationException; protected ModelAndView onSubmit( HttpServletRequest request, @@ -110,6 +117,33 @@ return selectResultsView(request); } + protected ModelAndView searchResultsAsRDF (SearchResults<?> searchResults,HttpServletRequest request,CQLNode root, String schema, String original) throws UnsupportedEncodingException { + //${baseURL} + //${phyloWSPath} + //${normalizedCQLQuery} + //${searchResults} + //${domainAddress} + String phyloWSPath = "find/" + original; + request.getSession().setAttribute("searchResultsThawed", searchResults); + StringBuffer domainAddress = new StringBuffer("http://"); + domainAddress + .append(request.getServerName()) + .append(':') + .append(request.getServerPort()); + StringBuffer baseURL = new StringBuffer(domainAddress); + baseURL.append("/treebase-web/phylows"); + request.getSession().setAttribute("recordSchema", schema); + request.getSession().setAttribute("format", request.getParameter("format")); + request.getSession().setAttribute("baseURL", baseURL.toString()); + request.getSession().setAttribute("domainAddress", domainAddress.toString()); + request.getSession().setAttribute("phyloWSPath", phyloWSPath); + request.getSession().setAttribute("originalSection", original); + if ( null != root ) { + request.getSession().setAttribute("normalizedCQLQuery", URLEncoder.encode(root.toCQL(),"UTF-8")); + } + return new ModelAndView(new RedirectView("searchResultsAsRDF.html")); + } + protected <E extends TBPersistable> SearchResults<E> intersectSearchResults( SearchResults<E> oldRes, SearchResults<E> newRes, @@ -380,6 +414,10 @@ protected ModelAndView showForm(HttpServletRequest request, HttpServletResponse response, BindException bindException, Map model) throws Exception { + String query = request.getParameter("query"); + if ( query != null ) { + return this.handleQueryRequest(request, response, bindException); + } String action = request.getParameter("action"); if (action != null && action.equals("discard") && request.getMethod().equals("GET")) { discardSearchResults(request); Modified: trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/StudySearchController.java =================================================================== --- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/StudySearchController.java 2009-07-02 10:41:25 UTC (rev 158) +++ trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/StudySearchController.java 2009-07-02 10:43:46 UTC (rev 159) @@ -20,27 +20,36 @@ package org.cipres.treebase.web.controllers; +import java.io.IOException; import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.cipres.treebase.TreebaseIDString; +import org.cipres.treebase.TreebaseUtil; import org.cipres.treebase.TreebaseIDString.MalformedTreebaseIDString; import org.cipres.treebase.domain.search.SearchResults; import org.cipres.treebase.domain.search.SearchResultsType; import org.cipres.treebase.domain.search.StudySearchResults; import org.cipres.treebase.domain.study.Study; import org.cipres.treebase.domain.study.StudyService; -import org.cipres.treebase.domain.taxon.TaxonLabel; -import org.cipres.treebase.domain.taxon.TaxonVariant; import org.cipres.treebase.web.Constants; import org.cipres.treebase.web.util.RequestMessageSetter; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; +import org.z3950.zing.cql.CQLAndNode; +import org.z3950.zing.cql.CQLBooleanNode; +import org.z3950.zing.cql.CQLNode; +import org.z3950.zing.cql.CQLNotNode; +import org.z3950.zing.cql.CQLOrNode; +import org.z3950.zing.cql.CQLParseException; +import org.z3950.zing.cql.CQLParser; +import org.z3950.zing.cql.CQLRelation; +import org.z3950.zing.cql.CQLTermNode; /** * StudySearchController.java @@ -99,13 +108,41 @@ clearMessages(request); String formName = request.getParameter("formName"); + String query = request.getParameter("query"); LOGGER.info("formName is '" + formName + "'"); + if ( ! TreebaseUtil.isEmpty(query) ) { + /* + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<Study> queryResults = doCQLQuery(root, new HashSet<Study>(),request, response, errors); + StudySearchResults tsr = new StudySearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return new ModelAndView("search/studySearch", Constants.RESULT_SET, tsr); + } + else { + return this.searchResultsAsRDF(tsr, request, root); + } + */ + return this.handleQueryRequest(request, response, errors); + } + if (formName.equals("searchKeyword")) { SearchType searchType; String buttonName = request.getParameter("searchButton"); - + String searchTerm = convertStars(request.getParameter("searchTerm")); + StudySearchResults oldRes; + { + SearchResults<?> sr = searchResults(request); + if (sr != null) { + oldRes = (StudySearchResults) sr.convertToStudies(); + } else { + oldRes = new StudySearchResults (); // TODO: Convert existing search results to new type + } + } if (buttonName.equals("authorKeyword")) { searchType = SearchType.byAuthorName; } else if (buttonName.equals("studyID")) { @@ -123,84 +160,171 @@ } else { throw new Error("Unknown search button name '" + buttonName + "'"); } - - return doSearch(request, response, searchType, errors); + Collection<Study> matches = doSearch(request, response, searchType, errors,searchTerm); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + SearchResults<Study> newRes = intersectSearchResults(oldRes, new StudySearchResults(matches), + new RequestMessageSetter(request), "No matching studies found"); + saveSearchResults(request, newRes); + return new ModelAndView("search/studySearch", Constants.RESULT_SET, newRes); + } + else { + return this.searchResultsAsRDF(new StudySearchResults(matches), request, null,"study","study"); + } } else { return super.onSubmit(request, response, command, errors); } } - protected ModelAndView doSearch( + private Set<Study> doCQLQuery( + CQLNode node, + Set<Study> results, + HttpServletRequest request, + HttpServletResponse response, + BindException errors + ) throws InstantiationException { + if ( node instanceof CQLBooleanNode ) { + Set<Study> resultsLeft = doCQLQuery(((CQLBooleanNode)node).left,results, request, response, errors); + Set<Study> resultsRight = doCQLQuery(((CQLBooleanNode)node).right,results, request, response, errors); + if ( node instanceof CQLNotNode ) { + Set<Study> resultsDifference = new HashSet<Study>(); + for ( Study leftStudy : resultsLeft ) { + if ( ! resultsRight.contains(leftStudy) ) + resultsDifference.add(leftStudy); + } + resultsLeft = resultsDifference; + } + else if ( node instanceof CQLOrNode ) { + resultsLeft.addAll(resultsRight); + } + else if ( node instanceof CQLAndNode ) { + Set<Study> resultsUnion = new HashSet<Study>(); + for ( Study leftStudy : resultsLeft ) { + if ( resultsRight.contains(leftStudy) ) + resultsUnion.add(leftStudy); + } + resultsLeft = resultsUnion; + } + results = resultsLeft; + } + else if ( node instanceof CQLTermNode ) { + CQLTermNode term = (CQLTermNode)node; + String index = term.getIndex(); + if ( index.startsWith("tb.title") ) { + results.addAll(doSearch(request, response, SearchType.byTitle, errors, term.getTerm())); + } else if ( index.equals("tb.identifier.study") ) { + results.addAll(doSearch(request, response, SearchType.byID, errors, term.getTerm())); + } else if ( index.startsWith("dcterms.contributor") ) { + results.addAll(doSearch(request, response, SearchType.byAuthorName, errors, term.getTerm())); + } else if ( index.startsWith("dcterms.abstract") ) { + results.addAll(doSearch(request, response, SearchType.inAbstract, errors, term.getTerm())); + } else if ( index.startsWith("dcterms.subject") ) { + results.addAll(doSearch(request, response, SearchType.byKeyword, errors, term.getTerm())); + } else if ( index.startsWith("dcterms.bibliographicCitation") ) { + results.addAll(doSearch(request, response, SearchType.inCitation, errors, term.getTerm())); + } else if ( index.equals("tb.identifier.study.tb1") ) { + results.addAll(doSearch(request, response, SearchType.byLegacyID, errors, term.getTerm())); + } else { + // issue warnings + addMessage(request, "Unsupported index: " + index); + } + } + logger.debug(node); + return results; + } + + private CQLNode normalizeParseTree(CQLNode node) { + if ( node instanceof CQLBooleanNode ) { + ((CQLBooleanNode)node).left = normalizeParseTree(((CQLBooleanNode)node).left); + ((CQLBooleanNode)node).right = normalizeParseTree(((CQLBooleanNode)node).right); + return node; + } + else if ( node instanceof CQLTermNode ) { + String index = ((CQLTermNode)node).getIndex(); + String term = ((CQLTermNode)node).getTerm(); + CQLRelation relation = ((CQLTermNode)node).getRelation(); + index = index.replaceAll("dcterms.title", "tb.title.study"); + index = index.replaceAll("dcterms.identifier", "tb.identifier.study"); + return new CQLTermNode(index,relation,term); + } + logger.debug(node); + return node; + } + + @SuppressWarnings("unchecked") + protected Collection<Study> doSearch( HttpServletRequest request, HttpServletResponse response, SearchType searchType, - BindException errors) throws InstantiationException { + BindException errors, + String searchTerm) throws InstantiationException { - String searchTerm = convertStars(request.getParameter("searchTerm")); +// String searchTerm = convertStars(request.getParameter("searchTerm")); String keywordSearchTerm = "%" + searchTerm + "%"; - StudySearchResults oldRes; - - { - SearchResults<?> sr = searchResults(request); - if (sr != null) { - oldRes = (StudySearchResults) sr.convertToStudies(); - } else { - oldRes = new StudySearchResults (); // TODO: Convert existing search results to new type - } - } - - LOGGER.info("doSearch old results contained " + oldRes.size() + " item(s)"); +// StudySearchResults oldRes; +// +// { +// SearchResults<?> sr = searchResults(request); +// if (sr != null) { +// oldRes = (StudySearchResults) sr.convertToStudies(); +// } else { +// oldRes = new StudySearchResults (); // TODO: Convert existing search results to new type +// } +// } +// +// LOGGER.info("doSearch old results contained " + oldRes.size() + " item(s)"); Collection<Study> matches; StudyService studyService = getSearchService().getStudyService(); switch (searchType) { - case byID: - matches = (Collection<Study>) doSearchByIDString(request, studyService, Study.class, searchTerm); - break; - case byLegacyID: - { - TreebaseIDString legacyID = null; - boolean malformed = false; - try { - legacyID = new TreebaseIDString(searchTerm, Study.class); - } catch (MalformedTreebaseIDString e) { - malformed = true; + case byID: + matches = (Collection<Study>) doSearchByIDString(request, studyService, Study.class, searchTerm); + break; + case byLegacyID: + { + TreebaseIDString legacyID = null; + boolean malformed = false; + try { + legacyID = new TreebaseIDString(searchTerm, Study.class); + } catch (MalformedTreebaseIDString e) { + malformed = true; + } + if (malformed || legacyID.getTBClass() != Study.class) { + addMessage(request, "Legacy ID number '" + searchTerm + "' is not valid; try S#### or just ####"); + matches = null; + break; + } + matches = (Collection<Study>) studyService.findByTBStudyID("S" + legacyID.getId().toString()); + break; } - if (malformed || legacyID.getTBClass() != Study.class) { - addMessage(request, "Legacy ID number '" + searchTerm + "' is not valid; try S#### or just ####"); - matches = null; + case inAbstract: + matches = studyService.findByAbstract(keywordSearchTerm); break; - } - matches = (Collection<Study>) studyService.findByTBStudyID("S" + legacyID.getId().toString()); - break; + case inCitation: + matches = studyService.findByCitation(keywordSearchTerm); + break; + case byAuthorName: + matches = studyService.findByAuthor(searchTerm); + break; + case byTitle: + matches = studyService.findByTitle(keywordSearchTerm); + break; + case byKeyword: + matches = studyService.findByKeyword(keywordSearchTerm); + break; + default: + throw new Error ("Unknown search type '" + searchType + "'"); } - case inAbstract: - matches = studyService.findByAbstract(keywordSearchTerm); - break; - case inCitation: - matches = studyService.findByCitation(keywordSearchTerm); - break; - case byAuthorName: - matches = studyService.findByAuthor(searchTerm); - break; - case byTitle: - matches = studyService.findByTitle(keywordSearchTerm); - break; - case byKeyword: - matches = studyService.findByKeyword(keywordSearchTerm); - break; - default: - throw new Error ("Unknown search type '" + searchType + "'"); - } - SearchResults<Study> newRes = intersectSearchResults(oldRes, new StudySearchResults(matches), - new RequestMessageSetter(request), "No matching studies found"); - - saveSearchResults(request, newRes); - - return new ModelAndView("search/studySearch", Constants.RESULT_SET, newRes); + return matches; +// SearchResults<Study> newRes = intersectSearchResults(oldRes, new StudySearchResults(matches), +// new RequestMessageSetter(request), "No matching studies found"); +// +// saveSearchResults(request, newRes); +// +// return new ModelAndView("search/studySearch", Constants.RESULT_SET, newRes); } + /* private void validateTaxonSet(HttpServletRequest request, HttpServletResponse response, String searchTerm, BindException errors) { @@ -256,6 +380,7 @@ private String titleCase(String s) { return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); } + */ @Override SearchResultsType currentSearchType() { @@ -266,4 +391,38 @@ public String getDefaultViewURL() { return "studySearch.html"; } + + @Override + protected ModelAndView handleQueryRequest(HttpServletRequest request, + HttpServletResponse response, BindException errors) + throws CQLParseException, IOException, InstantiationException { + String query = request.getParameter("query"); + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<Study> queryResults = doCQLQuery(root, new HashSet<Study>(),request, response, errors); + StudySearchResults tsr = new StudySearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return new ModelAndView("search/studySearch", Constants.RESULT_SET, tsr); + } + else { + SearchResults<?> res = tsr; + String schema = null; + if ( ! TreebaseUtil.isEmpty(request.getParameter("recordSchema")) ) { + schema = request.getParameter("recordSchema"); + if ( schema.equals("tree") ) { + res = tsr.convertToTrees(); + } + else if ( schema.equals("matrix") ) { + res = tsr.convertToMatrices(); + } + else if ( schema.equals("taxon") ) { + res = tsr.convertToTaxa(); + } + } + this.saveSearchResults(request, res); + return this.searchResultsAsRDF(res, request, root, schema, "study"); + } + } } Modified: trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TaxonSearchController.java =================================================================== --- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TaxonSearchController.java 2009-07-02 10:41:25 UTC (rev 158) +++ trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TaxonSearchController.java 2009-07-02 10:43:46 UTC (rev 159) @@ -1,17 +1,20 @@ package org.cipres.treebase.web.controllers; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.cipres.treebase.TreebaseIDString; +import org.cipres.treebase.TreebaseUtil; import org.cipres.treebase.TreebaseIDString.MalformedTreebaseIDString; +import org.cipres.treebase.domain.search.MatrixSearchResults; +import org.cipres.treebase.domain.search.SearchResults; import org.cipres.treebase.domain.search.SearchResultsType; import org.cipres.treebase.domain.search.SearchService; import org.cipres.treebase.domain.search.TaxonSearchResults; @@ -19,16 +22,29 @@ import org.cipres.treebase.domain.taxon.TaxonHome; import org.cipres.treebase.domain.taxon.TaxonLabel; import org.cipres.treebase.domain.taxon.TaxonLabelHome; +import org.cipres.treebase.domain.taxon.TaxonLabelService; import org.cipres.treebase.domain.taxon.TaxonVariant; import org.cipres.treebase.web.model.SearchCommand; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; +import org.z3950.zing.cql.CQLAndNode; +import org.z3950.zing.cql.CQLBooleanNode; +import org.z3950.zing.cql.CQLNode; +import org.z3950.zing.cql.CQLNotNode; +import org.z3950.zing.cql.CQLOrNode; +import org.z3950.zing.cql.CQLParseException; +import org.z3950.zing.cql.CQLParser; +import org.z3950.zing.cql.CQLRelation; +import org.z3950.zing.cql.CQLTermNode; public class TaxonSearchController extends SearchController { - static final Logger LOGGER = Logger.getLogger(TreeSearchController.class); + static final Logger LOGGER = Logger.getLogger(TaxonSearchController.class); private TaxonHome mTaxonHome; private TaxonLabelHome mTaxonLabelHome; + private enum SearchIndex { LABEL, ID }; + private enum SearchTable { TAXON, TAXONLABEL, TAXONVARIANT }; + private enum NamingAuthority { TREEBASE, UBIO, NCBI }; @Override protected ModelAndView onSubmit(HttpServletRequest request, @@ -36,10 +52,56 @@ throws Exception { clearMessages(request); String formName = request.getParameter("formName"); + String query = request.getParameter("query"); + if ( ! TreebaseUtil.isEmpty(query) ) { + /* + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<Taxon> queryResults = doCQLQuery(root, new HashSet<Taxon>(),request); + TaxonSearchResults tsr = new TaxonSearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return samePage(request); + } + else { + return this.searchResultsAsRDF(tsr, request, root); + } + */ + return this.handleQueryRequest(request, response, errors); + } if (formName.equals("searchByTaxonLabel")) { SearchCommand newSearchCommand = (SearchCommand)searchCommand; - ModelAndView modelAndView = doTaxonSearch(request, response, newSearchCommand, errors); - return modelAndView; + String searchOn = request.getParameter("searchOn"); + String searchTerm = convertStars(request.getParameter("searchTerm")); + String[] searchTerms = searchTerm.split("\\r\\n"); + Collection<Taxon> taxa = new HashSet<Taxon>(); + for ( int i = 0; i < searchTerms.length; i++ ) { + if ( searchOn.equals("TextSearch") ) { + taxa.addAll(doTaxonSearch(request, newSearchCommand, searchTerms[i], SearchIndex.LABEL, null)); + } + else if ( searchOn.equals("Identifiers") ) { + String objectIdentifier = request.getParameter("objectIdentifier"); + if ( objectIdentifier.equals("TreeBASE") ) { + taxa.addAll(doTaxonSearch(request,newSearchCommand,searchTerms[i],SearchIndex.ID,NamingAuthority.TREEBASE)); + } + else if ( objectIdentifier.equals("NCBI") ) { + taxa.addAll(doTaxonSearch(request,newSearchCommand,searchTerms[i],SearchIndex.ID,NamingAuthority.NCBI)); + } + else if ( objectIdentifier.equals("uBio") ) { + taxa.addAll(doTaxonSearch(request,newSearchCommand,searchTerms[i],SearchIndex.ID,NamingAuthority.UBIO)); + } + } + } + TaxonSearchResults tsr = new TaxonSearchResults(taxa); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return samePage(request); + } + else { + return this.searchResultsAsRDF(tsr, request, null,"taxon","taxon"); + } + } else if (formName.equals("taxonResultsAction")) { return modifySearchResults(request, response, errors); } else { @@ -47,13 +109,99 @@ } } + private CQLNode normalizeParseTree(CQLNode node) { + if ( node instanceof CQLBooleanNode ) { + ((CQLBooleanNode)node).left = normalizeParseTree(((CQLBooleanNode)node).left); + ((CQLBooleanNode)node).right = normalizeParseTree(((CQLBooleanNode)node).right); + return node; + } + else if ( node instanceof CQLTermNode ) { + String index = ((CQLTermNode)node).getIndex(); + String term = ((CQLTermNode)node).getTerm(); + CQLRelation relation = ((CQLTermNode)node).getRelation(); + index = index.replaceAll("dcterms.title", "tb.title.taxon"); + index = index.replaceAll("dcterms.identifier", "tb.identifier.taxon"); + return new CQLTermNode(index,relation,term); + } + logger.debug(node); + return node; + } + + private Set<Taxon> doCQLQuery(CQLNode node, Set<Taxon> results, HttpServletRequest request) { + if ( node instanceof CQLBooleanNode ) { + Set<Taxon> resultsLeft = doCQLQuery(((CQLBooleanNode)node).left,results, request); + Set<Taxon> resultsRight = doCQLQuery(((CQLBooleanNode)node).right,results, request); + if ( node instanceof CQLNotNode ) { + for ( Taxon rightTaxon : resultsRight ) { + if ( resultsLeft.contains(rightTaxon) ) { + resultsLeft.remove(rightTaxon); + } + } + } + else if ( node instanceof CQLOrNode ) { + resultsLeft.addAll(resultsRight); + } + else if ( node instanceof CQLAndNode ) { + Set<Taxon> resultsUnion = new HashSet<Taxon>(); + for ( Taxon leftTaxon : resultsLeft ) { + if ( resultsRight.contains(leftTaxon) ) { + resultsUnion.add(leftTaxon); + } + } + resultsLeft = resultsUnion; + } + results = resultsLeft; + } + else if ( node instanceof CQLTermNode ) { + CQLTermNode term = (CQLTermNode)node; + String index = term.getIndex(); + if ( index.startsWith("tb.title") ) { + boolean exactMatch = term.getRelation().getBase().equals("=="); + SearchTable searchTable = null; + if ( index.endsWith("taxonLabel") ) { + searchTable = SearchTable.TAXONLABEL; + } + else if ( index.endsWith("taxonVariant") ) { + searchTable = SearchTable.TAXONVARIANT; + } + else if ( index.endsWith("taxon") ) { + searchTable = SearchTable.TAXON; + } + boolean caseSensitive = true; + if ( ! term.getRelation().getModifiers().isEmpty() ) { + caseSensitive = ! term.getRelation().getModifiers().firstElement().getType().equalsIgnoreCase("ignoreCase"); + } + results.addAll(doTextSearch(term.getTerm(), caseSensitive, exactMatch, searchTable)); + } + else if ( index.startsWith("tb.identifier") ) { + NamingAuthority namingAuthority = null; + if ( index.endsWith("ncbi") ) { + namingAuthority = NamingAuthority.NCBI; + } + else if ( index.endsWith("ubio") ) { + namingAuthority = NamingAuthority.UBIO; + } + else { + namingAuthority = NamingAuthority.TREEBASE; + } + results.addAll(doIdentifierSearch(request, term.getTerm(), namingAuthority)); + } else { + // issue warnings + addMessage(request, "Unsupported index: " + index); + } + + } + logger.debug(node); + return results; + } + private ModelAndView modifySearchResults(HttpServletRequest request, HttpServletResponse response, BindException errors) throws InstantiationException { TaxonSearchResults results = searchResults(request).convertToTaxa(); String buttonName = request.getParameter("taxonResultsaction"); if (buttonName.equals("addCheckedToResults")) { - Map<String,String> parameterMap = request.getParameterMap(); +// Map<String,String> parameterMap = request.getParameterMap(); Collection<Taxon> newTaxa = new HashSet<Taxon> (); for (String taxonIdString : request.getParameterValues("selection")) { Taxon tx; @@ -72,36 +220,40 @@ return samePage(request); } - protected ModelAndView doTaxonSearch(HttpServletRequest request, - HttpServletResponse response, - SearchCommand searchCommand, BindException errors) throws Exception { - String searchTerm = convertStars(request.getParameter("searchTerm")); - String[] searchTerms = searchTerm.split("\\r\\n"); - String searchOn = request.getParameter("searchOn"); - //Collection<TaxonVariant> tvs = new ArrayList<TaxonVariant>(); + protected Collection<Taxon> doTaxonSearch(HttpServletRequest request, + SearchCommand searchCommand, String searchTerm, SearchIndex searchIndex, NamingAuthority namingAuthority) throws Exception { + Collection<Taxon> taxa = new HashSet<Taxon> (); - if ( searchOn.equals("TextSearch") ) { - taxa = doTextSearch(request,searchTerms); + switch(searchIndex) { + case LABEL: + String[] stringModifiers = request.getParameterValues("stringModifier"); + boolean caseSensitive = false; + boolean exactMatch = false; + if ( stringModifiers != null ) { + for ( int i = 0; i < stringModifiers.length; i++ ) { + if ( stringModifiers[i].equals("caseSensitive") ) { + caseSensitive = true; + } + if ( stringModifiers[i].equals("exactMatch") ) { + exactMatch = true; + } + } + } + for ( SearchTable searchTable : createSearchTableEnum(request) ) { + taxa.addAll(doTextSearch(searchTerm, caseSensitive, exactMatch, searchTable)); + } + break; + case ID: + taxa.addAll(doIdentifierSearch(request,searchTerm, namingAuthority)); + break; } - else if ( searchOn.equals("Identifiers") ) { - taxa = doIdentifierSearch(request,searchTerms); - } - /* - tvs = getTaxonLabelService().findTaxonVariantByFullName(searchTerm); - LOGGER.debug("Found " + tvs.size() + " tvs"); - for (TaxonVariant tv : tvs) { - if (tv.getTaxon() != null) taxa.add(tv.getTaxon()); - } - */ - getTaxonLabelService().resurrectAll(taxa); LOGGER.debug("Found " + taxa.size() + " taxa"); - - TaxonSearchResults tsr = new TaxonSearchResults(taxa); - //saveTempSearchResults(request, tsr); - saveSearchResults(request, tsr); - return samePage(request); + return taxa; +// TaxonSearchResults tsr = new TaxonSearchResults(taxa); +// saveSearchResults(request, tsr); +// return samePage(request); } /** @@ -110,44 +262,60 @@ * @param request * @param results */ - private Collection<Taxon> doIdentifierSearch(HttpServletRequest request,String[] identifiers) { - String objectIdentifier = request.getParameter("objectIdentifier"); + private Collection<Taxon> doIdentifierSearch(HttpServletRequest request, String identifier, NamingAuthority namingAuthority) { Collection<Taxon> taxaFound = new ArrayList<Taxon>(); - if ( objectIdentifier.equals("TreeBASE") ) { - LOGGER.debug("Going to search for TreeBASE IDs"); - for ( int i = 0; i < identifiers.length; i++ ) { + switch(namingAuthority) { + case TREEBASE : + LOGGER.debug("Going to search for TreeBASE IDs"); TreebaseIDString idstr; try { - idstr = new TreebaseIDString(identifiers[i], Taxon.class, true); + idstr = new TreebaseIDString(identifier, Taxon.class, true); + Taxon match = getTaxonHome().findPersistedObjectByID(idstr.getTBClass(), idstr.getId()); + if ( match != null ) { + taxaFound.add(match); + } } catch (MalformedTreebaseIDString e) { - addMessage(request, "Ignoring malformed taxon ID string '" + identifiers[i] + "'; try 'Tx####' or just a number"); - continue; + addMessage(request, "Ignoring malformed taxon ID string '" + identifier + "'; try 'Tx####' or just a number"); } - Taxon match = getTaxonHome().findPersistedObjectByID(idstr.getTBClass(), idstr.getId()); + break; + case NCBI : + LOGGER.debug("Going to search for NCBI taxon ids"); + Taxon match = getTaxonHome().findByNcbiTaxId(Integer.parseInt(identifier)); if ( match != null ) { taxaFound.add(match); } - } + break; + case UBIO : + LOGGER.debug("Going to search for uBio nameBankIDs"); + Taxon match1 = getTaxonHome().findByUBIOTaxId(Long.parseLong(identifier)); + if ( match1 != null ) { + taxaFound.add(match1); + } + break; } - else if ( objectIdentifier.equals("NCBI") ) { - LOGGER.debug("Going to search for NCBI taxon ids"); - for ( int i = 0; i < identifiers.length; i++ ) { - Taxon match = getTaxonHome().findByNcbiTaxId(Integer.parseInt(identifiers[i])); - if ( match != null ) { - taxaFound.add(match); - } + return taxaFound; + } + + /** + * + * @param request + * @return + */ + private Set<SearchTable> createSearchTableEnum(HttpServletRequest request) { + Set<SearchTable> results = new HashSet<SearchTable>(); + String[] stringProperties = request.getParameterValues("stringProperty"); + for ( int i = 0; i < stringProperties.length; i++ ) { + if ( stringProperties[i].equals("taxonLabel") ) { + results.add(SearchTable.TAXONLABEL); } - } - else if ( objectIdentifier.equals("uBio") ) { - LOGGER.debug("Going to search for uBio nameBankIDs"); - for ( int i = 0; i < identifiers.length; i++ ) { - Taxon match = getTaxonHome().findByUBIOTaxId(Long.parseLong(identifiers[i])); - if ( match != null ) { - taxaFound.add(match); - } + else if ( stringProperties[i].equals("taxonVariant") ) { + results.add(SearchTable.TAXONVARIANT); + } + else if ( stringProperties[i].equals("taxon") ) { + results.add(SearchTable.TAXON); } } - return taxaFound; + return results; } /** @@ -156,88 +324,50 @@ * @param request * @param results */ - private Collection<Taxon> doTextSearch(HttpServletRequest request, String[] stringPatterns) { + private Collection<Taxon> doTextSearch(String pattern, boolean caseSensitive, boolean exactMatch, SearchTable searchTable) { LOGGER.debug("Going to search for strings"); + LOGGER.debug("Case sensitive? " + caseSensitive); + LOGGER.debug("Exact match? " + exactMatch); + TaxonLabelService tls = getTaxonLabelService(); Collection<Taxon> taxaFound = new ArrayList<Taxon>(); - String[] stringProperties = request.getParameterValues("stringProperty"); - String[] stringModifiers = request.getParameterValues("stringModifier"); - boolean caseSensitive = false; - boolean exactMatch = false; - if ( stringModifiers != null ) { - for ( int i = 0; i < stringModifiers.length; i++ ) { - if ( stringModifiers[i].equals("caseSensitive") ) { - caseSensitive = true; + switch(searchTable) { + case TAXONLABEL : + LOGGER.debug("Will search taxon labels"); + Collection<TaxonLabel> labelsFound = exactMatch + ? tls.findByExactString(pattern) + : tls.findBySubstring(pattern, caseSensitive); + for ( TaxonLabel label : labelsFound ) { + if ( label.getTaxonVariant() != null && label.getTaxonVariant().getTaxon() != null ) { + taxaFound.add(label.getTaxonVariant().getTaxon()); + } } - if ( stringModifiers[i].equals("exactMatch") ) { - exactMatch = true; - } - } - } - LOGGER.debug("Case sensitive? " + caseSensitive); - LOGGER.debug("Exact match? " + exactMatch); - if ( stringProperties != null ) { - for ( int i = 0; i < stringProperties.length; i++ ) { - for ( int j = 0; j < stringPatterns.length; j++ ) { - if ( stringProperties[i].equals("taxonLabel") ) { - LOGGER.debug("Will search taxon labels"); - Collection<TaxonLabel> labelsFound = new ArrayList<TaxonLabel>(); - if ( exactMatch ) { - labelsFound = getTaxonLabelService().findByExactString(stringPatterns[j]); - } - else { - labelsFound = getTaxonLabelService().findBySubstring(stringPatterns[j], caseSensitive); - } - Iterator<TaxonLabel> labelsIterator = labelsFound.iterator(); - while ( labelsIterator.hasNext() ) { - TaxonLabel label = labelsIterator.next(); - TaxonVariant variant = label.getTaxonVariant(); - if ( variant != null ) { - Taxon taxon = variant.getTaxon(); - if ( taxon != null ) { - taxaFound.add(taxon); - } - } - } + break; + case TAXONVARIANT : + LOGGER.debug("Will search taxon variants"); + Collection<TaxonVariant> variantsFound = exactMatch + ? tls.findTaxonVariantByFullName(pattern) + : tls.findTaxonVariantWithSubstring(pattern, caseSensitive); + for ( TaxonVariant variant : variantsFound ) { + if ( variant.getTaxon() != null ) { + taxaFound.add(variant.getTaxon()); } - if ( stringProperties[i].equals("taxonVariant") ) { - LOGGER.debug("Will search taxon variants"); - Collection<TaxonVariant> variantsFound = new ArrayList<TaxonVariant>(); - if ( exactMatch ) { - variantsFound = getTaxonLabelService().findTaxonVariantByFullName(stringPatterns[j]); - } - else { - variantsFound = getTaxonLabelService().findTaxonVariantWithSubstring(stringPatterns[j], caseSensitive); - } - Iterator<TaxonVariant> variantsIterator = variantsFound.iterator(); - while ( variantsIterator.hasNext() ) { - TaxonVariant variant = variantsIterator.next(); - Taxon taxon = variant.getTaxon(); - if ( taxon != null ) { - taxaFound.add(taxon); - } - } - } - if ( stringProperties[i].equals("taxon") ) { - LOGGER.debug("Will search taxa"); - Collection<Taxon> tmpTaxaFound = new ArrayList<Taxon>(); - if ( exactMatch ) { - tmpTaxaFound = getTaxonLabelService().findTaxaByName(stringPatterns[j]); - } - else { - tmpTaxaFound = getTaxonLabelService().findTaxaBySubstring(stringPatterns[j], caseSensitive); - } - taxaFound.addAll(tmpTaxaFound); - } } - } + break; + case TAXON : + LOGGER.debug("Will search taxa"); + Collection<Taxon> tmpTaxaFound = exactMatch + ? tls.findTaxaByName(pattern) + : tls.findTaxaBySubstring(pattern, caseSensitive); + taxaFound.addAll(tmpTaxaFound); + break; } return taxaFound; } - private void saveTempSearchResults(HttpServletRequest request, - TaxonSearchResults taxonSearchResults) { - request.getSession().setAttribute("taxonSearchResults", taxonSearchResults); - } +// private void saveTempSearchResults(HttpServletRequest request, +// TaxonSearchResults taxonSearchResults) { +// request.getSession().setAttribute("taxonSearchResults", taxonSearchResults); +// } public void setSearchService(SearchService searchService) { this.searchService = searchService; @@ -268,4 +398,38 @@ public void setTaxonLabelHome(TaxonLabelHome taxonLabelHome) { mTaxonLabelHome = taxonLabelHome; } + + @Override + protected ModelAndView handleQueryRequest(HttpServletRequest request, + HttpServletResponse response, BindException errors) + throws CQLParseException, IOException, InstantiationException { + String query = request.getParameter("query"); + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<Taxon> queryResults = doCQLQuery(root, new HashSet<Taxon>(),request); + TaxonSearchResults tsr = new TaxonSearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return samePage(request); + } + else { + SearchResults<?> res = tsr; + String schema = null; + if ( ! TreebaseUtil.isEmpty(request.getParameter("recordSchema")) ) { + schema = request.getParameter("recordSchema"); + if ( schema.equals("tree" ) ) { + res = tsr.convertToTrees(); + } + else if ( schema.equals("matrix") ) { + res = tsr.convertToMatrices(); + } + else if ( schema.equals("study") ) { + res = tsr.convertToStudies(); + } + } + this.saveSearchResults(request, res); + return this.searchResultsAsRDF(res, request, root,schema,"taxon"); + } + } } Modified: trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TreeSearchController.java =================================================================== --- trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TreeSearchController.java 2009-07-02 10:41:25 UTC (rev 158) +++ trunk/treebase-web/src/main/java/org/cipres/treebase/web/controllers/TreeSearchController.java 2009-07-02 10:43:46 UTC (rev 159) @@ -20,25 +20,35 @@ package org.cipres.treebase.web.controllers; -import java.util.ArrayList; +import java.io.IOException; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.cipres.treebase.TreebaseUtil; import org.cipres.treebase.RangeExpression.MalformedRangeExpression; import org.cipres.treebase.domain.search.SearchResults; import org.cipres.treebase.domain.search.SearchResultsType; -import org.cipres.treebase.domain.search.StudySearchResults; import org.cipres.treebase.domain.search.TreeSearchResults; -import org.cipres.treebase.domain.study.Study; import org.cipres.treebase.domain.tree.PhyloTree; import org.cipres.treebase.domain.tree.PhyloTreeService; import org.cipres.treebase.web.Constants; import org.cipres.treebase.web.util.RequestMessageSetter; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; +import org.z3950.zing.cql.CQLAndNode; +import org.z3950.zing.cql.CQLBooleanNode; +import org.z3950.zing.cql.CQLNode; +import org.z3950.zing.cql.CQLNotNode; +import org.z3950.zing.cql.CQLOrNode; +import org.z3950.zing.cql.CQLParseException; +import org.z3950.zing.cql.CQLParser; +import org.z3950.zing.cql.CQLRelation; +import org.z3950.zing.cql.CQLTermNode; /** * TreeSearchController.java @@ -73,50 +83,161 @@ clearMessages(request); String formName = request.getParameter("formName"); + String query = request.getParameter("query"); LOGGER.info("formName is '" + formName + "'"); - + if ( ! TreebaseUtil.isEmpty(query) ) { + /* + CQLParser parser = new CQLParser(); + CQLNode root = parser.parse(query); + root = normalizeParseTree(root); + Set<PhyloTree> queryResults = doCQLQuery(root, new HashSet<PhyloTree>(),request, response, errors); + TreeSearchResults tsr = new TreeSearchResults(queryResults); + saveSearchResults(request, tsr); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return new ModelAndView("search/treeSearch", Constants.RESULT_SET, tsr); + } + else { + return this.searchResultsAsRDF(tsr, request, root); + } + */ + return this.handleQueryRequest(request, response, errors); + } + if (formName.equals("treeSimple")) { String buttonName = request.getParameter("searchButton"); - + String searchTerm = convertStars(request.getParameter("searchTerm")); + Collection<PhyloTree> matches = null; + TreeSearchResults oldRes; + { + SearchResults<?> sr = searchResults(request); + if (sr != null) { + oldRes = (TreeSearchResults) sr.convertToTrees(); + } else { + oldRes = new TreeSearchResults (); // TODO: Convert existing search results to new type + } + } if (buttonName.equals("treeID")) { - return doSearch(request, response, SearchType.byID, errors); + matches = doSearch(request, response, SearchType.byID, errors, searchTerm); } else if (buttonName.equals("treeTitle")) { - return doSearch(request, response, SearchType.byTitle, errors); + matches = doSearch(request, response, SearchType.byTitle, errors, searchTerm); } else if (buttonName.equals("treeType")) { - return doSearch(request, response, SearchType.byType, errors); + matches = doSearch(request, response, SearchType.byType, errors, searchTerm); } else if (buttonName.equals("treeKind")) { - return doSearch(request, response, SearchType.byKind, errors); + matches = doSearch(request, response, SearchType.byKind, errors, searchTerm); } else if (buttonName.equals("treeQuality")) { - return doSearch(request, response, SearchType.byQuality, errors); + matches = doSearch(request, response, SearchType.byQuality, errors, searchTerm); } else if (buttonName.equals("treeNTAX")) { - return doSearch(request, response, SearchType.byNTAX, errors); + matches = doSearch(request, response, SearchType.byNTAX, errors, searchTerm); } else { throw new Error("Unknown search button name '" + buttonName + "'"); } + SearchResults<PhyloTree> newRes = intersectSearchResults(oldRes, new TreeSearchResults(matches), + new RequestMessageSetter(request), "No matching trees found"); + saveSearchResults(request, newRes); + if ( TreebaseUtil.isEmpty(request.getParameter("format")) || ! request.getParameter("format").equals("rss1") ) { + return new ModelAndView("search/treeSearch", Constants.RESULT_SET, newRes); + } + else { + return this.searchResultsAsRDF(newRes, request, null,"tree","tree"); + } } else { return super.onSubmit(request, response, command, errors); } } - private ModelAndView doSearch( + private Set<PhyloTree> doCQLQuery( + CQLNode node, + Set<PhyloTree> results, + HttpServletRequest request, + HttpServletResponse response, + BindException errors + ) throws InstantiationException { + if ( node instanceof CQLBooleanNode ) { + Set<PhyloTree> resultsLeft = doCQLQuery(((CQLBooleanNode)node).left,results, request, response, erro... [truncated message content] |