a bit more cleaning up
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TaxonServiceImpl.java
index dd3caab3362dc2281d6b3df36abbe523c83190a0..beb58134b1fb3c581363cba49f01a47b690821bf 100644 (file)
@@ -21,10 +21,11 @@ import java.util.UUID;
 import org.apache.log4j.Logger;\r
 import org.apache.lucene.index.CorruptIndexException;\r
 import org.apache.lucene.queryParser.ParseException;\r
+import org.apache.lucene.search.BooleanClause.Occur;\r
+import org.apache.lucene.search.BooleanQuery;\r
 import org.apache.lucene.search.Query;\r
 import org.apache.lucene.search.SortField;\r
 import org.apache.lucene.search.TopDocs;\r
-import org.hibernate.criterion.Criterion;\r
 import org.springframework.beans.factory.annotation.Autowired;\r
 import org.springframework.stereotype.Service;\r
 import org.springframework.transaction.annotation.Propagation;\r
@@ -41,14 +42,14 @@ import eu.etaxonomy.cdm.api.service.pager.Pager;
 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;\r
 import eu.etaxonomy.cdm.api.service.search.ISearchResultBuilder;\r
 import eu.etaxonomy.cdm.api.service.search.LuceneSearch;\r
+import eu.etaxonomy.cdm.api.service.search.QueryFactory;\r
 import eu.etaxonomy.cdm.api.service.search.SearchResult;\r
 import eu.etaxonomy.cdm.api.service.search.SearchResultBuilder;\r
-import eu.etaxonomy.cdm.api.service.search.SearchResultHighligther;\r
 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
 import eu.etaxonomy.cdm.hibernate.search.DefinedTermBaseClassBridge;\r
+import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;\r
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
-import eu.etaxonomy.cdm.model.common.DefinedTermBase;\r
 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
 import eu.etaxonomy.cdm.model.common.Language;\r
@@ -66,7 +67,6 @@ import eu.etaxonomy.cdm.model.media.Media;
 import eu.etaxonomy.cdm.model.media.MediaRepresentation;\r
 import eu.etaxonomy.cdm.model.media.MediaUtils;\r
 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;\r
-import eu.etaxonomy.cdm.model.name.NonViralName;\r
 import eu.etaxonomy.cdm.model.name.Rank;\r
 import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
 import eu.etaxonomy.cdm.model.name.ZoologicalName;\r
@@ -639,6 +639,42 @@ public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDa
         return medRep;\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxonDescriptionMedia(eu.etaxonomy.cdm.model.taxon.Taxon, boolean)\r
+     */\r
+    public List<Media> listTaxonDescriptionMedia(Taxon taxon, boolean limitToGalleries, List<String> propertyPath){\r
+\r
+        Pager<TaxonDescription> p =\r
+                    descriptionService.getTaxonDescriptions(taxon, null, null, null, null, propertyPath);\r
+\r
+        // pars the media and quality parameters\r
+\r
+\r
+        // collect all media of the given taxon\r
+        List<Media> taxonMedia = new ArrayList<Media>();\r
+        List<Media> taxonGalleryMedia = new ArrayList<Media>();\r
+        for(TaxonDescription desc : p.getRecords()){\r
+\r
+            if(desc.isImageGallery()){\r
+                for(DescriptionElementBase element : desc.getElements()){\r
+                    for(Media media : element.getMedia()){\r
+                        taxonGalleryMedia.add(media);\r
+                    }\r
+                }\r
+            } else if(!limitToGalleries){\r
+                for(DescriptionElementBase element : desc.getElements()){\r
+                    for(Media media : element.getMedia()){\r
+                        taxonMedia.add(media);\r
+                    }\r
+                }\r
+            }\r
+\r
+        }\r
+\r
+        taxonGalleryMedia.addAll(taxonMedia);\r
+        return taxonGalleryMedia;\r
+    }\r
+\r
     /* (non-Javadoc)\r
      * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)\r
      */\r
@@ -1092,80 +1128,95 @@ public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDa
         return dao.getUuidAndTitleCacheSynonym();\r
     }\r
 \r
+    @Override\r
+    public Pager<SearchResult<TaxonBase>> findByFullText(\r
+            Class<? extends TaxonBase> clazz, String queryString,\r
+            Classification classification, List<Language> languages,\r
+            boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
+\r
+//        // -- set defaults\r
+//        Class<? extends TaxonBase> directorySelectClass = TaxonBase.class;\r
+//        if(clazz != null){\r
+//            directorySelectClass = clazz;\r
+//        }\r
+        return null;\r
+\r
+    }\r
+\r
     @Override\r
     public Pager<SearchResult<TaxonBase>> findByDescriptionElementFullText(\r
             Class<? extends DescriptionElementBase> clazz, String queryString,\r
             Classification classification, List<Feature> features, List<Language> languages,\r
             boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
 \r
+        // -- set defaults\r
         Class<? extends DescriptionElementBase> directorySelectClass = DescriptionElementBase.class;\r
         if(clazz != null){\r
             directorySelectClass = clazz;\r
         }\r
 \r
-        Set<String> freetextFields = new HashSet<String>();\r
+\r
+        BooleanQuery finalQuery = new BooleanQuery();\r
+        BooleanQuery textQuery = new BooleanQuery();\r
+\r
+        LuceneSearch luceneSearch = new LuceneSearch(getSession(), directorySelectClass);\r
+        QueryFactory queryFactory = new QueryFactory(luceneSearch);\r
+\r
         // ---- search criteria\r
-        freetextFields.add("titleCache");\r
-        StringBuilder luceneQueryTemplate = new StringBuilder();\r
-        luceneQueryTemplate.append("+(");\r
-        luceneQueryTemplate.append("titleCache:%1$s ");\r
+        textQuery.add(queryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
+\r
         // common name\r
-        freetextFields.add("name");\r
+        Query nameQuery;\r
         if(languages == null || languages.size() == 0){\r
-            luceneQueryTemplate.append("name:%1$s ");\r
+            nameQuery = queryFactory.newTermQuery("name", queryString);\r
         } else {\r
-            luceneQueryTemplate.append("(+name:%1$s ");\r
+            nameQuery = new BooleanQuery();\r
+            BooleanQuery languageSubQuery = new BooleanQuery();\r
             for(Language lang : languages){\r
-                luceneQueryTemplate.append(" +language.uuid:" + lang.getUuid().toString());\r
+                languageSubQuery.add(queryFactory.newTermQuery("language.uuid",  lang.getUuid().toString()), Occur.SHOULD);\r
             }\r
-            luceneQueryTemplate.append(")");\r
+            ((BooleanQuery) nameQuery).add(queryFactory.newTermQuery("name", queryString), Occur.MUST);\r
+            ((BooleanQuery) nameQuery).add(languageSubQuery, Occur.MUST);\r
         }\r
+        textQuery.add(nameQuery, Occur.SHOULD);\r
+\r
+\r
         // text field from TextData\r
-        freetextFields.add("text.ALL");\r
-        appendLocalizedFieldQuery("text", languages, luceneQueryTemplate).append(" ");\r
+        textQuery.add(queryFactory.newLocalizedTermQuery("text", queryString, languages), Occur.SHOULD);\r
+\r
+        // --- TermBase fields - by representation ----\r
         // state field from CategoricalData\r
-        freetextFields.add("states.state.representation.ALL");\r
-        appendLocalizedFieldQuery("states.state.representation", languages, luceneQueryTemplate).append(" ");\r
+        textQuery.add(queryFactory.newLocalizedTermQuery("states.state.representation", queryString, languages), Occur.SHOULD);\r
+\r
         // state field from CategoricalData\r
-        freetextFields.add("states.modifyingText.ALL");\r
-        appendLocalizedFieldQuery("states.modifyingText", languages, luceneQueryTemplate).append(" ");\r
-        luceneQueryTemplate.append(") ");\r
+        textQuery.add(queryFactory.newLocalizedTermQuery("states.modifyingText", queryString, languages), Occur.SHOULD);\r
+\r
+        finalQuery.add(textQuery, Occur.MUST);\r
+        // --- classification ----\r
 \r
         if(classification != null){\r
-            luceneQueryTemplate.append("+inDescription.taxon.taxonNodes.classification.id:").append(classification.getId()).append(" ");\r
+            finalQuery.add(queryFactory.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification), Occur.MUST);\r
         }\r
 \r
+        // --- IdentifieableEntity fields - by uuid\r
         if(features != null && features.size() > 0 ){\r
-            luceneQueryTemplate.append("+feature.uuid:(");\r
-            for(Feature feature : features){\r
-                luceneQueryTemplate.append(feature.getUuid()).append(" ");\r
-            }\r
-            luceneQueryTemplate.append(") ");\r
+            finalQuery.add(queryFactory.newEntityUuidQuery("feature.uuid", features), Occur.MUST);\r
         }\r
 \r
         // the description must be associated with a taxon\r
-        // TODO open range queries [0 TO *] not working in the current version of lucene (https://issues.apache.org/jira/browse/LUCENE-995)\r
-        //       so we are using integer maximum as workaround\r
-        luceneQueryTemplate.append("+inDescription.taxon.id:[0 TO " + Integer.MAX_VALUE + "] ");\r
-\r
-        String luceneQueryStr = String.format(luceneQueryTemplate.toString(), queryString);\r
+        finalQuery.add(queryFactory.newIdNotNullQuery("inDescription.taxon.id"), Occur.MUST);\r
 \r
-        // --- sort fields\r
         SortField[] sortFields = new  SortField[]{SortField.FIELD_SCORE, new SortField("inDescription.taxon.titleCache__sort", false)};\r
 \r
-        // ---- execute criteria\r
-        LuceneSearch luceneSearch = new LuceneSearch(getSession(), directorySelectClass);\r
-\r
-        Query luceneQuery = luceneSearch.parse(luceneQueryStr);\r
-        TopDocs topDocsResultSet = luceneSearch.executeSearch(luceneQuery, clazz, pageSize, pageNumber, sortFields);\r
+        TopDocs topDocsResultSet = luceneSearch.executeSearch(finalQuery, clazz, pageSize, pageNumber, sortFields);\r
 \r
         String[] highlightFields = null;\r
         if(highlightFragments){\r
-            highlightFields = freetextFields.toArray(new String[freetextFields.size()]);\r
+            highlightFields = queryFactory.getTextFieldNames().toArray(new String[queryFactory.getTextFieldNames().size()]);\r
         }\r
 \r
         // initialize taxa, thighlight matches ....\r
-        ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneQuery);\r
+        ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, finalQuery);\r
         List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
                 topDocsResultSet, highlightFields, dao, "inDescription.taxon.id", propertyPaths);\r
 \r
@@ -1192,10 +1243,10 @@ public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDa
             stringBuilder = new StringBuilder();\r
         }\r
         if(languages == null || languages.size() == 0){\r
-            stringBuilder.append(name + ".ALL:%1$s ");\r
+            stringBuilder.append(name + ".ALL:(%1$s) ");\r
         } else {\r
             for(Language lang : languages){\r
-                stringBuilder.append(name + "." + lang.getUuid().toString() + ":%1$s ");\r
+                stringBuilder.append(name + "." + lang.getUuid().toString() + ":(%1$s) ");\r
             }\r
         }\r
         return stringBuilder;\r