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
import org.springframework.transaction.annotation.Transactional;\r
\r
-import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;\r
import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator;\r
import eu.etaxonomy.cdm.api.service.config.NameDeletionConfigurator;\r
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;\r
import eu.etaxonomy.cdm.api.service.pager.Pager;\r
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.common.monitor.IProgressMonitor;\r
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
-import eu.etaxonomy.cdm.hibernate.search.DefinedTermBaseFieldBridge;\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.IdentifiableEntity;\r
import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;\r
import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
+import eu.etaxonomy.cdm.model.description.Feature;\r
import eu.etaxonomy.cdm.model.description.IIdentificationKey;\r
import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
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
import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder;\r
-import eu.etaxonomy.cdm.search.LuceneSearch;\r
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;\r
\r
\r
@Autowired\r
private ITaxonNameDao nameDao;\r
\r
- @Autowired\r
- private ISearchResultBuilder searchResultBuilder;\r
-\r
@Autowired\r
private INameService nameService;\r
\r
return heterotypicSynonymyGroups;\r
}\r
\r
- public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(ITaxonServiceConfigurator configurator){\r
+ public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator){\r
\r
List<UuidAndTitleCache<TaxonBase>> result = new ArrayList<UuidAndTitleCache<TaxonBase>>();\r
// Class<? extends TaxonBase> clazz = null;\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)\r
*/\r
- public Pager<IdentifiableEntity> findTaxaAndNames(ITaxonServiceConfigurator configurator) {\r
+ public Pager<IdentifiableEntity> findTaxaAndNames(IFindTaxaAndNamesConfigurator configurator) {\r
\r
List<IdentifiableEntity> results = new ArrayList<IdentifiableEntity>();\r
int numberOfResults = 0; // overall number of results (as opposed to number of results per page)\r
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
}\r
\r
@Override\r
- public Pager<SearchResult<TaxonBase>> findByDescriptionElementFullText(\r
- Class<? extends DescriptionElementBase> clazz, String queryString,\r
- List<Language> languages, Integer pageSize, Integer pageNumber,\r
- List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\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
-// // type selection\r
-// String typeSelect = "";\r
+// // -- set defaults\r
+// Class<? extends TaxonBase> directorySelectClass = TaxonBase.class;\r
// if(clazz != null){\r
-// typeSelect = "_hibernate_class:\"" + clazz.getName() + "\" AND ";\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
- StringBuilder luceneQueryTemplate = new StringBuilder();\r
\r
- luceneQueryTemplate.append("titleCache:%1$s ");\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
+ textQuery.add(queryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
+\r
// common 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 AND (");\r
+ nameQuery = new BooleanQuery();\r
+ BooleanQuery languageSubQuery = new BooleanQuery();\r
for(Language lang : languages){\r
- luceneQueryTemplate.append(" language.label:" + lang.getLabel());\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
- 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
- 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
- appendLocalizedFieldQuery("states.modifyingText", languages, luceneQueryTemplate).append(" ");\r
+ textQuery.add(queryFactory.newLocalizedTermQuery("states.modifyingText", queryString, languages), Occur.SHOULD);\r
\r
-// String luceneQueryTemplate = typeSelect + "( titleCache:%1$s OR " + languageSelection + "OR name:%1$s )";\r
- String luceneQuery = String.format(luceneQueryTemplate.toString(), queryString);\r
+ finalQuery.add(textQuery, Occur.MUST);\r
+ // --- classification ----\r
\r
- LuceneSearch luceneSearch = new LuceneSearch(getSession(), directorySelectClass);\r
- TopDocs topDocsResultSet = luceneSearch.executeSearch(luceneQuery, clazz);\r
- List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSetFromIds(luceneSearch, topDocsResultSet, dao, "inDescription.taxon.id");\r
+ if(classification != null){\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
+ finalQuery.add(queryFactory.newEntityUuidQuery("feature.uuid", features), Occur.MUST);\r
+ }\r
+\r
+ // the description must be associated with a taxon\r
+ finalQuery.add(queryFactory.newIdNotNullQuery("inDescription.taxon.id"), Occur.MUST);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("inDescription.taxon.titleCache__sort", false)};\r
+\r
+ TopDocs topDocsResultSet = luceneSearch.executeSearch(finalQuery, clazz, pageSize, pageNumber, sortFields);\r
+\r
+ String[] highlightFields = null;\r
+ if(highlightFragments){\r
+ highlightFields = queryFactory.getTextFieldNames().toArray(new String[queryFactory.getTextFieldNames().size()]);\r
+ }\r
+\r
+ // initialize taxa, thighlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, finalQuery);\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, highlightFields, dao, "inDescription.taxon.id", propertyPaths);\r
\r
return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, searchResults.size(), pageSize, searchResults);\r
\r
}\r
\r
/**\r
- * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseFieldBridge}\r
+ * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}\r
* and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.\r
* This method is a convenient means to retrieve a Lucene query string for such the fields.\r
*\r
- * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseFieldBridge}\r
+ * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}\r
* or {@link MultilanguageTextFieldBridge }\r
* @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages\r
* @param stringBuilder a StringBuilder to be reused, if <code>null</code> a new StringBuilder will be instantiated and is returned\r
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.getLabel() + ":%1$s ");\r
+ stringBuilder.append(name + "." + lang.getUuid().toString() + ":(%1$s) ");\r
}\r
}\r
return stringBuilder;\r
\r
// Set sourceReference\r
sourceReference = syn.getSec();\r
+ if (sourceReference == null){\r
+ logger.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");\r
+ //TODO:Remove\r
+ if (!parentSynZooName.getTaxa().isEmpty()){\r
+ TaxonBase taxon = parentSynZooName.getTaxa().iterator().next();\r
\r
-\r
+ sourceReference = taxon.getSec();\r
+ }\r
+ }\r
String synTaxonSpecificEpithet = zooSynName.getSpecificEpithet();\r
\r
String synTaxonInfraSpecificName= null;\r
// Determine the sourceReference\r
Reference sourceReference = syn.getSec();\r
\r
+ //logger.warn(sourceReference.getTitleCache());\r
+\r
synName = syn.getName();\r
ZoologicalName synZooName = getZoologicalName(synName.getUuid(), zooHashMap);\r
String synSpeciesEpithetName = synZooName.getSpecificEpithet();\r
\r
originalSource = IdentifiableSource.NewInstance(idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
inferredSynName.addSource(originalSource);\r
+ originalSource = null;\r
\r
+ }else{\r
+ logger.error("There is an idInSource missing: " + idInSourceSyn + " of Synonym or " + idInSourceTaxon + " of Taxon");\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ inferredGenus.addSource(originalSource);\r
+\r
+ originalSource = IdentifiableSource.NewInstance(idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ inferredSynName.addSource(originalSource);\r
+ originalSource = null;\r
}\r
\r
taxon.addSynonym(inferredGenus, SynonymRelationshipType.INFERRED_GENUS_OF());\r
// Determine the sourceReference\r
Reference sourceReference = syn.getSec();\r
\r
+ if (sourceReference == null){\r
+ logger.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");\r
+ //TODO:Remove\r
+ System.out.println("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon.getSec());\r
+ sourceReference = taxon.getSec();\r
+ }\r
+\r
synName = syn.getName();\r
ZoologicalName zooSynName = getZoologicalName(synName.getUuid(), zooHashMap);\r
String synGenusName = zooSynName.getGenusOrUninomial();\r
}\r
count++;\r
}\r
+ } else if (sources.size() == 0){\r
+ logger.warn("No idInSource for TaxonBase " + taxonBase.getUuid() + " - " + taxonBase.getTitleCache());\r
}\r
\r
+\r
return idInSource;\r
}\r
\r