]> source.dussan.org Git - archiva.git/commitdiff
[MRM-864]
authorMaria Odea B. Ching <oching@apache.org>
Wed, 16 Jul 2008 08:46:38 +0000 (08:46 +0000)
committerMaria Odea B. Ching <oching@apache.org>
Wed, 16 Jul 2008 08:46:38 +0000 (08:46 +0000)
-use a lucene Filter with BooleanQuery and the LuceneQuery for searching within the search results
-added a checkbox in the general search page to search from the results only
-maintain a list of previous query strings if searchResultsOnly option is enabled in general search

git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@677197 13f79535-47bb-0310-9956-ffa450edef68

archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/CrossRepositorySearch.java
archiva-modules/archiva-base/archiva-indexer/src/main/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearch.java
archiva-modules/archiva-base/archiva-indexer/src/test/java/org/apache/maven/archiva/indexer/search/DefaultCrossRepositorySearchTest.java
archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/SearchAction.java
archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/include/quickSearchForm.jspf
archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/results.jsp

index 73c8cf61ab574136558655de7d6810ded1f69944..63e21151c004b4246d0590aa6f5d269adb302ac6 100644 (file)
@@ -39,6 +39,19 @@ public interface CrossRepositorySearch
      */
     public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term, SearchResultLimits limits );
     
+    /**
+     * Search for a specific term from the previous search results.
+     * 
+     * @param principal the user doing the search.
+     * @param selectedRepos the repositories to search from.
+     * @param term the term to search for.
+     * @param limits the limits to apply to the search results.
+     * @param previousSearchTerms the list of the previous search terms.
+     * @return the results
+     */
+    public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term,
+                                        SearchResultLimits limits, List<String> previousSearchTerms );
+    
     /**
      * Search for the specific bytecode across all repositories.
      * 
index a2c813a19e209ffd67478d26d31f865952a08f4d..8565acc46490f90c865736767dc5dd5cc7ecbd6c 100644 (file)
@@ -27,8 +27,12 @@ import org.apache.lucene.document.Document;
 import org.apache.lucene.queryParser.MultiFieldQueryParser;
 import org.apache.lucene.queryParser.ParseException;
 import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.Hits;
 import org.apache.lucene.search.MultiSearcher;
+import org.apache.lucene.search.QueryWrapperFilter;
 import org.apache.lucene.search.Searchable;
 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
 import org.apache.maven.archiva.configuration.ConfigurationNames;
@@ -84,7 +88,7 @@ public class DefaultCrossRepositorySearch
             QueryParser parser = new MultiFieldQueryParser( new String[]{HashcodesKeys.MD5, HashcodesKeys.SHA1},
                                                             new HashcodesHandlers().getAnalyzer() );
             LuceneQuery query = new LuceneQuery( parser.parse( checksum ) );
-            SearchResults results = searchAll( query, limits, indexes );
+            SearchResults results = searchAll( query, limits, indexes, null );
             results.getRepositories().addAll( this.localIndexedRepositories );
 
             return results;
@@ -106,7 +110,7 @@ public class DefaultCrossRepositorySearch
         {
             QueryParser parser = new BytecodeHandlers().getQueryParser();
             LuceneQuery query = new LuceneQuery( parser.parse( term ) );
-            SearchResults results = searchAll( query, limits, indexes );
+            SearchResults results = searchAll( query, limits, indexes, null );
             results.getRepositories().addAll( this.localIndexedRepositories );
 
             return results;
@@ -120,7 +124,14 @@ public class DefaultCrossRepositorySearch
         return new SearchResults();
     }
 
+    
     public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term, SearchResultLimits limits )
+    {
+        return searchForTerm( principal, selectedRepos, term, limits, null );        
+    }
+    
+    public SearchResults searchForTerm( String principal, List<String> selectedRepos, String term,
+                                        SearchResultLimits limits, List<String> previousSearchTerms )
     {
         List<RepositoryContentIndex> indexes = getFileContentIndexes( principal, selectedRepos );
         List<RepositoryContentIndex> bytecodeIndices = getBytecodeIndexes( principal, selectedRepos );        
@@ -129,8 +140,26 @@ public class DefaultCrossRepositorySearch
         try
         {
             QueryParser parser = new FileContentHandlers().getQueryParser();
-            LuceneQuery query = new LuceneQuery( parser.parse( term ) );
-            SearchResults results = searchAll( query, limits, indexes );
+            LuceneQuery query = null;
+            SearchResults results = null;
+            if( previousSearchTerms == null || previousSearchTerms.isEmpty() )
+            {
+                query = new LuceneQuery( parser.parse( term ) );
+                results = searchAll( query, limits, indexes, null );
+            }
+            else
+            {
+                // AND the previous search terms
+                BooleanQuery booleanQuery = new BooleanQuery();
+                for( String previousSearchTerm : previousSearchTerms )
+                {
+                    booleanQuery.add( parser.parse( previousSearchTerm ), BooleanClause.Occur.MUST );
+                }
+                
+                query = new LuceneQuery( booleanQuery );                
+                Filter filter = new QueryWrapperFilter( parser.parse( term ) );
+                results = searchAll( query, limits, indexes, filter );
+            }            
             results.getRepositories().addAll( this.localIndexedRepositories );
             
             return results;
@@ -141,10 +170,10 @@ public class DefaultCrossRepositorySearch
         }
 
         // empty results.
-        return new SearchResults();
+        return new SearchResults(); 
     }
-
-    private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List<RepositoryContentIndex> indexes )
+    
+    private SearchResults searchAll( LuceneQuery luceneQuery, SearchResultLimits limits, List<RepositoryContentIndex> indexes, Filter filter )
     {
         org.apache.lucene.search.Query specificQuery = luceneQuery.getLuceneQuery();
 
@@ -175,7 +204,15 @@ public class DefaultCrossRepositorySearch
             searcher = new MultiSearcher( searchables );
 
             // Perform the search.
-            Hits hits = searcher.search( specificQuery );
+            Hits hits = null;
+            if( filter != null )
+            {
+                hits = searcher.search( specificQuery, filter );
+            }
+            else
+            {
+                hits = searcher.search( specificQuery );
+            }
 
             int hitCount = hits.length();
 
index a503d6f8b9d39a8cfe7ebaca15e64694e56a1145..576b54481268501e02d0f16fa539758bc5ef4e26 100644 (file)
@@ -140,7 +140,7 @@ public class DefaultCrossRepositorySearchTest
             "org","org2","org3","org4","org5","org6","org7"
         };
         
-        assertSearchResults( expectedRepos, expectedResults, search, "org" );
+        assertSearchResults( expectedRepos, expectedResults, search, "org", null );
     }
 
     public void testSearchTerm_Junit()
@@ -156,7 +156,7 @@ public class DefaultCrossRepositorySearchTest
             "junit","junit2","junit3"
         };
         
-        assertSearchResults( expectedRepos, expectedResults, search, "junit" );
+        assertSearchResults( expectedRepos, expectedResults, search, "junit", null );
     }
 
     public void testSearchInvalidTerm()
@@ -172,10 +172,49 @@ public class DefaultCrossRepositorySearchTest
             // Nothing.
         };
         
-        assertSearchResults( expectedRepos, expectedResults, search, "monosodium" );
+        assertSearchResults( expectedRepos, expectedResults, search, "monosodium", null );
     }
     
-    private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search, String term )
+    public void testSearchWithinSearchResults()
+        throws Exception
+    {
+        CrossRepositorySearch search = lookupCrossRepositorySearch();
+
+        String expectedRepos[] = new String[] {
+            TEST_DEFAULT_REPO_ID
+        };
+        
+        String expectedResults[] = new String[] { 
+            "org","org2","org3","org4","org5","org6","org7"
+        };
+        
+        // first search
+        assertSearchResults( expectedRepos, expectedResults, search, "org", null );
+        
+        List<String> previousSearchTerms = new ArrayList<String>();
+        previousSearchTerms.add( "org" );        
+        String secondSearchExpectedResults[] = new String[] { 
+            "org.apache.maven.archiva.record", "org.apache.maven.archiva.record2",
+                "org.apache.maven.archiva.record3", "org.apache.maven.archiva.record4",
+                "org.apache.maven.archiva.record5", "org.apache.maven.archiva.record6",
+                "org.apache.maven.archiva.record7"
+        };
+        
+        //second search
+        assertSearchResults( expectedRepos, secondSearchExpectedResults, search, "org.apache.maven.archiva.record",
+                             previousSearchTerms );
+        
+        previousSearchTerms.add( "org.apache.maven.archiva.record" );
+        String thirdSearchExpectedResults[] = new String[] { 
+            "junit", "junit2", "junit3"
+        };
+        
+        //third search
+        assertSearchResults( expectedRepos, thirdSearchExpectedResults, search, "junit", previousSearchTerms );        
+    }
+    
+    private void assertSearchResults( String expectedRepos[], String expectedResults[], CrossRepositorySearch search,
+                                      String term, List<String> previousSearchTerms )
         throws Exception
     {
         SearchResultLimits limits = new SearchResultLimits( 0 );
@@ -184,7 +223,15 @@ public class DefaultCrossRepositorySearchTest
         List<String> selectedRepos = new ArrayList<String>();
         selectedRepos.addAll( Arrays.asList( expectedRepos ) );
         
-        SearchResults results = search.searchForTerm( "guest", selectedRepos, term, limits );
+        SearchResults results = null;
+        if( previousSearchTerms == null )
+        {
+            results = search.searchForTerm( "guest", selectedRepos, term, limits );
+        }
+        else
+        {
+            results = search.searchForTerm( "guest", selectedRepos, term, limits, previousSearchTerms );
+        }
         
         assertNotNull( "Search Results should not be null.", results );
         assertEquals( "Repository Hits", expectedRepos.length, results.getRepositories().size() );
index d797c072cbdf8868446eb19e09d170a299f6e604..92b203c847e0ef1863e7497c7767f2e0aedc7666 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.maven.archiva.web.action;
  */
 
 import java.net.MalformedURLException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -83,6 +84,12 @@ public class SearchAction
     private int currentPage = 0;
     
     private int totalPages;
+    
+    private boolean searchResultsOnly; 
+    
+    private String completeQueryString;
+    
+    private static final String COMPLETE_QUERY_STRING_SEPARATOR = ";";
 
     public String quickSearch()
         throws MalformedURLException, RepositoryIndexException, RepositoryIndexSearchException
@@ -103,7 +110,15 @@ public class SearchAction
             return GlobalResults.ACCESS_TO_NO_REPOS;
         }
 
-        results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits );
+        if( searchResultsOnly && !completeQueryString.equals( "" ) )
+        { 
+            results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits, parseCompleteQueryString() );
+        }
+        else
+        {
+            completeQueryString = "";
+            results = crossRepoSearch.searchForTerm( getPrincipal(), selectedRepos, q, limits );
+        }
         
         if ( results.isEmpty() )
         {
@@ -125,7 +140,12 @@ public class SearchAction
          * to result in a higher score. 
          *   - Joakim
          */
-
+        
+        if( !isEqualToPreviousSearchTerm( q ) )
+        {
+            buildCompleteQueryString( q );
+        }
+        
         return SUCCESS;
     }
 
@@ -191,6 +211,46 @@ public class SearchAction
         return Collections.emptyList();
     }
 
+    private void buildCompleteQueryString( String searchTerm )
+    {
+        if( searchTerm.indexOf( COMPLETE_QUERY_STRING_SEPARATOR ) != -1 )
+        {
+            searchTerm = StringUtils.remove( searchTerm, COMPLETE_QUERY_STRING_SEPARATOR );
+        }
+        
+        if( completeQueryString == null || "".equals( completeQueryString ) )
+        {
+            completeQueryString = searchTerm;
+        }
+        else
+        {            
+            completeQueryString = completeQueryString + COMPLETE_QUERY_STRING_SEPARATOR + searchTerm;
+        }
+    }
+    
+    private List<String> parseCompleteQueryString()
+    {
+        List<String> parsedCompleteQueryString = new ArrayList<String>();        
+        String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR );
+        CollectionUtils.addAll( parsedCompleteQueryString, parsed );
+        
+        return parsedCompleteQueryString;
+    }
+    
+    private boolean isEqualToPreviousSearchTerm( String searchTerm )
+    {
+        if( !"".equals( completeQueryString ) )
+        {
+            String[] parsed = StringUtils.split( completeQueryString, COMPLETE_QUERY_STRING_SEPARATOR );
+            if( StringUtils.equalsIgnoreCase( searchTerm, parsed[ parsed.length - 1 ] ) )
+            {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
     public String getQ()
     {
         return q;
@@ -230,4 +290,24 @@ public class SearchAction
     {
         this.totalPages = totalPages;
     }
+
+    public boolean isSearchResultsOnly()
+    {
+        return searchResultsOnly;
+    }
+
+    public void setSearchResultsOnly( boolean searchResultsOnly )
+    {
+        this.searchResultsOnly = searchResultsOnly;
+    }
+
+    public String getCompleteQueryString()
+    {
+        return completeQueryString;
+    }
+
+    public void setCompleteQueryString( String completeQueryString )
+    {
+        this.completeQueryString = completeQueryString;
+    }    
 }
index 7db37265b40db408a076d5087b0de5e55d23e6f6..71ef30ae43be40456045f21e353aa77cab9b5e98 100644 (file)
@@ -22,6 +22,8 @@
 <div id="searchBox">
   <ww:form method="get" action="quickSearch" validate="true">
     <ww:textfield label="Search for" size="50" name="q"/>
+    <ww:checkbox label="Search Results Only" name="searchResultsOnly"/>        
+    <ww:hidden name="completeQueryString" value="${completeQueryString}"/>        
     <ww:submit label="Go!"/>
   </ww:form>
 
index 3bd47cbd3e6d419f5aff93f8c4e9a93db03b10c3..685f24cfe41ae94da4494add01f7b65499482a0f 100644 (file)
                              <ww:url action="quickSearch" namespace="/">
                                <ww:param name="q" value="%{'${q}'}"/>
                                <ww:param name="currentPage" value="%{'${i}'}"/>
+                               <ww:param name="searchResultsOnly" value="%{'${searchResultsOnly}'}"/>
+                               <ww:param name="completeQueryString" value="%{'${completeQueryString}'}"/>
                              </ww:url>
                          </c:set>
                                  <a href="${specificPageUrl}">${i + 1}</a>