\r
import java.io.IOException;\r
import java.util.ArrayList;\r
+import java.util.EnumSet;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
+import java.util.Iterator;\r
import java.util.List;\r
+import java.util.Map;\r
import java.util.Set;\r
import java.util.UUID;\r
\r
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.TopDocs;\r
-import org.hibernate.criterion.Criterion;\r
+import org.apache.lucene.search.BooleanClause.Occur;\r
+import org.apache.lucene.search.BooleanFilter;\r
+import org.apache.lucene.search.BooleanQuery;\r
+import org.apache.lucene.search.DocIdSet;\r
+import org.apache.lucene.search.Query;\r
+import org.apache.lucene.search.QueryWrapperFilter;\r
+import org.apache.lucene.search.SortField;\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.SynonymDeletionConfigurator;\r
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator.ChildHandling;\r
import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException;\r
import eu.etaxonomy.cdm.api.service.exception.HomotypicalGroupChangeException;\r
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\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.ILuceneIndexToolProvider;\r
import eu.etaxonomy.cdm.api.service.search.ISearchResultBuilder;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearch;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearchException;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneSearch;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneSearch.TopGroupsWithMaxScore;\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.util.TaxonRelationshipEdge;\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.GroupByTaxonClassBridge;\r
+import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;\r
+import eu.etaxonomy.cdm.model.CdmBaseType;\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
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;\r
+import eu.etaxonomy.cdm.model.common.OriginalSourceType;\r
import eu.etaxonomy.cdm.model.common.RelationshipBase;\r
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;\r
import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
+import eu.etaxonomy.cdm.model.description.CommonTaxonName;\r
+import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
+import eu.etaxonomy.cdm.model.description.Distribution;\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.PresenceAbsenceTermBase;\r
+import eu.etaxonomy.cdm.model.description.SpecimenDescription;\r
import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
import eu.etaxonomy.cdm.model.description.TaxonInteraction;\r
+import eu.etaxonomy.cdm.model.description.TaxonNameDescription;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
import eu.etaxonomy.cdm.model.media.Media;\r
import eu.etaxonomy.cdm.model.media.MediaRepresentation;\r
import eu.etaxonomy.cdm.model.media.MediaUtils;\r
+import eu.etaxonomy.cdm.model.molecular.Amplification;\r
+import eu.etaxonomy.cdm.model.molecular.DnaSample;\r
+import eu.etaxonomy.cdm.model.molecular.Sequence;\r
+import eu.etaxonomy.cdm.model.molecular.SingleRead;\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.model.occurrence.DerivedUnitBase;\r
+import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
import eu.etaxonomy.cdm.model.reference.Reference;\r
import eu.etaxonomy.cdm.model.taxon.Classification;\r
import eu.etaxonomy.cdm.model.taxon.Synonym;\r
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;\r
import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;\r
import eu.etaxonomy.cdm.persistence.dao.common.IOrderedTermVocabularyDao;\r
+import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer;\r
import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;\r
+import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;\r
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;\r
import eu.etaxonomy.cdm.persistence.fetch.CdmFetch;\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
*\r
*/\r
@Service\r
-@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)\r
+@Transactional(readOnly = true)\r
public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDao> implements ITaxonService{\r
private static final Logger logger = Logger.getLogger(TaxonServiceImpl.class);\r
\r
@Autowired\r
private ITaxonNameDao nameDao;\r
\r
- @Autowired\r
- private ISearchResultBuilder searchResultBuilder;\r
-\r
@Autowired\r
private INameService nameService;\r
+ \r
+ @Autowired\r
+ private ITaxonNodeService nodeService;\r
+ \r
\r
@Autowired\r
private ICdmGenericDao genericDao;\r
@Autowired\r
private IOrderedTermVocabularyDao orderedVocabularyDao;\r
\r
+ @Autowired\r
+ private IOccurrenceDao occurrenceDao;\r
+\r
+ @Autowired\r
+ private AbstractBeanInitializer beanInitializer;\r
+\r
+ @Autowired\r
+ private ILuceneIndexToolProvider luceneIndexToolProvider;\r
+\r
/**\r
* Constructor\r
*/\r
* FIXME Candidate for harmonization\r
* rename searchByName ?\r
*/\r
+ @Override\r
public List<TaxonBase> searchTaxaByName(String name, Reference sec) {\r
return dao.getTaxaByName(name, sec);\r
}\r
* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)\r
*/\r
+ @Override\r
public List<Synonym> getAllSynonyms(int limit, int start) {\r
return dao.getAllSynonyms(limit, start);\r
}\r
* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)\r
*/\r
+ @Override\r
public List<Taxon> getAllTaxa(int limit, int start) {\r
return dao.getAllTaxa(limit, start);\r
}\r
* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)\r
*/\r
+ @Override\r
public List<Taxon> getRootTaxa(Reference sec, CdmFetch cdmFetch, boolean onlyWithChildren) {\r
if (cdmFetch == null){\r
cdmFetch = CdmFetch.NO_FETCH();\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)\r
*/\r
+ @Override\r
public List<Taxon> getRootTaxa(Rank rank, Reference sec, boolean onlyWithChildren,boolean withMisapplications, List<String> propertyPaths) {\r
return dao.getRootTaxa(rank, sec, null, onlyWithChildren, withMisapplications, propertyPaths);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)\r
*/\r
+ @Override\r
public List<RelationshipBase> getAllRelationships(int limit, int start){\r
return dao.getAllRelationships(limit, start);\r
}\r
* FIXME Candidate for harmonization\r
* is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?\r
*/\r
+ @Override\r
@Deprecated\r
public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypeVocabulary() {\r
\r
* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)\r
*/\r
+ @Override\r
@Transactional(readOnly = false)\r
public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)\r
*/\r
- //TODO correct delete handling still needs to be implemented / checked\r
+ \r
@Override\r
@Transactional(readOnly = false)\r
public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, boolean deleteSynonym, boolean copyCitationInfo, Reference citation, String microCitation) throws HomotypicalGroupChangeException{\r
-\r
+ \r
TaxonNameBase<?,?> acceptedName = acceptedTaxon.getName();\r
TaxonNameBase<?,?> synonymName = synonym.getName();\r
HomotypicalGroup synonymHomotypicGroup = synonymName.getHomotypicalGroup();\r
}\r
\r
//synonym.getName().removeTaxonBase(synonym);\r
- //TODO correct delete handling still needs to be implemented / checked\r
+ \r
if (deleteSynonym){\r
// deleteSynonym(synonym, taxon, false);\r
try {\r
this.dao.flush();\r
- this.delete(synonym);\r
+ this.deleteSynonym(synonym, acceptedTaxon, new SynonymDeletionConfigurator());\r
\r
} catch (Exception e) {\r
logger.info("Can't delete old synonym from database");\r
}\r
\r
\r
+ @Override\r
public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, Reference citation, String microcitation){\r
\r
// Get name from synonym\r
super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);\r
}\r
\r
+ @Override\r
@Autowired\r
protected void setDao(ITaxonDao dao) {\r
this.dao = dao;\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)\r
*/\r
+ @Override\r
public Pager<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {\r
Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)\r
*/\r
+ @Override\r
public List<TaxonBase> listTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {\r
Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#listToTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public List<TaxonRelationship> listToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#pageToTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public Pager<TaxonRelationship> pageToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#listFromTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public List<TaxonRelationship> listFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#pageFromTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public Pager<TaxonRelationship> pageFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);\r
\r
return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);\r
}\r
\r
+ /**\r
+ * @param taxon\r
+ * @param includeRelationships\r
+ * @param maxDepth\r
+ * @param limit\r
+ * @param starts\r
+ * @param propertyPaths\r
+ * @return an List which is not specifically ordered\r
+ */\r
+ @Override\r
+ public Set<Taxon> listRelatedTaxa(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, Integer maxDepth,\r
+ Integer limit, Integer start, List<String> propertyPaths) {\r
+\r
+ Set<Taxon> relatedTaxa = collectRelatedTaxa(taxon, includeRelationships, new HashSet<Taxon>(), maxDepth);\r
+ relatedTaxa.remove(taxon);\r
+ beanInitializer.initializeAll(relatedTaxa, propertyPaths);\r
+ return relatedTaxa;\r
+ }\r
+\r
+\r
+ /**\r
+ * recursively collect related taxa for the given <code>taxon</code> . The returned list will also include the\r
+ * <code>taxon</code> supplied as parameter.\r
+ *\r
+ * @param taxon\r
+ * @param includeRelationships\r
+ * @param taxa\r
+ * @param maxDepth can be <code>null</code> for infinite depth\r
+ * @return\r
+ */\r
+ private Set<Taxon> collectRelatedTaxa(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, Set<Taxon> taxa, Integer maxDepth) {\r
+\r
+ if(taxa.isEmpty()) {\r
+ taxa.add(taxon);\r
+ }\r
+\r
+ if(maxDepth != null) {\r
+ maxDepth--;\r
+ }\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug("collecting related taxa for " + taxon + " with maxDepth=" + maxDepth);\r
+ }\r
+ List<TaxonRelationship> taxonRelationships = dao.getTaxonRelationships(taxon, null, null, null, null, null, null);\r
+ for (TaxonRelationship taxRel : taxonRelationships) {\r
+\r
+ // skip invalid data\r
+ if (taxRel.getToTaxon() == null || taxRel.getFromTaxon() == null || taxRel.getType() == null) {\r
+ continue;\r
+ }\r
+ // filter by includeRelationships\r
+ for (TaxonRelationshipEdge relationshipEdgeFilter : includeRelationships) {\r
+ if ( relationshipEdgeFilter.getTaxonRelationshipType().equals(taxRel.getType()) ) {\r
+ if (relationshipEdgeFilter.getDirections().contains(Direction.relatedTo) && !taxa.contains(taxRel.getToTaxon())) {\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug(maxDepth + ": " + taxon.getTitleCache() + " --[" + taxRel.getType().getLabel() + "]--> " + taxRel.getToTaxon().getTitleCache());\r
+ }\r
+ taxa.add(taxRel.getToTaxon());\r
+ if(maxDepth == null || maxDepth > 0) {\r
+ taxa.addAll(collectRelatedTaxa(taxRel.getToTaxon(), includeRelationships, taxa, maxDepth));\r
+ }\r
+ }\r
+ if(relationshipEdgeFilter.getDirections().contains(Direction.relatedFrom) && !taxa.contains(taxRel.getFromTaxon())) {\r
+ taxa.add(taxRel.getFromTaxon());\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug(maxDepth + ": " +taxRel.getFromTaxon().getTitleCache() + " --[" + taxRel.getType().getLabel() + "]--> " + taxon.getTitleCache() );\r
+ }\r
+ if(maxDepth == null || maxDepth > 0) {\r
+ taxa.addAll(collectRelatedTaxa(taxRel.getFromTaxon(), includeRelationships, taxa, maxDepth));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return taxa;\r
+ }\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getSynonyms(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public Pager<SynonymRelationship> getSynonyms(Taxon taxon, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countSynonyms(taxon, type);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getSynonyms(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public Pager<SynonymRelationship> getSynonyms(Synonym synonym, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countSynonyms(synonym, type);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
*/\r
+ @Override\r
public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){\r
Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
return t.getHomotypicSynonymsByHomotypicGroup();\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
*/\r
+ @Override\r
public List<List<Synonym>> getHeterotypicSynonymyGroups(Taxon taxon, List<String> propertyPaths){\r
Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
List<HomotypicalGroup> homotypicalGroups = t.getHeterotypicSynonymyGroups();\r
return heterotypicSynonymyGroups;\r
}\r
\r
- public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(ITaxonServiceConfigurator configurator){\r
+ @Override\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
+ @Override\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
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])\r
*/\r
+ @Override\r
public List<MediaRepresentation> getAllMedia(Taxon taxon, int size, int height, int widthOrDuration, String[] mimeTypes){\r
List<MediaRepresentation> medRep = new ArrayList<MediaRepresentation>();\r
taxon = (Taxon)dao.load(taxon.getUuid());\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
+ @Override\r
+ public List<Media> listTaxonDescriptionMedia(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, boolean limitToGalleries, List<String> propertyPath){\r
+ return listMedia(taxon, includeRelationships, limitToGalleries, true, false, false, propertyPath);\r
+ }\r
+\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#listMedia(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, boolean, java.util.List)\r
+ */\r
+ @Override\r
+ public List<Media> listMedia(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships,\r
+ Boolean limitToGalleries, Boolean includeTaxonDescriptions, Boolean includeOccurrences,\r
+ Boolean includeTaxonNameDescriptions, List<String> propertyPath) {\r
+\r
+ Set<Taxon> taxa = new HashSet<Taxon>();\r
+ List<Media> taxonMedia = new ArrayList<Media>();\r
+\r
+ if (limitToGalleries == null) {\r
+ limitToGalleries = false;\r
+ }\r
+\r
+ // --- resolve related taxa\r
+ if (includeRelationships != null) {\r
+ taxa = listRelatedTaxa(taxon, includeRelationships, null, null, null, null);\r
+ }\r
+\r
+ taxa.add((Taxon) dao.load(taxon.getUuid()));\r
+\r
+ if(includeTaxonDescriptions != null && includeTaxonDescriptions){\r
+ List<TaxonDescription> taxonDescriptions = new ArrayList<TaxonDescription>();\r
+ // --- TaxonDescriptions\r
+ for (Taxon t : taxa) {\r
+ taxonDescriptions.addAll(descriptionService.listTaxonDescriptions(t, null, null, null, null, propertyPath));\r
+ }\r
+ for (TaxonDescription taxonDescription : taxonDescriptions) {\r
+ if (!limitToGalleries || taxonDescription.isImageGallery()) {\r
+ for (DescriptionElementBase element : taxonDescription.getElements()) {\r
+ for (Media media : element.getMedia()) {\r
+ taxonMedia.add(media);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if(includeOccurrences != null && includeOccurrences) {\r
+ Set<SpecimenOrObservationBase> specimensOrObservations = new HashSet<SpecimenOrObservationBase>();\r
+ // --- Specimens\r
+ for (Taxon t : taxa) {\r
+ specimensOrObservations.addAll(occurrenceDao.listByAssociatedTaxon(null, t, null, null, null, null));\r
+ }\r
+ for (SpecimenOrObservationBase occurrence : specimensOrObservations) {\r
+\r
+// direct media removed from specimen #3597\r
+// taxonMedia.addAll(occurrence.getMedia());\r
+\r
+ // SpecimenDescriptions\r
+ Set<SpecimenDescription> specimenDescriptions = occurrence.getSpecimenDescriptions();\r
+ for (DescriptionBase specimenDescription : specimenDescriptions) {\r
+ if (!limitToGalleries || specimenDescription.isImageGallery()) {\r
+ Set<DescriptionElementBase> elements = specimenDescription.getElements();\r
+ for (DescriptionElementBase element : elements) {\r
+ for (Media media : element.getMedia()) {\r
+ taxonMedia.add(media);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // Collection\r
+ //TODO why may collections have media attached? #\r
+ if (occurrence.isInstanceOf(DerivedUnit.class)) {\r
+ DerivedUnit derivedUnit = CdmBase.deproxy(occurrence, DerivedUnit.class);\r
+ if (derivedUnit.getCollection() != null){\r
+ taxonMedia.addAll(derivedUnit.getCollection().getMedia());\r
+ }\r
+ }\r
+\r
+ // pherograms & gelPhotos\r
+ if (occurrence.isInstanceOf(DnaSample.class)) {\r
+ DnaSample dnaSample = CdmBase.deproxy(occurrence, DnaSample.class);\r
+ Set<Sequence> sequences = dnaSample.getSequences();\r
+ //we do show only those gelPhotos which lead to a consensus sequence\r
+ for (Sequence sequence : sequences) {\r
+ Set<Media> dnaRelatedMedia = new HashSet<Media>();\r
+ for (SingleRead singleRead : sequence.getSingleReads()){\r
+ Amplification amplification = singleRead.getAmplification();\r
+ dnaRelatedMedia.add(amplification.getGelPhoto());\r
+ dnaRelatedMedia.add(singleRead.getPherogram());\r
+ dnaRelatedMedia.remove(null);\r
+ }\r
+ taxonMedia.addAll(dnaRelatedMedia);\r
+ }\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+ if(includeTaxonNameDescriptions != null && includeTaxonNameDescriptions) {\r
+ // --- TaxonNameDescription\r
+ Set<TaxonNameDescription> nameDescriptions = new HashSet<TaxonNameDescription>();\r
+ for (Taxon t : taxa) {\r
+ nameDescriptions .addAll(t.getName().getDescriptions());\r
+ }\r
+ for(TaxonNameDescription nameDescription: nameDescriptions){\r
+ if (!limitToGalleries || nameDescription.isImageGallery()) {\r
+ Set<DescriptionElementBase> elements = nameDescription.getElements();\r
+ for (DescriptionElementBase element : elements) {\r
+ for (Media media : element.getMedia()) {\r
+ taxonMedia.add(media);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ beanInitializer.initializeAll(taxonMedia, propertyPath);\r
+ return taxonMedia;\r
+ }\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)\r
*/\r
+ @Override\r
public List<TaxonBase> findTaxaByID(Set<Integer> listOfIDs) {\r
- return this.dao.findById(listOfIDs);\r
+ return this.dao.listByIds(listOfIDs, null, null, null, null);\r
}\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)\r
*/\r
+ @Override\r
public TaxonBase findTaxonByUuid(UUID uuid, List<String> propertyPaths){\r
return this.dao.findByUuid(uuid, null ,propertyPaths);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()\r
*/\r
+ @Override\r
public int countAllRelationships() {\r
return this.dao.countAllRelationships();\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)\r
*/\r
+ @Override\r
public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {\r
return this.dao.findIdenticalTaxonNames(propertyPath);\r
}\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)\r
*/\r
@Override\r
- public void deleteTaxon(Taxon taxon, TaxonDeletionConfigurator config) throws ReferencedObjectUndeletableException {\r
+ public UUID deleteTaxon(Taxon taxon, TaxonDeletionConfigurator config, Classification classification) throws DataChangeNoRollbackException {\r
if (config == null){\r
config = new TaxonDeletionConfigurator();\r
}\r
\r
- // TaxonNode\r
- if (! config.isDeleteTaxonNodes()){\r
- if (taxon.getTaxonNodes().size() > 0){\r
- String message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
- }\r
-\r
-\r
// SynonymRelationShip\r
if (config.isDeleteSynonymRelations()){\r
boolean removeSynonymNameFromHomotypicalGroup = false;\r
if (config.isDeleteSynonymsIfPossible()){\r
//TODO which value\r
boolean newHomotypicGroupIfNeeded = true;\r
- deleteSynonym(synonym, taxon, config.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded);\r
+ SynonymDeletionConfigurator synConfig = new SynonymDeletionConfigurator();\r
+ \r
+ deleteSynonym(synonym, taxon, synConfig);\r
}else{\r
deleteSynonymRelationships(synonym, taxon);\r
}\r
String message = "Taxon can't be deleted as it is related to another taxon. Remove taxon from all relations to other taxa prior to deletion.";\r
throw new ReferencedObjectUndeletableException(message);\r
}\r
+ } else{\r
+ for (TaxonRelationship taxRel: taxon.getTaxonRelations()){\r
+ \r
+ \r
+ \r
+ if (config.isDeleteMisappliedNamesAndInvalidDesignations()){\r
+ if (taxRel.getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR()) || taxRel.getType().equals(TaxonRelationshipType.INVALID_DESIGNATION_FOR())){\r
+ if (taxon.equals(taxRel.getToTaxon())){\r
+ this.deleteTaxon(taxRel.getFromTaxon(), config, classification);\r
+ }\r
+ }\r
+ }\r
+ taxon.removeTaxonRelation(taxRel);\r
+ /*if (taxFrom.equals(taxon)){\r
+ try{\r
+ this.deleteTaxon(taxTo, taxConf, classification);\r
+ } catch(DataChangeNoRollbackException e){\r
+ logger.debug("A related taxon will not be deleted." + e.getMessage());\r
+ }\r
+ } else {\r
+ try{\r
+ this.deleteTaxon(taxFrom, taxConf, classification);\r
+ } catch(DataChangeNoRollbackException e){\r
+ logger.debug("A related taxon will not be deleted." + e.getMessage());\r
+ }\r
+ \r
+ }*/\r
+ }\r
}\r
\r
\r
+ \r
+ \r
// TaxonDescription\r
+ if (config.isDeleteDescriptions()){\r
Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
\r
for (TaxonDescription desc: descriptions){\r
- if (config.isDeleteDescriptions()){\r
- //TODO use description delete configurator ?\r
- //FIXME check if description is ALWAYS deletable\r
- descriptionService.delete(desc);\r
- }else{\r
- if (desc.getDescribedSpecimenOrObservations().size()>0){\r
- String message = "Taxon can't be deleted as it is used in a TaxonDescription" +\r
- " which also describes specimens or abservations";\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
- }\r
+ //TODO use description delete configurator ?\r
+ //FIXME check if description is ALWAYS deletable\r
+ if (desc.getDescribedSpecimenOrObservation() != null){\r
+ String message = "Taxon can't be deleted as it is used in a TaxonDescription" +\r
+ " which also describes specimens or abservations";\r
+ throw new ReferencedObjectUndeletableException(message);\r
}\r
+ descriptionService.delete(desc);\r
+ taxon.removeDescription(desc);\r
+ }\r
+ }\r
\r
\r
- //check references with only reverse mapping\r
- Set<CdmBase> referencingObjects = genericDao.getReferencingObjects(taxon);\r
- for (CdmBase referencingObject : referencingObjects){\r
- //IIdentificationKeys (Media, Polytomous, MultiAccess)\r
- if (HibernateProxyHelper.isInstanceOf(referencingObject, IIdentificationKey.class)){\r
- String message = "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";\r
- message = String.format(message, CdmBase.deproxy(referencingObject, DerivedUnitBase.class).getTitleCache());\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
-\r
-\r
- //PolytomousKeyNode\r
- if (referencingObject.isInstanceOf(PolytomousKeyNode.class)){\r
- String message = "Taxon can't be deleted as it is used in polytomous key node";\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
-\r
- //TaxonInteraction\r
- if (referencingObject.isInstanceOf(TaxonInteraction.class)){\r
- String message = "Taxon can't be deleted as it is used in taxonInteraction#taxon2";\r
+ //check references with only reverse mapping\r
+ String message = checkForReferences(taxon);\r
+ if (message != null){\r
+ throw new ReferencedObjectUndeletableException(message.toString());\r
+ }\r
+ \r
+ if (! config.isDeleteTaxonNodes() || (!config.isDeleteInAllClassifications() && classification == null )){\r
+ if (taxon.getTaxonNodes().size() > 0){\r
+ message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion or define a classification where it should be deleted or adapt the taxon deletion configurator.";\r
throw new ReferencedObjectUndeletableException(message);\r
}\r
+ }else{\r
+ if (taxon.getTaxonNodes().size() != 0){\r
+ Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
+ Iterator<TaxonNode> iterator = nodes.iterator();\r
+ TaxonNode node = null;\r
+ boolean deleteChildren;\r
+ if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)){\r
+ deleteChildren = true;\r
+ }else {\r
+ deleteChildren = false;\r
+ }\r
+ boolean success = true;\r
+ if (!config.isDeleteInAllClassifications() && !(classification == null)){\r
+ while (iterator.hasNext()){\r
+ node = iterator.next();\r
+ if (node.getClassification().equals(classification)){\r
+ break;\r
+ }\r
+ node = null;\r
+ }\r
+ if (node != null){\r
+ success =taxon.removeTaxonNode(node, deleteChildren);\r
+ } else {\r
+ message = "Taxon is not used in defined classification";\r
+ throw new DataChangeNoRollbackException(message);\r
+ }\r
+ } else if (config.isDeleteInAllClassifications()){\r
+ List<TaxonNode> nodesList = new ArrayList<TaxonNode>();\r
+ nodesList.addAll(taxon.getTaxonNodes());\r
+ \r
+ for (TaxonNode taxonNode: nodesList){\r
+ if(deleteChildren){\r
+ Object[] childNodes = taxonNode.getChildNodes().toArray();\r
+ for (Object childNode: childNodes){\r
+ TaxonNode childNodeCast = (TaxonNode) childNode;\r
+ deleteTaxon(childNodeCast.getTaxon(), config, classification);\r
+ \r
+ }\r
+ \r
+ /*for (TaxonNode childNode: taxonNode.getChildNodes()){\r
+ deleteTaxon(childNode.getTaxon(), config, classification);\r
+ \r
+ }*/\r
+ //taxon.removeTaxonNode(taxonNode);\r
+ } else{\r
+ Object[] childNodes = taxonNode.getChildNodes().toArray();\r
+ for (Object childNode: childNodes){\r
+ TaxonNode childNodeCast = (TaxonNode) childNode;\r
+ taxonNode.getParent().addChildNode(childNodeCast, childNodeCast.getReference(), childNodeCast.getMicroReference());\r
+ }\r
+ \r
+ //taxon.removeTaxonNode(taxonNode);\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ nodeService.deleteTaxonNodes(nodesList);\r
+ \r
+ }\r
+ if (!success){\r
+ message = "The taxon node could not be deleted.";\r
+ throw new DataChangeNoRollbackException(message);\r
+ }\r
+ }\r
}\r
-\r
-\r
//TaxonNameBase\r
if (config.isDeleteNameIfPossible()){\r
try {\r
- nameService.delete(taxon.getName(), config.getNameDeletionConfig());\r
+ \r
+ //TaxonNameBase name = nameService.find(taxon.getName().getUuid());\r
+ TaxonNameBase name = (TaxonNameBase)HibernateProxyHelper.deproxy(taxon.getName());\r
+ //check whether taxon will be deleted or not\r
+ if (taxon.getTaxonNodes() == null || taxon.getTaxonNodes().size()== 0){\r
+ taxon = (Taxon) HibernateProxyHelper.deproxy(taxon);\r
+ name.removeTaxonBase(taxon);\r
+ nameService.save(name);\r
+ nameService.delete(name, config.getNameDeletionConfig());\r
+ }\r
} catch (ReferencedObjectUndeletableException e) {\r
//do nothing\r
if (logger.isDebugEnabled()){logger.debug("Name could not be deleted");}\r
+ \r
}\r
}\r
+ \r
+// TaxonDescription\r
+ /* Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
+\r
+ for (TaxonDescription desc: descriptions){\r
+ if (config.isDeleteDescriptions()){\r
+ //TODO use description delete configurator ?\r
+ //FIXME check if description is ALWAYS deletable\r
+ taxon.removeDescription(desc);\r
+ descriptionService.delete(desc);\r
+ }else{\r
+ if (desc.getDescribedSpecimenOrObservations().size()>0){\r
+ String message = "Taxon can't be deleted as it is used in a TaxonDescription" +\r
+ " which also describes specimens or observations";\r
+ throw new ReferencedObjectUndeletableException(message);\r
+ }\r
+ }\r
+ }*/\r
+ \r
+ \r
+\r
+ if (taxon.getTaxonNodes() == null || taxon.getTaxonNodes().size()== 0){\r
+ dao.delete(taxon);\r
+ return taxon.getUuid();\r
+ } else{\r
+ message = "Taxon can't be deleted as it is used in another Taxonnode";\r
+ throw new ReferencedObjectUndeletableException(message);\r
+ }\r
+ \r
\r
}\r
+ \r
+ private String checkForReferences(Taxon taxon){\r
+ Set<CdmBase> referencingObjects = genericDao.getReferencingObjects(taxon);\r
+ for (CdmBase referencingObject : referencingObjects){\r
+ //IIdentificationKeys (Media, Polytomous, MultiAccess)\r
+ if (HibernateProxyHelper.isInstanceOf(referencingObject, IIdentificationKey.class)){\r
+ String message = "Taxon" + taxon.getTitleCache() + "can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";\r
+ \r
+ return message;\r
+ }\r
+\r
\r
+ //PolytomousKeyNode\r
+ if (referencingObject.isInstanceOf(PolytomousKeyNode.class)){\r
+ String message = "Taxon" + taxon.getTitleCache() + " can't be deleted as it is used in polytomous key node";\r
+ return message;\r
+ }\r
+\r
+ //TaxonInteraction\r
+ if (referencingObject.isInstanceOf(TaxonInteraction.class)){\r
+ String message = "Taxon can't be deleted as it is used in taxonInteraction#taxon2";\r
+ return message;\r
+ }\r
+ }\r
+ referencingObjects = null;\r
+ return null;\r
+ }\r
+ \r
+ @Transactional(readOnly = false)\r
+ public UUID delete(Synonym syn){\r
+ UUID result = syn.getUuid();\r
+ this.deleteSynonym(syn, null);\r
+ return result;\r
+ }\r
+ \r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)\r
*/\r
@Transactional(readOnly = false)\r
@Override\r
- public void deleteSynonym(Synonym synonym, Taxon taxon, boolean removeNameIfPossible,boolean newHomotypicGroupIfNeeded) {\r
+ public void deleteSynonym(Synonym synonym, SynonymDeletionConfigurator config) {\r
+ deleteSynonym(synonym, null, config);\r
+ \r
+ }\r
+ \r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)\r
+ */\r
+ @Transactional(readOnly = false)\r
+ @Override\r
+ public void deleteSynonym(Synonym synonym, Taxon taxon, SynonymDeletionConfigurator config) {\r
if (synonym == null){\r
return;\r
}\r
+ if (config == null){\r
+ config = new SynonymDeletionConfigurator();\r
+ }\r
synonym = CdmBase.deproxy(dao.merge(synonym), Synonym.class);\r
\r
//remove synonymRelationship\r
}\r
for (Taxon relatedTaxon : taxonSet){\r
// dao.deleteSynonymRelationships(synonym, relatedTaxon);\r
- relatedTaxon.removeSynonym(synonym, newHomotypicGroupIfNeeded);\r
+ relatedTaxon.removeSynonym(synonym, config.isNewHomotypicGroupIfNeeded());\r
}\r
this.saveOrUpdate(synonym);\r
\r
//TODO remove name from homotypical group?\r
\r
//remove synonym (if necessary)\r
+ \r
+ \r
if (synonym.getSynonymRelations().isEmpty()){\r
TaxonNameBase<?,?> name = synonym.getName();\r
synonym.setName(null);\r
dao.delete(synonym);\r
\r
//remove name if possible (and required)\r
- if (name != null && removeNameIfPossible){\r
+ if (name != null && config.isDeleteNameIfPossible()){\r
try{\r
- nameService.delete(name, new NameDeletionConfigurator());\r
- }catch (DataChangeNoRollbackException ex){\r
- if (logger.isDebugEnabled())logger.debug("Name wasn't deleted as it is referenced");\r
+ nameService.delete(name, config.getNameDeletionConfig());\r
+ }catch (ReferencedObjectUndeletableException ex){\r
+ System.err.println("Name wasn't deleted as it is referenced");\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Name wasn't deleted as it is referenced");\r
+ }\r
}\r
}\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)\r
*/\r
+ @Override\r
public List<TaxonNameBase> findIdenticalTaxonNameIds(List<String> propertyPath) {\r
\r
return this.dao.findIdenticalNamesNew(propertyPath);\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)\r
*/\r
+ @Override\r
public String getPhylumName(TaxonNameBase name){\r
return this.dao.getPhylumName(name);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)\r
*/\r
+ @Override\r
public long deleteSynonymRelationships(Synonym syn, Taxon taxon) {\r
return dao.deleteSynonymRelationships(syn, taxon);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)\r
*/\r
+ @Override\r
public long deleteSynonymRelationships(Synonym syn) {\r
return dao.deleteSynonymRelationships(syn, null);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#listSynonymRelationships(eu.etaxonomy.cdm.model.taxon.TaxonBase, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction)\r
*/\r
+ @Override\r
public List<SynonymRelationship> listSynonymRelationships(\r
TaxonBase taxonBase, SynonymRelationshipType type, Integer pageSize, Integer pageNumber,\r
List<OrderHint> orderHints, List<String> propertyPaths, Direction direction) {\r
\r
} catch (Exception e){\r
logger.error(e);\r
+ e.printStackTrace();\r
}\r
\r
return bestCandidate;\r
return dao.getUuidAndTitleCacheSynonym();\r
}\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findByFullText(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\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
+\r
+ LuceneSearch luceneSearch = prepareFindByFullTextSearch(clazz, queryString, classification, languages, highlightFragments);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+\r
+ // --- initialize taxa, thighlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+ }\r
+\r
+ @Override\r
+ public Pager<SearchResult<TaxonBase>> findByDistribution(List<NamedArea> areaFilter, List<PresenceAbsenceTermBase<?>> statusFilter,\r
+ Classification classification,\r
+ Integer pageSize, Integer pageNumber,\r
+ List<OrderHint> orderHints, List<String> propertyPaths) throws IOException, ParseException {\r
+\r
+ LuceneSearch luceneSearch = prepareByDistributionSearch(areaFilter, statusFilter, classification);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+\r
+ // --- initialize taxa, thighlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+ }\r
+\r
+ /**\r
+ * @param clazz\r
+ * @param queryString\r
+ * @param classification\r
+ * @param languages\r
+ * @param highlightFragments\r
+ * @param directorySelectClass\r
+ * @return\r
+ */\r
+ protected LuceneSearch prepareFindByFullTextSearch(Class<? extends CdmBase> clazz, String queryString, Classification classification, List<Language> languages,\r
+ boolean highlightFragments) {\r
+ BooleanQuery finalQuery = new BooleanQuery();\r
+ BooleanQuery textQuery = new BooleanQuery();\r
+\r
+ LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, TaxonBase.class);\r
+ QueryFactory taxonBaseQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonBase.class);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ luceneSearch.setSortFields(sortFields);\r
+\r
+ // ---- search criteria\r
+ luceneSearch.setCdmTypRestriction(clazz);\r
+\r
+ textQuery.add(taxonBaseQueryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
+ textQuery.add(taxonBaseQueryFactory.newDefinedTermQuery("name.rank", queryString, languages), Occur.SHOULD);\r
+\r
+ finalQuery.add(textQuery, Occur.MUST);\r
+\r
+ if(classification != null){\r
+ finalQuery.add(taxonBaseQueryFactory.newEntityIdQuery("taxonNodes.classification.id", classification), Occur.MUST);\r
+ }\r
+ luceneSearch.setQuery(finalQuery);\r
+\r
+ if(highlightFragments){\r
+ luceneSearch.setHighlightFields(taxonBaseQueryFactory.getTextFieldNamesAsArray());\r
+ }\r
+ return luceneSearch;\r
+ }\r
+\r
+ /**\r
+ * Uses org.apache.lucene.search.join.JoinUtil for query time joining, alternatively\r
+ * the BlockJoinQuery could be used. The latter might be more memory save but has the\r
+ * drawback of requiring to do the join an indexing time.\r
+ * see http://dev.e-taxonomy.eu/trac/wiki/LuceneNotes#JoinsinLucene for more information on this.\r
+ *\r
+ * Joins TaxonRelationShip with Taxon depending on the direction of the given edge:\r
+ * <ul>\r
+ * <li>direct, everted: {@link Direction.relatedTo}: TaxonRelationShip.relatedTo.id --> Taxon.id </li>\r
+ * <li>inverse: {@link Direction.relatedFrom}: TaxonRelationShip.relatedFrom.id --> Taxon.id </li>\r
+ * <ul>\r
+ *\r
+ * @param queryString\r
+ * @param classification\r
+ * @param languages\r
+ * @param highlightFragments\r
+ * @return\r
+ * @throws IOException\r
+ */\r
+ protected LuceneSearch prepareFindByTaxonRelationFullTextSearch(TaxonRelationshipEdge edge, String queryString, Classification classification, List<Language> languages,\r
+ boolean highlightFragments) throws IOException {\r
+\r
+ String fromField;\r
+ String queryTermField;\r
+ String toField = "id"; // TaxonBase.uuid\r
+\r
+ if(edge.isBidirectional()){\r
+ throw new RuntimeException("Bidirectional joining not supported!");\r
+ }\r
+ if(edge.isEvers()){\r
+ fromField = "relatedFrom.id";\r
+ queryTermField = "relatedFrom.titleCache";\r
+ } else if(edge.isInvers()) {\r
+ fromField = "relatedTo.id";\r
+ queryTermField = "relatedTo.titleCache";\r
+ } else {\r
+ throw new RuntimeException("Invalid direction: " + edge.getDirections());\r
+ }\r
+\r
+ BooleanQuery finalQuery = new BooleanQuery();\r
+\r
+ LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, TaxonBase.class);\r
+ QueryFactory taxonBaseQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonBase.class);\r
+\r
+ BooleanQuery joinFromQuery = new BooleanQuery();\r
+ joinFromQuery.add(taxonBaseQueryFactory.newTermQuery(queryTermField, queryString), Occur.MUST);\r
+ joinFromQuery.add(taxonBaseQueryFactory.newEntityIdQuery("type.id", edge.getTaxonRelationshipType()), Occur.MUST);\r
+ Query joinQuery = taxonBaseQueryFactory.newJoinQuery(fromField, toField, joinFromQuery, TaxonRelationship.class);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ luceneSearch.setSortFields(sortFields);\r
+\r
+ finalQuery.add(joinQuery, Occur.MUST);\r
+\r
+ if(classification != null){\r
+ finalQuery.add(taxonBaseQueryFactory.newEntityIdQuery("taxonNodes.classification.id", classification), Occur.MUST);\r
+ }\r
+ luceneSearch.setQuery(finalQuery);\r
+\r
+ if(highlightFragments){\r
+ luceneSearch.setHighlightFields(taxonBaseQueryFactory.getTextFieldNamesAsArray());\r
+ }\r
+ return luceneSearch;\r
+ }\r
+\r
+\r
+\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNamesByFullText(java.util.EnumSet, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.Set, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.Map)\r
+ */\r
+ @Override\r
+ public Pager<SearchResult<TaxonBase>> findTaxaAndNamesByFullText(\r
+ EnumSet<TaxaAndNamesSearchMode> searchModes, String queryString, Classification classification,\r
+ Set<NamedArea> namedAreas, Set<PresenceAbsenceTermBase<?>> distributionStatus, List<Language> languages,\r
+ boolean highlightFragments, Integer pageSize,\r
+ Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)\r
+ throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {\r
+\r
+ // FIXME: allow taxonomic ordering\r
+ // hql equivalent: order by t.name.genusOrUninomial, case when t.name.specificEpithet like '\"%\"' then 1 else 0 end, t.name.specificEpithet, t.name.rank desc, t.name.nameCache";\r
+ // this require building a special sort column by a special classBridge\r
+ if(highlightFragments){\r
+ logger.warn("findTaxaAndNamesByFullText() : fragment highlighting is " +\r
+ "currently not fully supported by this method and thus " +\r
+ "may not work with common names and misapplied names.");\r
+ }\r
+\r
+ // convert sets to lists\r
+ List<NamedArea> namedAreaList = null;\r
+ List<PresenceAbsenceTermBase<?>>distributionStatusList = null;\r
+ if(namedAreas != null){\r
+ namedAreaList = new ArrayList<NamedArea>(namedAreas.size());\r
+ namedAreaList.addAll(namedAreas);\r
+ }\r
+ if(distributionStatus != null){\r
+ distributionStatusList = new ArrayList<PresenceAbsenceTermBase<?>>(distributionStatus.size());\r
+ distributionStatusList.addAll(distributionStatus);\r
+ }\r
+\r
+ // set default if parameter is null\r
+ if(searchModes == null){\r
+ searchModes = EnumSet.of(TaxaAndNamesSearchMode.doTaxa);\r
+ }\r
+\r
+ boolean addDistributionFilter = namedAreas != null && namedAreas.size() > 0;\r
+\r
+ List<LuceneSearch> luceneSearches = new ArrayList<LuceneSearch>();\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+\r
+ /*\r
+ ======== filtering by distribution , HOWTO ========\r
+\r
+ - http://www.javaranch.com/journal/2009/02/filtering-a-lucene-search.html\r
+ - http://stackoverflow.com/questions/17709256/lucene-solr-using-complex-filters -> QueryWrapperFilter\r
+ add Filter to search as http://lucene.apache.org/core/3_6_0/api/all/org/apache/lucene/search/Filter.html\r
+ which will be put into a FilteredQuersy in the end ?\r
+\r
+\r
+ 3. how does it work in spatial?\r
+ see\r
+ - http://www.nsshutdown.com/projects/lucene/whitepaper/locallucene_v2.html\r
+ - http://www.infoq.com/articles/LuceneSpatialSupport\r
+ - http://www.mhaller.de/archives/156-Spatial-search-with-Lucene.html\r
+ ------------------------------------------------------------------------\r
+\r
+ filter strategies:\r
+ A) use a separate distribution filter per index sub-query/search:\r
+ - byTaxonSyonym (query TaxaonBase):\r
+ use a join area filter (Distribution -> TaxonBase)\r
+ - byCommonName (query DescriptionElementBase): use an area filter on\r
+ DescriptionElementBase !!! PROBLEM !!!\r
+ This cannot work since the distributions are different entities than the\r
+ common names and thus these are different lucene documents.\r
+ - byMisaplliedNames (join query TaxonRelationship -> TaxaonBase):\r
+ use a join area filter (Distribution -> TaxonBase)\r
+\r
+ B) use a common distribution filter for all index sub-query/searches:\r
+ - use a common join area filter (Distribution -> TaxonBase)\r
+ - also implement the byCommonName as join query (CommonName -> TaxonBase)\r
+ PROBLEM in this case: we are losing the fragment highlighting for the\r
+ common names, since the returned documents are always TaxonBases\r
+ */\r
+\r
+ /* The QueryFactory for creating filter queries on Distributions should\r
+ * The query factory used for the common names query cannot be reused\r
+ * for this case, since we want to only record the text fields which are\r
+ * actually used in the primary query\r
+ */\r
+ QueryFactory distributionFilterQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(Distribution.class);\r
+\r
+ BooleanFilter multiIndexByAreaFilter = new BooleanFilter();\r
+\r
+\r
+ // search for taxa or synonyms\r
+ if(searchModes.contains(TaxaAndNamesSearchMode.doTaxa) || searchModes.contains(TaxaAndNamesSearchMode.doSynonyms)) {\r
+ Class taxonBaseSubclass = TaxonBase.class;\r
+ if(searchModes.contains(TaxaAndNamesSearchMode.doTaxa) && !searchModes.contains(TaxaAndNamesSearchMode.doSynonyms)){\r
+ taxonBaseSubclass = Taxon.class;\r
+ } else if (!searchModes.contains(TaxaAndNamesSearchMode.doTaxa) && searchModes.contains(TaxaAndNamesSearchMode.doSynonyms)) {\r
+ taxonBaseSubclass = Synonym.class;\r
+ }\r
+ luceneSearches.add(prepareFindByFullTextSearch(taxonBaseSubclass, queryString, classification, languages, highlightFragments));\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+ /* A) does not work!!!!\r
+ if(addDistributionFilter){\r
+ // in this case we need a filter which uses a join query\r
+ // to get the TaxonBase documents for the DescriptionElementBase documents\r
+ // which are matching the areas in question\r
+ Query taxonAreaJoinQuery = createByDistributionJoinQuery(\r
+ namedAreaList,\r
+ distributionStatusList,\r
+ distributionFilterQueryFactory\r
+ );\r
+ multiIndexByAreaFilter.add(new QueryWrapperFilter(taxonAreaJoinQuery), Occur.SHOULD);\r
+ }\r
+ */\r
+ if(addDistributionFilter && searchModes.contains(TaxaAndNamesSearchMode.doSynonyms)){\r
+ // add additional area filter for synonyms\r
+ String fromField = "inDescription.taxon.id"; // in DescriptionElementBase index\r
+ String toField = "accTaxon.id"; // id in TaxonBase index\r
+\r
+ BooleanQuery byDistributionQuery = createByDistributionQuery(namedAreaList, distributionStatusList, distributionFilterQueryFactory);\r
+\r
+ Query taxonAreaJoinQuery = distributionFilterQueryFactory.newJoinQuery(fromField, toField, byDistributionQuery, Distribution.class);\r
+ multiIndexByAreaFilter.add(new QueryWrapperFilter(taxonAreaJoinQuery), Occur.SHOULD);\r
+\r
+ }\r
+ }\r
+\r
+ // search by CommonTaxonName\r
+ if(searchModes.contains(TaxaAndNamesSearchMode.doTaxaByCommonNames)) {\r
+ // B)\r
+ QueryFactory descriptionElementQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(DescriptionElementBase.class);\r
+ Query byCommonNameJoinQuery = descriptionElementQueryFactory.newJoinQuery(\r
+ "inDescription.taxon.id",\r
+ "id",\r
+ QueryFactory.addTypeRestriction(\r
+ createByDescriptionElementFullTextQuery(queryString, classification, null, languages, descriptionElementQueryFactory)\r
+ , CommonTaxonName.class\r
+ ),\r
+ CommonTaxonName.class);\r
+ logger.debug("byCommonNameJoinQuery: " + byCommonNameJoinQuery.toString());\r
+ LuceneSearch byCommonNameSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, Taxon.class);\r
+ byCommonNameSearch.setCdmTypRestriction(Taxon.class);\r
+ byCommonNameSearch.setQuery(byCommonNameJoinQuery);\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+\r
+ luceneSearches.add(byCommonNameSearch);\r
+\r
+ /* A) does not work!!!!\r
+ luceneSearches.add(\r
+ prepareByDescriptionElementFullTextSearch(CommonTaxonName.class,\r
+ queryString, classification, null, languages, highlightFragments)\r
+ );\r
+ idFieldMap.put(CdmBaseType.DESCRIPTION_ELEMENT, "inDescription.taxon.id");\r
+ if(addDistributionFilter){\r
+ // in this case we are able to use DescriptionElementBase documents\r
+ // which are matching the areas in question directly\r
+ BooleanQuery byDistributionQuery = createByDistributionQuery(\r
+ namedAreaList,\r
+ distributionStatusList,\r
+ distributionFilterQueryFactory\r
+ );\r
+ multiIndexByAreaFilter.add(new QueryWrapperFilter(byDistributionQuery), Occur.SHOULD);\r
+ } */\r
+ }\r
+\r
+ // search by misapplied names\r
+ if(searchModes.contains(TaxaAndNamesSearchMode.doMisappliedNames)) {\r
+ // NOTE:\r
+ // prepareFindByTaxonRelationFullTextSearch() is making use of JoinUtil.createJoinQuery()\r
+ // which allows doing query time joins\r
+ // finds the misapplied name (Taxon B) which is an misapplication for\r
+ // a related Taxon A.\r
+ //\r
+ luceneSearches.add(prepareFindByTaxonRelationFullTextSearch(\r
+ new TaxonRelationshipEdge(TaxonRelationshipType.MISAPPLIED_NAME_FOR(), Direction.relatedTo),\r
+ queryString, classification, languages, highlightFragments));\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+\r
+ if(addDistributionFilter){\r
+ String fromField = "inDescription.taxon.id"; // in DescriptionElementBase index\r
+\r
+ /*\r
+ * Here i was facing wired and nasty bug which took me bugging be really for hours until I found this solution.\r
+ * Maybe this is a but in java itself java.\r
+ *\r
+ * When the string toField is constructed by using the expression TaxonRelationshipType.MISAPPLIED_NAME_FOR().getUuid().toString()\r
+ * directly:\r
+ *\r
+ * String toField = "relation." + TaxonRelationshipType.MISAPPLIED_NAME_FOR().getUuid().toString() +".to.id";\r
+ *\r
+ * The byDistributionQuery fails, however when the uuid is first stored in another string variable the query\r
+ * will execute as expected:\r
+ *\r
+ * String misappliedNameForUuid = TaxonRelationshipType.MISAPPLIED_NAME_FOR().getUuid().toString();\r
+ * String toField = "relation." + misappliedNameForUuid +".to.id";\r
+ *\r
+ * Comparing both strings by the String.equals method returns true, so both String are identical.\r
+ *\r
+ * The bug occurs when running eu.etaxonomy.cdm.api.service.TaxonServiceSearchTest in eclipse and in maven and seems to to be\r
+ * dependent from a specific jvm (openjdk6 6b27-1.12.6-1ubuntu0.13.04.2, openjdk7 7u25-2.3.10-1ubuntu0.13.04.2, oracle jdk1.7.0_25 tested)\r
+ * The bug is persistent after a reboot of the development computer.\r
+ */\r
+// String misappliedNameForUuid = TaxonRelationshipType.MISAPPLIED_NAME_FOR().getUuid().toString();\r
+// String toField = "relation." + misappliedNameForUuid +".to.id";\r
+ String toField = "relation.1ed87175-59dd-437e-959e-0d71583d8417.to.id";\r
+// System.out.println("relation.1ed87175-59dd-437e-959e-0d71583d8417.to.id".equals("relation." + misappliedNameForUuid +".to.id") ? " > identical" : " > different");\r
+// System.out.println("relation.1ed87175-59dd-437e-959e-0d71583d8417.to.id".equals("relation." + TaxonRelationshipType.MISAPPLIED_NAME_FOR().getUuid().toString() +".to.id") ? " > identical" : " > different");\r
+\r
+ BooleanQuery byDistributionQuery = createByDistributionQuery(namedAreaList, distributionStatusList, distributionFilterQueryFactory);\r
+ Query taxonAreaJoinQuery = distributionFilterQueryFactory.newJoinQuery(fromField, toField, byDistributionQuery, Distribution.class);\r
+ QueryWrapperFilter filter = new QueryWrapperFilter(taxonAreaJoinQuery);\r
+\r
+// debug code for bug described above\r
+ DocIdSet filterMatchSet = filter.getDocIdSet(luceneIndexToolProvider.getIndexReaderFor(Taxon.class));\r
+// System.err.println(DocIdBitSetPrinter.docsAsString(filterMatchSet, 100));\r
+\r
+ multiIndexByAreaFilter.add(filter, Occur.SHOULD);\r
+ }\r
+ }\r
+\r
+ LuceneMultiSearch multiSearch = new LuceneMultiSearch(luceneIndexToolProvider,\r
+ luceneSearches.toArray(new LuceneSearch[luceneSearches.size()]));\r
+\r
+\r
+ if(addDistributionFilter){\r
+\r
+ // B)\r
+ // in this case we need a filter which uses a join query\r
+ // to get the TaxonBase documents for the DescriptionElementBase documents\r
+ // which are matching the areas in question\r
+ //\r
+ // for toTaxa, doByCommonName\r
+ Query taxonAreaJoinQuery = createByDistributionJoinQuery(\r
+ namedAreaList,\r
+ distributionStatusList,\r
+ distributionFilterQueryFactory\r
+ );\r
+ multiIndexByAreaFilter.add(new QueryWrapperFilter(taxonAreaJoinQuery), Occur.SHOULD);\r
+ }\r
+\r
+ if (addDistributionFilter){\r
+ multiSearch.setFilter(multiIndexByAreaFilter);\r
+ }\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = multiSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ // --- initialize taxa, highlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(multiSearch, multiSearch.getQuery());\r
+\r
+\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, multiSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+ }\r
+\r
+ /**\r
+ * @param namedAreaList at least one area must be in the list\r
+ * @param distributionStatusList optional\r
+ * @return\r
+ * @throws IOException\r
+ */\r
+ protected Query createByDistributionJoinQuery(\r
+ List<NamedArea> namedAreaList,\r
+ List<PresenceAbsenceTermBase<?>> distributionStatusList,\r
+ QueryFactory queryFactory\r
+ ) throws IOException {\r
+\r
+ String fromField = "inDescription.taxon.id"; // in DescriptionElementBase index\r
+ String toField = "id"; // id in TaxonBase index\r
+\r
+ BooleanQuery byDistributionQuery = createByDistributionQuery(namedAreaList, distributionStatusList, queryFactory);\r
+\r
+ Query taxonAreaJoinQuery = queryFactory.newJoinQuery(fromField, toField, byDistributionQuery, Distribution.class);\r
+\r
+ return taxonAreaJoinQuery;\r
+ }\r
+\r
+ /**\r
+ * @param namedAreaList\r
+ * @param distributionStatusList\r
+ * @param queryFactory\r
+ * @return\r
+ */\r
+ private BooleanQuery createByDistributionQuery(List<NamedArea> namedAreaList,\r
+ List<PresenceAbsenceTermBase<?>> distributionStatusList, QueryFactory queryFactory) {\r
+ BooleanQuery areaQuery = new BooleanQuery();\r
+ // area field from Distribution\r
+ areaQuery.add(queryFactory.newEntityIdsQuery("area.id", namedAreaList), Occur.MUST);\r
+\r
+ // status field from Distribution\r
+ if(distributionStatusList != null && distributionStatusList.size() > 0){\r
+ areaQuery.add(queryFactory.newEntityIdsQuery("status.id", distributionStatusList), Occur.MUST);\r
+ }\r
+\r
+ logger.debug("createByDistributionQuery() query: " + areaQuery.toString());\r
+ return areaQuery;\r
+ }\r
+\r
+ /**\r
+ * This method has been primarily created for testing the area join query but might\r
+ * also be useful in other situations\r
+ *\r
+ * @param namedAreaList\r
+ * @param distributionStatusList\r
+ * @param classification\r
+ * @param highlightFragments\r
+ * @return\r
+ * @throws IOException\r
+ */\r
+ protected LuceneSearch prepareByDistributionSearch(\r
+ List<NamedArea> namedAreaList, List<PresenceAbsenceTermBase<?>> distributionStatusList,\r
+ Classification classification) throws IOException {\r
+\r
+ BooleanQuery finalQuery = new BooleanQuery();\r
+\r
+ LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, Taxon.class);\r
+\r
+ // FIXME is this query factory using the wrong type?\r
+ QueryFactory taxonQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(Taxon.class);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ luceneSearch.setSortFields(sortFields);\r
+\r
+\r
+ Query byAreaQuery = createByDistributionJoinQuery(namedAreaList, distributionStatusList, taxonQueryFactory);\r
+\r
+ finalQuery.add(byAreaQuery, Occur.MUST);\r
+\r
+ if(classification != null){\r
+ finalQuery.add(taxonQueryFactory.newEntityIdQuery("taxonNodes.classification.id", classification), Occur.MUST);\r
+ }\r
+\r
+ logger.info("prepareByAreaSearch() query: " + finalQuery.toString());\r
+ luceneSearch.setQuery(finalQuery);\r
+\r
+ return luceneSearch;\r
+ }\r
+\r
+\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findByDescriptionElementFullText(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.List, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\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
+ 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
+\r
+ LuceneSearch luceneSearch = prepareByDescriptionElementFullTextSearch(clazz, queryString, classification, features, languages, highlightFragments);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.DESCRIPTION_ELEMENT, "inDescription.taxon.id");\r
+\r
+ // --- initialize taxa, highlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());\r
+ @SuppressWarnings("rawtypes")\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+\r
+ }\r
+\r
+\r
+ @Override\r
+ public Pager<SearchResult<TaxonBase>> findByEverythingFullText(String queryString,\r
+ Classification classification, List<Language> languages, boolean highlightFragments,\r
+ Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {\r
+\r
+ LuceneSearch luceneSearchByDescriptionElement = prepareByDescriptionElementFullTextSearch(null, queryString, classification, null, languages, highlightFragments);\r
+ LuceneSearch luceneSearchByTaxonBase = prepareFindByFullTextSearch(null, queryString, classification, languages, highlightFragments);\r
+\r
+ LuceneMultiSearch multiSearch = new LuceneMultiSearch(luceneIndexToolProvider, luceneSearchByDescriptionElement, luceneSearchByTaxonBase);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = multiSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ // --- initialize taxa, highlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(multiSearch, multiSearch.getQuery());\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+ idFieldMap.put(CdmBaseType.DESCRIPTION_ELEMENT, "inDescription.taxon.id");\r
+\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, multiSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+\r
+ }\r
+\r
+\r
+ /**\r
+ * @param clazz\r
+ * @param queryString\r
+ * @param classification\r
+ * @param features\r
+ * @param languages\r
+ * @param highlightFragments\r
+ * @param directorySelectClass\r
+ * @return\r
+ */\r
+ protected LuceneSearch prepareByDescriptionElementFullTextSearch(Class<? extends CdmBase> clazz,\r
+ String queryString, Classification classification, List<Feature> features,\r
+ List<Language> languages, boolean highlightFragments) {\r
+\r
+ LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, DescriptionElementBase.class);\r
+ QueryFactory descriptionElementQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(DescriptionElementBase.class);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("inDescription.taxon.titleCache__sort", SortField.STRING, false)};\r
+\r
+ BooleanQuery finalQuery = createByDescriptionElementFullTextQuery(queryString, classification, features,\r
+ languages, descriptionElementQueryFactory);\r
\r
- Class<? extends DescriptionElementBase> directorySelectClass = DescriptionElementBase.class;\r
- if(clazz != null){\r
- directorySelectClass = clazz;\r
+ luceneSearch.setSortFields(sortFields);\r
+ luceneSearch.setCdmTypRestriction(clazz);\r
+ luceneSearch.setQuery(finalQuery);\r
+ if(highlightFragments){\r
+ luceneSearch.setHighlightFields(descriptionElementQueryFactory.getTextFieldNamesAsArray());\r
}\r
\r
- StringBuilder luceneQueryTemplate = new StringBuilder();\r
+ return luceneSearch;\r
+ }\r
+\r
+ /**\r
+ * @param queryString\r
+ * @param classification\r
+ * @param features\r
+ * @param languages\r
+ * @param descriptionElementQueryFactory\r
+ * @return\r
+ */\r
+ private BooleanQuery createByDescriptionElementFullTextQuery(String queryString, Classification classification,\r
+ List<Feature> features, List<Language> languages, QueryFactory descriptionElementQueryFactory) {\r
+ BooleanQuery finalQuery = new BooleanQuery();\r
+ BooleanQuery textQuery = new BooleanQuery();\r
+ textQuery.add(descriptionElementQueryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
\r
- luceneQueryTemplate.append("titleCache:%1$s ");\r
// common name\r
+ Query nameQuery;\r
if(languages == null || languages.size() == 0){\r
- luceneQueryTemplate.append("name:%1$s ");\r
+ nameQuery = descriptionElementQueryFactory.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.uuid:" + lang.getUuid().toString());\r
+ languageSubQuery.add(descriptionElementQueryFactory.newTermQuery("language.uuid", lang.getUuid().toString(), false), Occur.SHOULD);\r
}\r
- luceneQueryTemplate.append("))");\r
+ ((BooleanQuery) nameQuery).add(descriptionElementQueryFactory.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(descriptionElementQueryFactory.newMultilanguageTextQuery("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(descriptionElementQueryFactory.newDefinedTermQuery("stateData.state", queryString, languages), Occur.SHOULD);\r
+\r
// state field from CategoricalData\r
- appendLocalizedFieldQuery("states.modifyingText", languages, luceneQueryTemplate).append(" ");\r
+ textQuery.add(descriptionElementQueryFactory.newDefinedTermQuery("stateData.modifyingText", queryString, languages), Occur.SHOULD);\r
+\r
+ // area field from Distribution\r
+ textQuery.add(descriptionElementQueryFactory.newDefinedTermQuery("area", 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
+ // status field from Distribution\r
+ textQuery.add(descriptionElementQueryFactory.newDefinedTermQuery("status", queryString, languages), Occur.SHOULD);\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
+ finalQuery.add(textQuery, Occur.MUST);\r
+ // --- classification ----\r
\r
- return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, searchResults.size(), pageSize, searchResults);\r
+ if(classification != null){\r
+ finalQuery.add(descriptionElementQueryFactory.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(descriptionElementQueryFactory.newEntityUuidsQuery("feature.uuid", features), Occur.MUST);\r
+ }\r
+\r
+ // the description must be associated with a taxon\r
+ finalQuery.add(descriptionElementQueryFactory.newIsNotNullQuery("inDescription.taxon.id"), Occur.MUST);\r
+\r
+ logger.info("prepareByDescriptionElementFullTextSearch() query: " + finalQuery.toString());\r
+ return finalQuery;\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.getUuid().toString() + ":%1$s ");\r
+ stringBuilder.append(name + "." + lang.getUuid().toString() + ":(%1$s) ");\r
}\r
}\r
return stringBuilder;\r
}\r
\r
+ @Override\r
public List<Synonym> createInferredSynonyms(Taxon taxon, Classification classification, SynonymRelationshipType type, boolean doWithMisappliedNames){\r
List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\r
List<Synonym> inferredSynonymsToBeRemoved = new ArrayList<Synonym>();\r
HashMap <UUID, ZoologicalName> zooHashMap = new HashMap<UUID, ZoologicalName>();\r
\r
\r
- UUID uuid= taxon.getName().getUuid();\r
- ZoologicalName taxonName = getZoologicalName(uuid, zooHashMap);\r
+ UUID nameUuid= taxon.getName().getUuid();\r
+ ZoologicalName taxonName = getZoologicalName(nameUuid, zooHashMap);\r
String epithetOfTaxon = null;\r
String infragenericEpithetOfTaxon = null;\r
String infraspecificEpithetOfTaxon = null;\r
\r
if (node.getClassification().equals(classification)){\r
if (!node.isTopmostNode()){\r
- TaxonNode parent = (TaxonNode)node.getParent();\r
+ TaxonNode parent = node.getParent();\r
parent = (TaxonNode)HibernateProxyHelper.deproxy(parent);\r
- TaxonNameBase parentName = parent.getTaxon().getName();\r
+ TaxonNameBase<?,?> parentName = parent.getTaxon().getName();\r
ZoologicalName zooParentName = HibernateProxyHelper.deproxy(parentName, ZoologicalName.class);\r
Taxon parentTaxon = (Taxon)HibernateProxyHelper.deproxy(parent.getTaxon());\r
Rank rankOfTaxon = taxonName.getRank();\r
\r
\r
if (type.equals(SynonymRelationshipType.INFERRED_EPITHET_OF())){\r
- Set<String> genusNames = new HashSet<String>();\r
+\r
\r
for (SynonymRelationship synonymRelationOfParent:synonymRelationshipsOfParent){\r
Synonym syn = synonymRelationOfParent.getSynonym();\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
- sourceReference = taxon.getSec();\r
- }\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
+ if (!parentSynZooName.getTaxa().isEmpty()){\r
+ TaxonBase taxon = parentSynZooName.getTaxa().iterator().next();\r
+\r
+ sourceReference = taxon.getSec();\r
+ }\r
+ }\r
String synTaxonSpecificEpithet = zooSynName.getSpecificEpithet();\r
\r
String synTaxonInfraSpecificName= null;\r
/*if (epithetName != null && !synonymsEpithet.contains(epithetName)){\r
synonymsEpithet.add(epithetName);\r
}*/\r
- \r
+\r
//create potential combinations...\r
inferredSynName = ZoologicalName.NewInstance(syn.getName().getRank());\r
\r
String idInSourceSyn= getIdInSource(syn);\r
\r
if (idInSourceParent != null && idInSourceSyn != null) {\r
- IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSourceSyn + "; " + idInSourceParent, POTENTIAL_COMBINATION_NAMESPACE, sourceReference, null);\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, idInSourceSyn + "; " + idInSourceParent, POTENTIAL_COMBINATION_NAMESPACE, sourceReference, null);\r
inferredSynName.addSource(originalSource);\r
- originalSource = IdentifiableSource.NewInstance(idInSourceSyn + "; " + idInSourceParent, POTENTIAL_COMBINATION_NAMESPACE, sourceReference, null);\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, idInSourceSyn + "; " + idInSourceParent, POTENTIAL_COMBINATION_NAMESPACE, sourceReference, null);\r
potentialCombination.addSource(originalSource);\r
}\r
\r
}\r
\r
private Synonym createInferredGenus(Taxon taxon,\r
- HashMap<UUID, ZoologicalName> zooHashMap, ZoologicalName taxonName,\r
- String epithetOfTaxon, String genusOfTaxon,\r
- List<String> taxonNames, ZoologicalName zooParentName,\r
- TaxonBase syn) {\r
- \r
- Synonym inferredGenus;\r
- TaxonNameBase synName;\r
- ZoologicalName inferredSynName;\r
- synName =syn.getName();\r
- HibernateProxyHelper.deproxy(syn);\r
-\r
- // Determine the idInSource\r
- String idInSourceSyn = getIdInSource(syn);\r
- String idInSourceTaxon = getIdInSource(taxon);\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
+ HashMap<UUID, ZoologicalName> zooHashMap, ZoologicalName taxonName,\r
+ String epithetOfTaxon, String genusOfTaxon,\r
+ List<String> taxonNames, ZoologicalName zooParentName,\r
+ TaxonBase syn) {\r
+\r
+ Synonym inferredGenus;\r
+ TaxonNameBase synName;\r
+ ZoologicalName inferredSynName;\r
+ synName =syn.getName();\r
+ HibernateProxyHelper.deproxy(syn);\r
+\r
+ // Determine the idInSource\r
+ String idInSourceSyn = getIdInSource(syn);\r
+ String idInSourceTaxon = getIdInSource(taxon);\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
/* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){\r
- synonymsEpithet.add(synSpeciesEpithetName);\r
- }*/\r
- \r
- inferredSynName = ZoologicalName.NewInstance(taxon.getName().getRank());\r
- //TODO:differ between parent is genus and taxon is species, parent is subgenus and taxon is species, parent is species and taxon is subspecies and parent is genus and taxon is subgenus...\r
+ synonymsEpithet.add(synSpeciesEpithetName);\r
+ }*/\r
\r
+ inferredSynName = ZoologicalName.NewInstance(taxon.getName().getRank());\r
+ //TODO:differ between parent is genus and taxon is species, parent is subgenus and taxon is species, parent is species and taxon is subspecies and parent is genus and taxon is subgenus...\r
\r
- inferredSynName.setGenusOrUninomial(genusOfTaxon);\r
- if (zooParentName.isInfraGeneric()){\r
- inferredSynName.setInfraGenericEpithet(zooParentName.getInfraGenericEpithet());\r
- }\r
- \r
- if (taxonName.isSpecies()){\r
- inferredSynName.setSpecificEpithet(synSpeciesEpithetName);\r
- }\r
- if (taxonName.isInfraSpecific()){\r
- inferredSynName.setSpecificEpithet(epithetOfTaxon);\r
- inferredSynName.setInfraSpecificEpithet(synZooName.getInfraGenericEpithet());\r
- }\r
- \r
- \r
- inferredGenus = Synonym.NewInstance(inferredSynName, null);\r
-\r
- // Set the sourceReference\r
- inferredGenus.setSec(sourceReference);\r
-\r
- // Add the original source\r
- if (idInSourceSyn != null && idInSourceTaxon != null) {\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
- }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
- \r
- inferredSynName.generateTitle();\r
- \r
- \r
- return inferredGenus;\r
- }\r
+ inferredSynName.setGenusOrUninomial(genusOfTaxon);\r
+ if (zooParentName.isInfraGeneric()){\r
+ inferredSynName.setInfraGenericEpithet(zooParentName.getInfraGenericEpithet());\r
+ }\r
+\r
+ if (taxonName.isSpecies()){\r
+ inferredSynName.setSpecificEpithet(synSpeciesEpithetName);\r
+ }\r
+ if (taxonName.isInfraSpecific()){\r
+ inferredSynName.setSpecificEpithet(epithetOfTaxon);\r
+ inferredSynName.setInfraSpecificEpithet(synZooName.getInfraGenericEpithet());\r
+ }\r
+\r
+\r
+ inferredGenus = Synonym.NewInstance(inferredSynName, null);\r
+\r
+ // Set the sourceReference\r
+ inferredGenus.setSec(sourceReference);\r
+\r
+ // Add the original source\r
+ if (idInSourceSyn != null && idInSourceTaxon != null) {\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ inferredGenus.addSource(originalSource);\r
+\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ 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(OriginalSourceType.Transformation,\r
+ idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ inferredGenus.addSource(originalSource);\r
+\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ 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
+\r
+ inferredSynName.generateTitle();\r
+\r
+\r
+ return inferredGenus;\r
+ }\r
\r
private Synonym createInferredEpithets(Taxon taxon,\r
- HashMap<UUID, ZoologicalName> zooHashMap, ZoologicalName taxonName,\r
- String epithetOfTaxon, String infragenericEpithetOfTaxon,\r
- String infraspecificEpithetOfTaxon, List<String> taxonNames,\r
- TaxonNameBase parentName, TaxonBase syn) {\r
- \r
- Synonym inferredEpithet;\r
- TaxonNameBase synName;\r
- ZoologicalName inferredSynName;\r
- HibernateProxyHelper.deproxy(syn);\r
-\r
- // Determine the idInSource\r
- String idInSourceSyn = getIdInSource(syn);\r
- String idInSourceTaxon = getIdInSource(taxon);\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
- String synInfraGenericEpithet = null;\r
- String synSpecificEpithet = null;\r
- \r
- if (zooSynName.getInfraGenericEpithet() != null){\r
- synInfraGenericEpithet = zooSynName.getInfraGenericEpithet();\r
- } \r
- \r
- if (zooSynName.isInfraSpecific()){\r
- synSpecificEpithet = zooSynName.getSpecificEpithet();\r
- } \r
- \r
+ HashMap<UUID, ZoologicalName> zooHashMap, ZoologicalName taxonName,\r
+ String epithetOfTaxon, String infragenericEpithetOfTaxon,\r
+ String infraspecificEpithetOfTaxon, List<String> taxonNames,\r
+ TaxonNameBase parentName, TaxonBase syn) {\r
+\r
+ Synonym inferredEpithet;\r
+ TaxonNameBase<?,?> synName;\r
+ ZoologicalName inferredSynName;\r
+ HibernateProxyHelper.deproxy(syn);\r
+\r
+ // Determine the idInSource\r
+ String idInSourceSyn = getIdInSource(syn);\r
+ String idInSourceTaxon = getIdInSource(taxon);\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" + 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
+ String synInfraGenericEpithet = null;\r
+ String synSpecificEpithet = null;\r
+\r
+ if (zooSynName.getInfraGenericEpithet() != null){\r
+ synInfraGenericEpithet = zooSynName.getInfraGenericEpithet();\r
+ }\r
+\r
+ if (zooSynName.isInfraSpecific()){\r
+ synSpecificEpithet = zooSynName.getSpecificEpithet();\r
+ }\r
+\r
/* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){\r
- synonymsGenus.put(synGenusName, idInSource);\r
- }*/\r
- \r
- inferredSynName = ZoologicalName.NewInstance(taxon.getName().getRank());\r
+ synonymsGenus.put(synGenusName, idInSource);\r
+ }*/\r
\r
- // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!\r
- if (epithetOfTaxon == null && infragenericEpithetOfTaxon == null && infraspecificEpithetOfTaxon == null) {\r
- logger.error("This specificEpithet is NULL" + taxon.getTitleCache());\r
- }\r
- inferredSynName.setGenusOrUninomial(synGenusName);\r
- \r
- if (parentName.isInfraGeneric()){\r
- inferredSynName.setInfraGenericEpithet(synInfraGenericEpithet);\r
- }\r
- if (taxonName.isSpecies()){\r
- inferredSynName.setSpecificEpithet(epithetOfTaxon);\r
- }else if (taxonName.isInfraSpecific()){\r
- inferredSynName.setSpecificEpithet(synSpecificEpithet);\r
- inferredSynName.setInfraSpecificEpithet(infraspecificEpithetOfTaxon);\r
- }\r
- \r
- inferredEpithet = Synonym.NewInstance(inferredSynName, null);\r
- \r
- // Set the sourceReference\r
- inferredEpithet.setSec(sourceReference);\r
-\r
- /* Add the original source\r
- if (idInSource != null) {\r
- IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);\r
-\r
- // Add the citation\r
- Reference citation = getCitation(syn);\r
- if (citation != null) {\r
- originalSource.setCitation(citation);\r
- inferredEpithet.addSource(originalSource);\r
- }\r
- }*/\r
- String taxonId = idInSourceTaxon+ "; " + idInSourceSyn;\r
- \r
- IdentifiableSource originalSource;\r
- originalSource = IdentifiableSource.NewInstance(taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
- \r
- inferredEpithet.addSource(originalSource);\r
- \r
- originalSource = IdentifiableSource.NewInstance(taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
- \r
- inferredSynName.addSource(originalSource);\r
- \r
- \r
- \r
- taxon.addSynonym(inferredEpithet, SynonymRelationshipType.INFERRED_EPITHET_OF());\r
- \r
- inferredSynName.generateTitle();\r
- return inferredEpithet;\r
+ inferredSynName = ZoologicalName.NewInstance(taxon.getName().getRank());\r
+\r
+ // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!\r
+ if (epithetOfTaxon == null && infragenericEpithetOfTaxon == null && infraspecificEpithetOfTaxon == null) {\r
+ logger.error("This specificEpithet is NULL" + taxon.getTitleCache());\r
+ }\r
+ inferredSynName.setGenusOrUninomial(synGenusName);\r
+\r
+ if (parentName.isInfraGeneric()){\r
+ inferredSynName.setInfraGenericEpithet(synInfraGenericEpithet);\r
+ }\r
+ if (taxonName.isSpecies()){\r
+ inferredSynName.setSpecificEpithet(epithetOfTaxon);\r
+ }else if (taxonName.isInfraSpecific()){\r
+ inferredSynName.setSpecificEpithet(synSpecificEpithet);\r
+ inferredSynName.setInfraSpecificEpithet(infraspecificEpithetOfTaxon);\r
+ }\r
+\r
+ inferredEpithet = Synonym.NewInstance(inferredSynName, null);\r
+\r
+ // Set the sourceReference\r
+ inferredEpithet.setSec(sourceReference);\r
+\r
+ /* Add the original source\r
+ if (idInSource != null) {\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);\r
+\r
+ // Add the citation\r
+ Reference citation = getCitation(syn);\r
+ if (citation != null) {\r
+ originalSource.setCitation(citation);\r
+ inferredEpithet.addSource(originalSource);\r
+ }\r
+ }*/\r
+ String taxonId = idInSourceTaxon+ "; " + idInSourceSyn;\r
+\r
+\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
+\r
+ inferredEpithet.addSource(originalSource);\r
+\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
+\r
+ inferredSynName.addSource(originalSource);\r
+\r
+\r
+\r
+ taxon.addSynonym(inferredEpithet, SynonymRelationshipType.INFERRED_EPITHET_OF());\r
+\r
+ inferredSynName.generateTitle();\r
+ return inferredEpithet;\r
}\r
\r
/**\r
count++;\r
}\r
} else if (sources.size() == 0){\r
- logger.warn("No idInSource for TaxonBase " + taxonBase.getUuid() + " - " + taxonBase.getTitleCache());\r
+ logger.warn("No idInSource for TaxonBase " + taxonBase.getUuid() + " - " + taxonBase.getTitleCache());\r
}\r
- \r
+\r
\r
return idInSource;\r
}\r
return citation;\r
}\r
\r
+ @Override\r
public List<Synonym> createAllInferredSynonyms(Taxon taxon, Classification tree, boolean doWithMisappliedNames){\r
List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\r
\r
return inferredSynonyms;\r
}\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)\r
+ */\r
+ @Override\r
+ public List<Classification> listClassifications(TaxonBase taxonBase, Integer limit, Integer start, List<String> propertyPaths) {\r
+\r
+ // TODO quickly implemented, create according dao !!!!\r
+ Set<TaxonNode> nodes = new HashSet<TaxonNode>();\r
+ Set<Classification> classifications = new HashSet<Classification>();\r
+ List<Classification> list = new ArrayList<Classification>();\r
+\r
+ if (taxonBase == null) {\r
+ return list;\r
+ }\r
+\r
+ taxonBase = load(taxonBase.getUuid());\r
+\r
+ if (taxonBase instanceof Taxon) {\r
+ nodes.addAll(((Taxon)taxonBase).getTaxonNodes());\r
+ } else {\r
+ for (Taxon taxon : ((Synonym)taxonBase).getAcceptedTaxa() ) {\r
+ nodes.addAll(taxon.getTaxonNodes());\r
+ }\r
+ }\r
+ for (TaxonNode node : nodes) {\r
+ classifications.add(node.getClassification());\r
+ }\r
+ list.addAll(classifications);\r
+ return list;\r
+ }\r
+\r
+\r
+\r
\r
\r
\r