INameService : added findByNameFuzzySearch method to search names by fuzzy matching
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / search / SearchResultBuilder.java
index 213b3e396dc60045ad9bf327a1e32dbd4bc305c4..dee216f54ee97a7d9fea62ba8ac3852361ab72c8 100644 (file)
@@ -11,8 +11,6 @@ package eu.etaxonomy.cdm.api.service.search;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -27,9 +25,9 @@ import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.WildcardQuery;
 import org.apache.lucene.search.grouping.GroupDocs;
-import org.apache.lucene.search.grouping.TopGroups;
-import org.hibernate.search.engine.DocumentBuilder;
+import org.hibernate.search.ProjectionConstants;
 
+import eu.etaxonomy.cdm.api.service.search.LuceneSearch.TopGroupsWithMaxScore;
 import eu.etaxonomy.cdm.model.CdmBaseType;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
@@ -84,7 +82,7 @@ public class SearchResultBuilder implements ISearchResultBuilder {
      * This slows down the query immense or throws TooManyClauses exceptions if
      * too many terms match the wildcard.
      */
-    public <T extends CdmBase> List<SearchResult<T>> createResultSet(TopGroups topGroupsResultSet,
+    public <T extends CdmBase> List<SearchResult<T>> createResultSet(TopGroupsWithMaxScore topGroupsResultSet,
                 String[] highlightFields, ICdmEntityDao<T> dao, Map<CdmBaseType, String> idFields, List<String> propertyPaths) throws CorruptIndexException, IOException {
 
         List<SearchResult<T>> searchResults = new ArrayList<SearchResult<T>>();
@@ -98,7 +96,7 @@ public class SearchResultBuilder implements ISearchResultBuilder {
             highlighter = new SearchResultHighligther();
         }
 
-        for (GroupDocs groupDoc : topGroupsResultSet.groups) {
+        for (GroupDocs groupDoc : topGroupsResultSet.topGroups.groups) {
 
             String cdmEntityId = null;
             SearchResult<T> searchResult = new SearchResult<T>();
@@ -116,10 +114,10 @@ public class SearchResultBuilder implements ISearchResultBuilder {
             if(isNumber(groupDoc.maxScore)){
                 searchResult.setScore(groupDoc.maxScore);
             }
-            //FIXME get max score
-//            if(isNumber(topGroupsResultSet.getMaxScore())){
-//                searchResult.setMaxScore(topGroupsResultSet.getMaxScore());
-//            }
+
+            if(isNumber(topGroupsResultSet.maxScore)){
+                searchResult.setMaxScore(topGroupsResultSet.maxScore);
+            }
 
             //TODO use findByUuid(List<UUID> uuids, List<Criterion> criteria, List<String> propertyPaths)
             //      instead or even better a similar findById(List<Integer> ids) however this is not yet implemented
@@ -143,6 +141,60 @@ public class SearchResultBuilder implements ISearchResultBuilder {
 
         return searchResults;
     }
+    
+    /**
+     * {@inheritDoc}
+     *
+     */
+    public <T extends CdmBase> List<SearchResult<T>> createResultSet(TopDocs topDocs,
+                String[] highlightFields, ICdmEntityDao<T> dao, Map<CdmBaseType, String> idFields, List<String> propertyPaths) throws CorruptIndexException, IOException {
+
+        List<SearchResult<T>> searchResults = new ArrayList<SearchResult<T>>();
+
+        if(topDocs == null){
+            return searchResults;
+        }
+
+        SearchResultHighligther highlighter = null;
+        if(highlightFields  != null && highlightFields.length > 0){
+            highlighter = new SearchResultHighligther();
+        }
+
+        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
+
+               String cdmEntityId = null;
+               SearchResult<T> searchResult = new SearchResult<T>();
+
+               Document document = luceneSearch.getSearcher().doc(scoreDoc.doc);
+               searchResult.addDoc(document);
+
+               if(cdmEntityId == null){                    
+                       cdmEntityId = findId(idFields, document);
+               }
+
+               //TODO use findByUuid(List<UUID> uuids, List<Criterion> criteria, List<String> propertyPaths)
+               //      instead or even better a similar findById(List<Integer> ids) however this is not yet implemented
+               if(cdmEntityId != null){
+                       T entity = dao.load(Integer.valueOf(cdmEntityId), propertyPaths);
+                       searchResult.setEntity(entity);
+               }
+               searchResult.setScore(scoreDoc.score);
+               searchResult.setMaxScore(scoreDoc.score);
+            // add highlight fragments
+            if(highlighter != null){
+                Map<String, String[]> fieldFragmentMap = null;
+                for(Document doc: searchResult.getDocs()){
+                    fieldFragmentMap = merge(fieldFragmentMap, highlighter.getFragmentsWithHighlightedTerms(luceneSearch.getAnalyzer(), query, highlightFields, doc, fragmentNumber, fragmentSize));
+                }
+                searchResult.setFieldHighlightMap(fieldFragmentMap);
+            }
+
+            // finally add the final result to the list
+            searchResults.add(searchResult);
+        }
+
+        return searchResults;
+    }
 
     /**
      * @param base
@@ -173,7 +225,7 @@ public class SearchResultBuilder implements ISearchResultBuilder {
      */
     private String findId(Map<CdmBaseType,String> idFieldMap, Document doc) {
 
-        String docClassName = doc.getValues(DocumentBuilder.CLASS_FIELDNAME)[0];
+        String docClassName = doc.getValues(ProjectionConstants.OBJECT_CLASS)[0];
 
         String id = null;
         for(CdmBaseType baseType  : idFieldMap.keySet()){