\r
package eu.etaxonomy.cdm.api.service;\r
\r
+import java.io.IOException;\r
import java.util.ArrayList;\r
-import java.util.Comparator;\r
+import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.List;\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.BooleanClause.Occur;\r
+import org.apache.lucene.search.BooleanQuery;\r
+import org.apache.lucene.search.Query;\r
+import org.apache.lucene.search.SortField;\r
+import org.apache.lucene.search.TopDocs;\r
import org.springframework.beans.factory.annotation.Autowired;\r
import org.springframework.stereotype.Service;\r
import org.springframework.transaction.annotation.Propagation;\r
import org.springframework.transaction.annotation.Transactional;\r
\r
-import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;\r
import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.NameDeletionConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;\r
+import eu.etaxonomy.cdm.api.service.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.ISearchResultBuilder;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneSearch;\r
+import eu.etaxonomy.cdm.api.service.search.QueryFactory;\r
+import eu.etaxonomy.cdm.api.service.search.SearchResult;\r
+import eu.etaxonomy.cdm.api.service.search.SearchResultBuilder;\r
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
+import eu.etaxonomy.cdm.hibernate.search.DefinedTermBaseClassBridge;\r
+import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;\r
import eu.etaxonomy.cdm.model.common.CdmBase;\r
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
+import eu.etaxonomy.cdm.model.common.Language;\r
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;\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.DescriptionElementBase;\r
+import eu.etaxonomy.cdm.model.description.Feature;\r
+import eu.etaxonomy.cdm.model.description.IIdentificationKey;\r
+import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
+import eu.etaxonomy.cdm.model.description.TaxonInteraction;\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.name.HomotypicalGroup;\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.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.TaxonNode;\r
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\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.name.ITaxonNameDao;\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.strategy.cache.common.IIdentifiableEntityCacheStrategy;\r
\r
\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
+ public static final String POTENTIAL_COMBINATION_NAMESPACE = "Potential combination";\r
\r
- @Autowired\r
- private IOrderedTermVocabularyDao orderedVocabularyDao;\r
+ public static final String INFERRED_EPITHET_NAMESPACE = "Inferred epithet";\r
\r
- @Autowired\r
- private INameService nameService;\r
- \r
- /**\r
- * Constructor\r
- */\r
- public TaxonServiceImpl(){\r
- if (logger.isDebugEnabled()) { logger.debug("Load TaxonService Bean"); }\r
- }\r
+ public static final String INFERRED_GENUS_NAMESPACE = "Inferred genus";\r
+\r
+\r
+ @Autowired\r
+ private ITaxonNameDao nameDao;\r
+\r
+ @Autowired\r
+ private INameService nameService;\r
+\r
+ @Autowired\r
+ private ICdmGenericDao genericDao;\r
+\r
+ @Autowired\r
+ private IDescriptionService descriptionService;\r
+\r
+ @Autowired\r
+ private IOrderedTermVocabularyDao orderedVocabularyDao;\r
+\r
+ /**\r
+ * Constructor\r
+ */\r
+ public TaxonServiceImpl(){\r
+ if (logger.isDebugEnabled()) { logger.debug("Load TaxonService Bean"); }\r
+ }\r
\r
/**\r
* FIXME Candidate for harmonization\r
return taxonRelTypeVocabulary;\r
}\r
\r
- \r
- \r
- /*\r
- * (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)\r
- */\r
- @Transactional(readOnly = false)\r
- public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){\r
- \r
- TaxonNameBase<?,?> synonymName = synonym.getName();\r
- synonymName.removeTaxonBase(synonym);\r
- TaxonNameBase<?,?> taxonName = acceptedTaxon.getName();\r
- taxonName.removeTaxonBase(acceptedTaxon);\r
- \r
- synonym.setName(taxonName);\r
- acceptedTaxon.setName(synonymName);\r
- \r
- // the accepted taxon needs a new uuid because the concept has changed\r
- // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"\r
- //acceptedTaxon.setUuid(UUID.randomUUID());\r
- }\r
-\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
- @Override\r
- @Transactional(readOnly = false)\r
- public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, boolean deleteSynonym, boolean copyCitationInfo, Reference citation, String microCitation) throws IllegalArgumentException{\r
- \r
- TaxonNameBase<?,?> acceptedName = acceptedTaxon.getName();\r
- TaxonNameBase<?,?> synonymName = synonym.getName();\r
- HomotypicalGroup synonymHomotypicGroup = synonymName.getHomotypicalGroup();\r
- \r
- //check synonym is not homotypic\r
- if (acceptedName.getHomotypicalGroup().equals(synonymHomotypicGroup)){\r
- String message = "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";\r
- throw new IllegalArgumentException(message);\r
- }\r
- \r
- Taxon newAcceptedTaxon = Taxon.NewInstance(synonymName, acceptedTaxon.getSec());\r
- \r
- SynonymRelationshipType relTypeForGroup = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();\r
- List<Synonym> heteroSynonyms = acceptedTaxon.getSynonymsInGroup(synonymHomotypicGroup);\r
- \r
- for (Synonym heteroSynonym : heteroSynonyms){\r
- if (synonym.equals(heteroSynonym)){\r
- acceptedTaxon.removeSynonym(heteroSynonym, false);\r
- }else{\r
- //move synonyms in same homotypic group to new accepted taxon\r
- heteroSynonym.replaceAcceptedTaxon(newAcceptedTaxon, relTypeForGroup, copyCitationInfo, citation, microCitation);\r
- }\r
- }\r
-\r
- //synonym.getName().removeTaxonBase(synonym);\r
- //TODO correct delete handling still needs to be implemented / checked\r
- if (deleteSynonym){\r
+\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)\r
+ */\r
+ @Transactional(readOnly = false)\r
+ public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){\r
+\r
+ TaxonNameBase<?,?> synonymName = synonym.getName();\r
+ synonymName.removeTaxonBase(synonym);\r
+ TaxonNameBase<?,?> taxonName = acceptedTaxon.getName();\r
+ taxonName.removeTaxonBase(acceptedTaxon);\r
+\r
+ synonym.setName(taxonName);\r
+ acceptedTaxon.setName(synonymName);\r
+\r
+ // the accepted taxon needs a new uuid because the concept has changed\r
+ // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"\r
+ //acceptedTaxon.setUuid(UUID.randomUUID());\r
+ }\r
+\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
+ @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
+ TaxonNameBase<?,?> acceptedName = acceptedTaxon.getName();\r
+ TaxonNameBase<?,?> synonymName = synonym.getName();\r
+ HomotypicalGroup synonymHomotypicGroup = synonymName.getHomotypicalGroup();\r
+\r
+ //check synonym is not homotypic\r
+ if (acceptedName.getHomotypicalGroup().equals(synonymHomotypicGroup)){\r
+ String message = "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";\r
+ throw new HomotypicalGroupChangeException(message);\r
+ }\r
+\r
+ Taxon newAcceptedTaxon = Taxon.NewInstance(synonymName, acceptedTaxon.getSec());\r
+\r
+ SynonymRelationshipType relTypeForGroup = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();\r
+ List<Synonym> heteroSynonyms = acceptedTaxon.getSynonymsInGroup(synonymHomotypicGroup);\r
+\r
+ for (Synonym heteroSynonym : heteroSynonyms){\r
+ if (synonym.equals(heteroSynonym)){\r
+ acceptedTaxon.removeSynonym(heteroSynonym, false);\r
+ }else{\r
+ //move synonyms in same homotypic group to new accepted taxon\r
+ heteroSynonym.replaceAcceptedTaxon(newAcceptedTaxon, relTypeForGroup, copyCitationInfo, citation, microCitation);\r
+ }\r
+ }\r
+\r
+ //synonym.getName().removeTaxonBase(synonym);\r
+ //TODO correct delete handling still needs to be implemented / checked\r
+ if (deleteSynonym){\r
// deleteSynonym(synonym, taxon, false);\r
- try {\r
- this.dao.flush();\r
- this.delete(synonym);\r
- \r
- } catch (Exception e) {\r
- logger.info("Can't delete old synonym from database");\r
- }\r
- }\r
- \r
- return newAcceptedTaxon;\r
- }\r
- \r
- \r
- public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, Reference citation, String microcitation){\r
- \r
- // Get name from synonym\r
- TaxonNameBase<?, ?> synonymName = synonym.getName();\r
- \r
- // remove synonym from taxon\r
- toTaxon.removeSynonym(synonym);\r
- \r
- // Create a taxon with synonym name\r
- Taxon fromTaxon = Taxon.NewInstance(synonymName, null);\r
- \r
- // Add taxon relation \r
- fromTaxon.addTaxonRelation(toTaxon, taxonRelationshipType, citation, microcitation);\r
- \r
- // since we are swapping names, we have to detach the name from the synonym completely. \r
- // Otherwise the synonym will still be in the list of typified names.\r
- synonym.getName().removeTaxonBase(synonym);\r
- \r
- return fromTaxon;\r
- }\r
- \r
+ try {\r
+ this.dao.flush();\r
+ this.delete(synonym);\r
+\r
+ } catch (Exception e) {\r
+ logger.info("Can't delete old synonym from database");\r
+ }\r
+ }\r
+\r
+ return newAcceptedTaxon;\r
+ }\r
+\r
+\r
+ public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, Reference citation, String microcitation){\r
+\r
+ // Get name from synonym\r
+ TaxonNameBase<?, ?> synonymName = synonym.getName();\r
+\r
+ // remove synonym from taxon\r
+ toTaxon.removeSynonym(synonym);\r
+\r
+ // Create a taxon with synonym name\r
+ Taxon fromTaxon = Taxon.NewInstance(synonymName, null);\r
+\r
+ // Add taxon relation\r
+ fromTaxon.addTaxonRelation(toTaxon, taxonRelationshipType, citation, microcitation);\r
+\r
+ // since we are swapping names, we have to detach the name from the synonym completely.\r
+ // Otherwise the synonym will still be in the list of typified names.\r
+ synonym.getName().removeTaxonBase(synonym);\r
+\r
+ return fromTaxon;\r
+ }\r
+\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#changeHomotypicalGroupOfSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.name.HomotypicalGroup, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)\r
* @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)\r
*/\r
@Override\r
+ @Transactional(readOnly = false)\r
public void updateTitleCache(Class<? extends TaxonBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<TaxonBase> cacheStrategy, IProgressMonitor monitor) {\r
if (clazz == null){\r
clazz = TaxonBase.class;\r
*/\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
- List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();\r
- if(numberOfResults > 0) { // no point checking again\r
- results = dao.getSynonyms(synonym, type, pageSize, pageNumber, orderHints, propertyPaths);\r
- }\r
+\r
+ List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();\r
+ if(numberOfResults > 0) { // no point checking again\r
+ results = dao.getSynonyms(synonym, type, pageSize, pageNumber, orderHints, propertyPaths);\r
+ }\r
\r
return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
- */\r
- public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){\r
- Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
- return t.getHomotypicSynonymsByHomotypicGroup();\r
- }\r
- \r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
- */\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
- List<List<Synonym>> heterotypicSynonymyGroups = new ArrayList<List<Synonym>>(homotypicalGroups.size());\r
- for(HomotypicalGroup homotypicalGroup : homotypicalGroups){\r
- heterotypicSynonymyGroups.add(t.getSynonymsInGroup(homotypicalGroup));\r
- }\r
- return heterotypicSynonymyGroups;\r
- }\r
-\r
- public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(ITaxonServiceConfigurator configurator){\r
- \r
- List<UuidAndTitleCache<TaxonBase>> result = new ArrayList<UuidAndTitleCache<TaxonBase>>();\r
- Class<? extends TaxonBase> clazz = null;\r
- if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {\r
- clazz = TaxonBase.class;\r
- //propertyPath.addAll(configurator.getTaxonPropertyPath());\r
- //propertyPath.addAll(configurator.getSynonymPropertyPath());\r
- } else if(configurator.isDoTaxa()) {\r
- clazz = Taxon.class;\r
- //propertyPath = configurator.getTaxonPropertyPath();\r
- } else if (configurator.isDoSynonyms()) {\r
- clazz = Synonym.class;\r
- //propertyPath = configurator.getSynonymPropertyPath();\r
- }\r
- \r
- \r
- result = dao.getTaxaByNameForEditor(clazz, configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
- return result;\r
- }\r
-\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
- \r
- List<IdentifiableEntity> results = new ArrayList<IdentifiableEntity>();\r
- int numberOfResults = 0; // overall number of results (as opposed to number of results per page)\r
- List<TaxonBase> taxa = null; \r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
+ */\r
+ public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){\r
+ Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
+ return t.getHomotypicSynonymsByHomotypicGroup();\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
+ */\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
+ List<List<Synonym>> heterotypicSynonymyGroups = new ArrayList<List<Synonym>>(homotypicalGroups.size());\r
+ for(HomotypicalGroup homotypicalGroup : homotypicalGroups){\r
+ heterotypicSynonymyGroups.add(t.getSynonymsInGroup(homotypicalGroup));\r
+ }\r
+ return heterotypicSynonymyGroups;\r
+ }\r
+\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
+// if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {\r
+// clazz = TaxonBase.class;\r
+// //propertyPath.addAll(configurator.getTaxonPropertyPath());\r
+// //propertyPath.addAll(configurator.getSynonymPropertyPath());\r
+// } else if(configurator.isDoTaxa()) {\r
+// clazz = Taxon.class;\r
+// //propertyPath = configurator.getTaxonPropertyPath();\r
+// } else if (configurator.isDoSynonyms()) {\r
+// clazz = Synonym.class;\r
+// //propertyPath = configurator.getSynonymPropertyPath();\r
+// }\r
+\r
+\r
+ result = dao.getTaxaByNameForEditor(configurator.isDoTaxa(), configurator.isDoSynonyms(), configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
+ return result;\r
+ }\r
+\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(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
+ List<TaxonBase> taxa = null;\r
\r
// Taxa and synonyms\r
long numberTaxaResults = 0L;\r
\r
- Class<? extends TaxonBase> clazz = null;\r
+\r
List<String> propertyPath = new ArrayList<String>();\r
if(configurator.getTaxonPropertyPath() != null){\r
propertyPath.addAll(configurator.getTaxonPropertyPath());\r
}\r
- if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {\r
- clazz = TaxonBase.class;\r
- //propertyPath.addAll(configurator.getTaxonPropertyPath());\r
- //propertyPath.addAll(configurator.getSynonymPropertyPath());\r
- } else if(configurator.isDoTaxa()) {\r
- clazz = Taxon.class;\r
- //propertyPath = configurator.getTaxonPropertyPath();\r
- } else if (configurator.isDoSynonyms()) {\r
- clazz = Synonym.class;\r
- //propertyPath = configurator.getSynonymPropertyPath();\r
- }\r
\r
- if(clazz != null){\r
+\r
+ if (configurator.isDoMisappliedNames() || configurator.isDoSynonyms() || configurator.isDoTaxa()){\r
if(configurator.getPageSize() != null){ // no point counting if we need all anyway\r
numberTaxaResults =\r
- dao.countTaxaByName(clazz,\r
+ dao.countTaxaByName(configurator.isDoTaxa(),configurator.isDoSynonyms(), configurator.isDoMisappliedNames(),\r
configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(),\r
configurator.getNamedAreas());\r
}\r
\r
if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){ // no point checking again if less results\r
- taxa = dao.getTaxaByName(clazz,\r
- configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(),\r
- configurator.getNamedAreas(), configurator.getPageSize(),\r
- configurator.getPageNumber(), propertyPath);\r
+ taxa = dao.getTaxaByName(configurator.isDoTaxa(), configurator.isDoSynonyms(),\r
+ configurator.isDoMisappliedNames(), configurator.getTitleSearchStringSqlized(), configurator.getClassification(),\r
+ configurator.getMatchMode(), configurator.getNamedAreas(),\r
+ configurator.getPageSize(), configurator.getPageNumber(), propertyPath);\r
}\r
- }\r
+ }\r
\r
if (logger.isDebugEnabled()) { logger.debug(numberTaxaResults + " matching taxa counted"); }\r
\r
// Taxa from common names\r
\r
if (configurator.isDoTaxaByCommonNames()) {\r
- taxa = null;\r
+ taxa = new ArrayList<TaxonBase>();\r
numberTaxaResults = 0;\r
if(configurator.getPageSize() != null){// no point counting if we need all anyway\r
numberTaxaResults = dao.countTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
}\r
if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){\r
- taxa = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());\r
+ List<Object[]> commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());\r
+ for( Object[] entry : commonNameResults ) {\r
+ taxa.add((TaxonBase) entry[0]);\r
+ }\r
}\r
if(taxa != null){\r
results.addAll(taxa);\r
return medRep;\r
}\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxonDescriptionMedia(eu.etaxonomy.cdm.model.taxon.Taxon, boolean)\r
+ */\r
+ public List<Media> listTaxonDescriptionMedia(Taxon taxon, boolean limitToGalleries, List<String> propertyPath){\r
+\r
+ Pager<TaxonDescription> p =\r
+ descriptionService.getTaxonDescriptions(taxon, null, null, null, null, propertyPath);\r
+\r
+ // pars the media and quality parameters\r
+\r
+\r
+ // collect all media of the given taxon\r
+ List<Media> taxonMedia = new ArrayList<Media>();\r
+ List<Media> taxonGalleryMedia = new ArrayList<Media>();\r
+ for(TaxonDescription desc : p.getRecords()){\r
+\r
+ if(desc.isImageGallery()){\r
+ for(DescriptionElementBase element : desc.getElements()){\r
+ for(Media media : element.getMedia()){\r
+ taxonGalleryMedia.add(media);\r
+ }\r
+ }\r
+ } else if(!limitToGalleries){\r
+ for(DescriptionElementBase element : desc.getElements()){\r
+ for(Media media : element.getMedia()){\r
+ taxonMedia.add(media);\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ taxonGalleryMedia.addAll(taxonMedia);\r
+ return taxonGalleryMedia;\r
+ }\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)\r
*/\r
return this.dao.findById(listOfIDs);\r
}\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)\r
+ */\r
+ public TaxonBase findTaxonByUuid(UUID uuid, List<String> propertyPaths){\r
+ return this.dao.findByUuid(uuid, null ,propertyPaths);\r
+ }\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()\r
*/\r
return this.dao.countAllRelationships();\r
}\r
\r
+\r
+\r
+\r
/* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#createAllInferredSynonyms(eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.model.taxon.Taxon)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)\r
*/\r
- public List<Synonym> createAllInferredSynonyms(Classification tree,\r
- Taxon taxon) {\r
-\r
- return this.dao.createAllInferredSynonyms(taxon, tree);\r
+ public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {\r
+ return this.dao.findIdenticalTaxonNames(propertyPath);\r
}\r
\r
+\r
/* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#createInferredSynonyms(eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)\r
*/\r
- public List<Synonym> createInferredSynonyms(Classification tree, Taxon taxon, SynonymRelationshipType type) {\r
+ @Override\r
+ public void deleteTaxon(Taxon taxon, TaxonDeletionConfigurator config) throws ReferencedObjectUndeletableException {\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
+ for (SynonymRelationship synRel : taxon.getSynonymRelations()){\r
+ Synonym synonym = synRel.getSynonym();\r
+ taxon.removeSynonymRelation(synRel, removeSynonymNameFromHomotypicalGroup);\r
+ if (config.isDeleteSynonymsIfPossible()){\r
+ //TODO which value\r
+ boolean newHomotypicGroupIfNeeded = true;\r
+ deleteSynonym(synonym, taxon, config.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded);\r
+ }else{\r
+ deleteSynonymRelationships(synonym, taxon);\r
+ }\r
+ }\r
+ }\r
+\r
+ // TaxonRelationship\r
+ if (! config.isDeleteTaxonRelationships()){\r
+ if (taxon.getTaxonRelations().size() > 0){\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
+ }\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
+ 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
+ }\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
+ throw new ReferencedObjectUndeletableException(message);\r
+ }\r
+ }\r
+\r
+\r
+ //TaxonNameBase\r
+ if (config.isDeleteNameIfPossible()){\r
+ try {\r
+ nameService.delete(taxon.getName(), config.getNameDeletionConfig());\r
+ } catch (ReferencedObjectUndeletableException e) {\r
+ //do nothing\r
+ if (logger.isDebugEnabled()){logger.debug("Name could not be deleted");}\r
+ }\r
+ }\r
\r
- return this.dao.createInferredSynonyms(taxon, tree, type);\r
}\r
\r
/* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)\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
- public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {\r
-\r
- return this.dao.findIdenticalTaxonNames(propertyPath);\r
+ @Transactional(readOnly = false)\r
+ @Override\r
+ public void deleteSynonym(Synonym synonym, Taxon taxon, boolean removeNameIfPossible,boolean newHomotypicGroupIfNeeded) {\r
+ if (synonym == null){\r
+ return;\r
+ }\r
+ synonym = CdmBase.deproxy(dao.merge(synonym), Synonym.class);\r
+\r
+ //remove synonymRelationship\r
+ Set<Taxon> taxonSet = new HashSet<Taxon>();\r
+ if (taxon != null){\r
+ taxonSet.add(taxon);\r
+ }else{\r
+ taxonSet.addAll(synonym.getAcceptedTaxa());\r
+ }\r
+ for (Taxon relatedTaxon : taxonSet){\r
+// dao.deleteSynonymRelationships(synonym, relatedTaxon);\r
+ relatedTaxon.removeSynonym(synonym, newHomotypicGroupIfNeeded);\r
+ }\r
+ this.saveOrUpdate(synonym);\r
+\r
+ //TODO remove name from homotypical group?\r
+\r
+ //remove synonym (if necessary)\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
+ 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
+ }\r
+ }\r
+ }\r
}\r
\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Synonym, boolean)\r
- */\r
- //TODO move to dao??\r
- @Transactional(readOnly = false)\r
- @Override\r
- public void deleteSynonym(Synonym synonym, Taxon taxon, boolean removeNameIfPossible) {\r
- //remove synonymRelationship\r
- Set<Taxon> taxonSet = new HashSet<Taxon>();\r
- if (taxon != null){\r
- taxonSet.add(taxon);\r
- }else{\r
- taxonSet.addAll(synonym.getAcceptedTaxa());\r
- }\r
- Set<SynonymRelationship> synRels = synonym.getSynonymRelations();\r
- for (Taxon taxon2 : taxonSet){\r
- dao.deleteSynonymRelationships(synonym, taxon2);\r
- }\r
- \r
- //TODO remove name from homotypical group?\r
- \r
- //remove synonym (if necessary)\r
- if (synonym.getSynonymRelations().isEmpty()){\r
- dao.delete(synonym);\r
- }\r
- \r
- if (removeNameIfPossible){\r
- TaxonNameBase name = synonym.getName();\r
- nameService.delete(name);\r
- }\r
- }\r
- \r
- \r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)\r
*/\r
return this.dao.getPhylumName(name);\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)\r
- */\r
- public long deleteSynonymRelationships(Synonym syn) {\r
- return dao.deleteSynonymRelationships(syn, null);\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
+ public long deleteSynonymRelationships(Synonym syn, Taxon taxon) {\r
+ return dao.deleteSynonymRelationships(syn, taxon);\r
+ }\r
+\r
+/* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)\r
+ */\r
+ public long deleteSynonymRelationships(Synonym syn) {\r
+ return dao.deleteSynonymRelationships(syn, null);\r
+ }\r
\r
\r
/* (non-Javadoc)\r
Taxon bestCandidate = null;\r
try{\r
// 1. search for acceptet taxa\r
- List<TaxonBase> taxonList = dao.findByNameTitleCache(Taxon.class, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, 0, null, null);\r
+ List<TaxonBase> taxonList = dao.findByNameTitleCache(true, false, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, 0, null, null);\r
boolean bestCandidateMatchesSecUuid = false;\r
boolean bestCandidateIsInClassification = false;\r
int countEqualCandidates = 0;\r
\r
// 2. search for synonyms\r
if (config.isIncludeSynonyms()){\r
- List<TaxonBase> synonymList = dao.findByNameTitleCache(Synonym.class, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, 0, null, null);\r
+ List<TaxonBase> synonymList = dao.findByNameTitleCache(false, true, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, 0, null, null);\r
for(TaxonBase taxonBase : synonymList){\r
if(taxonBase instanceof Synonym){\r
Synonym synonym = CdmBase.deproxy(taxonBase, Synonym.class);\r
*/\r
@Override\r
public Synonym findBestMatchingSynonym(String taxonName) {\r
- List<TaxonBase> synonymList = dao.findByNameTitleCache(Synonym.class, taxonName, null, MatchMode.EXACT, null, 0, null, null);\r
+ List<TaxonBase> synonymList = dao.findByNameTitleCache(false, true, taxonName, null, MatchMode.EXACT, null, 0, null, null);\r
if(! synonymList.isEmpty()){\r
Synonym result = CdmBase.deproxy(synonymList.iterator().next(), Synonym.class);\r
if(synonymList.size() == 1){\r
return null;\r
}\r
\r
+\r
/* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#moveSynonymToAnotherTaxon(eu.etaxonomy.cdm.model.taxon.SynonymRelationship, eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.reference.Reference, java.lang.String)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#moveSynonymToAnotherTaxon(eu.etaxonomy.cdm.model.taxon.SynonymRelationship, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, eu.etaxonomy.cdm.model.reference.Reference, java.lang.String, boolean)\r
*/\r
@Override\r
- public Taxon moveSynonymToAnotherTaxon(SynonymRelationship synonymRelation,\r
- Taxon toTaxon, SynonymRelationshipType synonymRelationshipType, Reference reference, String referenceDetail) {\r
- Taxon fromTaxon = synonymRelation.getAcceptedTaxon();\r
-\r
- toTaxon.addSynonym(synonymRelation.getSynonym(), synonymRelationshipType, reference, referenceDetail);\r
-\r
- fromTaxon.removeSynonymRelation(synonymRelation);\r
+ public SynonymRelationship moveSynonymToAnotherTaxon(SynonymRelationship oldSynonymRelation, Taxon newTaxon, boolean moveHomotypicGroup,\r
+ SynonymRelationshipType newSynonymRelationshipType, Reference reference, String referenceDetail, boolean keepReference) throws HomotypicalGroupChangeException {\r
+\r
+ Synonym synonym = oldSynonymRelation.getSynonym();\r
+ Taxon fromTaxon = oldSynonymRelation.getAcceptedTaxon();\r
+ //TODO what if there is no name ?? Concepts may be cached (e.g. via TCS import)\r
+ TaxonNameBase<?,?> synonymName = synonym.getName();\r
+ TaxonNameBase<?,?> fromTaxonName = fromTaxon.getName();\r
+ //set default relationship type\r
+ if (newSynonymRelationshipType == null){\r
+ newSynonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();\r
+ }\r
+ boolean newRelTypeIsHomotypic = newSynonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF());\r
+\r
+ HomotypicalGroup homotypicGroup = synonymName.getHomotypicalGroup();\r
+ int hgSize = homotypicGroup.getTypifiedNames().size();\r
+ boolean isSingleInGroup = !(hgSize > 1);\r
+\r
+ if (! isSingleInGroup){\r
+ boolean isHomotypicToAccepted = synonymName.isHomotypic(fromTaxonName);\r
+ boolean hasHomotypicSynonymRelatives = isHomotypicToAccepted ? hgSize > 2 : hgSize > 1;\r
+ if (isHomotypicToAccepted){\r
+ String message = "Synonym is in homotypic group with accepted taxon%s. First remove synonym from homotypic group of accepted taxon before moving to other taxon.";\r
+ String homotypicRelatives = hasHomotypicSynonymRelatives ? " and other synonym(s)":"";\r
+ message = String.format(message, homotypicRelatives);\r
+ throw new HomotypicalGroupChangeException(message);\r
+ }\r
+ if (! moveHomotypicGroup){\r
+ String message = "Synonym is in homotypic group with other synonym(s). Either move complete homotypic group or remove synonym from homotypic group prior to moving to other taxon.";\r
+ throw new HomotypicalGroupChangeException(message);\r
+ }\r
+ }else{\r
+ moveHomotypicGroup = true; //single synonym always allows to moveCompleteGroup\r
+ }\r
+// Assert.assertTrue("Synonym can only be moved with complete homotypic group", moveHomotypicGroup);\r
+\r
+ SynonymRelationship result = null;\r
+ //move all synonyms to new taxon\r
+ List<Synonym> homotypicSynonyms = fromTaxon.getSynonymsInGroup(homotypicGroup);\r
+ for (Synonym syn: homotypicSynonyms){\r
+ Set<SynonymRelationship> synRelations = syn.getSynonymRelations();\r
+ for (SynonymRelationship synRelation : synRelations){\r
+ if (fromTaxon.equals(synRelation.getAcceptedTaxon())){\r
+ Reference<?> newReference = reference;\r
+ if (newReference == null && keepReference){\r
+ newReference = synRelation.getCitation();\r
+ }\r
+ String newRefDetail = referenceDetail;\r
+ if (newRefDetail == null && keepReference){\r
+ newRefDetail = synRelation.getCitationMicroReference();\r
+ }\r
+ SynonymRelationship newSynRelation = newTaxon.addSynonym(syn, newSynonymRelationshipType, newReference, newRefDetail);\r
+ fromTaxon.removeSynonymRelation(synRelation, false);\r
+//\r
+ //change homotypic group of synonym if relType is 'homotypic'\r
+// if (newRelTypeIsHomotypic){\r
+// newTaxon.getName().getHomotypicalGroup().addTypifiedName(syn.getName());\r
+// }\r
+ //set result\r
+ if (synRelation.equals(oldSynonymRelation)){\r
+ result = newSynRelation;\r
+ }\r
+ }\r
+ }\r
\r
- return toTaxon;\r
+ }\r
+ saveOrUpdate(newTaxon);\r
+ //Assert that there is a result\r
+ if (result == null){\r
+ String message = "Old synonym relation could not be transformed into new relation. This should not happen.";\r
+ throw new IllegalStateException(message);\r
+ }\r
+ return result;\r
}\r
\r
/* (non-Javadoc)\r
return dao.getUuidAndTitleCacheTaxon();\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()\r
- */\r
- @Override\r
- public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheSynonym() {\r
- return dao.getUuidAndTitleCacheSynonym();\r
- }\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()\r
+ */\r
+ @Override\r
+ public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheSynonym() {\r
+ return dao.getUuidAndTitleCacheSynonym();\r
+ }\r
+\r
+ @Override\r
+ public Pager<SearchResult<TaxonBase>> findByFullText(\r
+ Class<? extends TaxonBase> clazz, String queryString,\r
+ Classification classification, List<Language> languages,\r
+ boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
+\r
+// // -- set defaults\r
+// Class<? extends TaxonBase> directorySelectClass = TaxonBase.class;\r
+// if(clazz != null){\r
+// directorySelectClass = clazz;\r
+// }\r
+ return null;\r
+\r
+ }\r
+\r
+ @Override\r
+ public Pager<SearchResult<TaxonBase>> findByDescriptionElementFullText(\r
+ Class<? extends DescriptionElementBase> clazz, String queryString,\r
+ Classification classification, List<Feature> features, List<Language> languages,\r
+ boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
+\r
+ // -- set defaults\r
+ Class<? extends DescriptionElementBase> directorySelectClass = DescriptionElementBase.class;\r
+ if(clazz != null){\r
+ directorySelectClass = clazz;\r
+ }\r
+\r
+\r
+ BooleanQuery finalQuery = new BooleanQuery();\r
+ BooleanQuery textQuery = new BooleanQuery();\r
+\r
+ LuceneSearch luceneSearch = new LuceneSearch(getSession(), directorySelectClass);\r
+ QueryFactory queryFactory = new QueryFactory(luceneSearch);\r
+\r
+ // ---- search criteria\r
+ textQuery.add(queryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
+\r
+ // common name\r
+ Query nameQuery;\r
+ if(languages == null || languages.size() == 0){\r
+ nameQuery = queryFactory.newTermQuery("name", queryString);\r
+ } else {\r
+ nameQuery = new BooleanQuery();\r
+ BooleanQuery languageSubQuery = new BooleanQuery();\r
+ for(Language lang : languages){\r
+ languageSubQuery.add(queryFactory.newTermQuery("language.uuid", lang.getUuid().toString()), Occur.SHOULD);\r
+ }\r
+ ((BooleanQuery) nameQuery).add(queryFactory.newTermQuery("name", queryString), Occur.MUST);\r
+ ((BooleanQuery) nameQuery).add(languageSubQuery, Occur.MUST);\r
+ }\r
+ textQuery.add(nameQuery, Occur.SHOULD);\r
+\r
+\r
+ // text field from TextData\r
+ textQuery.add(queryFactory.newLocalizedTermQuery("text", queryString, languages), Occur.SHOULD);\r
+\r
+ // --- TermBase fields - by representation ----\r
+ // state field from CategoricalData\r
+ textQuery.add(queryFactory.newLocalizedTermQuery("states.state.representation", queryString, languages), Occur.SHOULD);\r
+\r
+ // state field from CategoricalData\r
+ textQuery.add(queryFactory.newLocalizedTermQuery("states.modifyingText", queryString, languages), Occur.SHOULD);\r
+\r
+ finalQuery.add(textQuery, Occur.MUST);\r
+ // --- classification ----\r
+\r
+ if(classification != null){\r
+ finalQuery.add(queryFactory.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification), Occur.MUST);\r
+ }\r
+\r
+ // --- IdentifieableEntity fields - by uuid\r
+ if(features != null && features.size() > 0 ){\r
+ finalQuery.add(queryFactory.newEntityUuidQuery("feature.uuid", features), Occur.MUST);\r
+ }\r
+\r
+ // the description must be associated with a taxon\r
+ finalQuery.add(queryFactory.newIdNotNullQuery("inDescription.taxon.id"), Occur.MUST);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("inDescription.taxon.titleCache__sort", false)};\r
+\r
+ TopDocs topDocsResultSet = luceneSearch.executeSearch(finalQuery, clazz, pageSize, pageNumber, sortFields);\r
+\r
+ String[] highlightFields = null;\r
+ if(highlightFragments){\r
+ highlightFields = queryFactory.getTextFieldNames().toArray(new String[queryFactory.getTextFieldNames().size()]);\r
+ }\r
+\r
+ // initialize taxa, thighlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, finalQuery);\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, highlightFields, dao, "inDescription.taxon.id", propertyPaths);\r
+\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, searchResults.size(), pageSize, searchResults);\r
+\r
+ }\r
+\r
+ /**\r
+ * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link 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 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
+ * @return the StringBuilder given a parameter or a new one if the stringBuilder parameter was null.\r
+ *\r
+ * TODO move to utiliy class !!!!!!!!\r
+ */\r
+ private StringBuilder appendLocalizedFieldQuery(String name, List<Language> languages, StringBuilder stringBuilder) {\r
+\r
+ if(stringBuilder == null){\r
+ stringBuilder = new StringBuilder();\r
+ }\r
+ if(languages == null || languages.size() == 0){\r
+ stringBuilder.append(name + ".ALL:(%1$s) ");\r
+ } else {\r
+ for(Language lang : languages){\r
+ stringBuilder.append(name + "." + lang.getUuid().toString() + ":(%1$s) ");\r
+ }\r
+ }\r
+ return stringBuilder;\r
+ }\r
+\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
+\r
+ HashMap <UUID, ZoologicalName> zooHashMap = new HashMap<UUID, ZoologicalName>();\r
+\r
+\r
+ UUID uuid= taxon.getName().getUuid();\r
+ ZoologicalName taxonName = getZoologicalName(uuid, zooHashMap);\r
+ String epithetOfTaxon = null;\r
+ String infragenericEpithetOfTaxon = null;\r
+ String infraspecificEpithetOfTaxon = null;\r
+ if (taxonName.isSpecies()){\r
+ epithetOfTaxon= taxonName.getSpecificEpithet();\r
+ } else if (taxonName.isInfraGeneric()){\r
+ infragenericEpithetOfTaxon = taxonName.getInfraGenericEpithet();\r
+ } else if (taxonName.isInfraSpecific()){\r
+ infraspecificEpithetOfTaxon = taxonName.getInfraSpecificEpithet();\r
+ }\r
+ String genusOfTaxon = taxonName.getGenusOrUninomial();\r
+ Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
+ List<String> taxonNames = new ArrayList<String>();\r
+\r
+ for (TaxonNode node: nodes){\r
+ // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName\r
+ // List<String> synonymsEpithet = new ArrayList<String>();\r
+\r
+ if (node.getClassification().equals(classification)){\r
+ if (!node.isTopmostNode()){\r
+ TaxonNode parent = (TaxonNode)node.getParent();\r
+ parent = (TaxonNode)HibernateProxyHelper.deproxy(parent);\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
+ //create inferred synonyms for species, subspecies\r
+ if ((parentName.isGenus() || parentName.isSpecies() || parentName.getRank().equals(Rank.SUBGENUS())) ){\r
+\r
+ Synonym inferredEpithet = null;\r
+ Synonym inferredGenus = null;\r
+ Synonym potentialCombination = null;\r
+\r
+ List<String> propertyPaths = new ArrayList<String>();\r
+ propertyPaths.add("synonym");\r
+ propertyPaths.add("synonym.name");\r
+ List<OrderHint> orderHints = new ArrayList<OrderHint>();\r
+ orderHints.add(new OrderHint("relatedFrom.titleCache", SortOrder.ASCENDING));\r
+\r
+ List<SynonymRelationship> synonymRelationshipsOfParent = dao.getSynonyms(parentTaxon, SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints,propertyPaths);\r
+ List<SynonymRelationship> synonymRelationshipsOfTaxon= dao.getSynonyms(taxon, SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints,propertyPaths);\r
+\r
+ List<TaxonRelationship> taxonRelListParent = null;\r
+ List<TaxonRelationship> taxonRelListTaxon = null;\r
+ if (doWithMisappliedNames){\r
+ taxonRelListParent = dao.getTaxonRelationships(parentTaxon, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null, orderHints, propertyPaths, Direction.relatedTo);\r
+ taxonRelListTaxon = dao.getTaxonRelationships(taxon, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null, orderHints, propertyPaths, Direction.relatedTo);\r
+ }\r
+\r
+\r
+ if (type.equals(SynonymRelationshipType.INFERRED_EPITHET_OF())){\r
+ Set<String> genusNames = new HashSet<String>();\r
+\r
+ for (SynonymRelationship synonymRelationOfParent:synonymRelationshipsOfParent){\r
+ Synonym syn = synonymRelationOfParent.getSynonym();\r
+\r
+ inferredEpithet = createInferredEpithets(taxon,\r
+ zooHashMap, taxonName, epithetOfTaxon,\r
+ infragenericEpithetOfTaxon,\r
+ infraspecificEpithetOfTaxon,\r
+ taxonNames, parentName,\r
+ syn);\r
+\r
+\r
+ inferredSynonyms.add(inferredEpithet);\r
+ zooHashMap.put(inferredEpithet.getName().getUuid(), (ZoologicalName)inferredEpithet.getName());\r
+ taxonNames.add(((ZoologicalName)inferredEpithet.getName()).getNameCache());\r
+ }\r
+\r
+ if (doWithMisappliedNames){\r
+\r
+ for (TaxonRelationship taxonRelationship: taxonRelListParent){\r
+ Taxon misappliedName = taxonRelationship.getFromTaxon();\r
+\r
+ inferredEpithet = createInferredEpithets(taxon,\r
+ zooHashMap, taxonName, epithetOfTaxon,\r
+ infragenericEpithetOfTaxon,\r
+ infraspecificEpithetOfTaxon,\r
+ taxonNames, parentName,\r
+ misappliedName);\r
+\r
+ inferredSynonyms.add(inferredEpithet);\r
+ zooHashMap.put(inferredEpithet.getName().getUuid(), (ZoologicalName)inferredEpithet.getName());\r
+ taxonNames.add(((ZoologicalName)inferredEpithet.getName()).getNameCache());\r
+ }\r
+ }\r
+\r
+ if (!taxonNames.isEmpty()){\r
+ List<String> synNotInCDM = dao.taxaByNameNotInDB(taxonNames);\r
+ ZoologicalName name;\r
+ if (!synNotInCDM.isEmpty()){\r
+ inferredSynonymsToBeRemoved.clear();\r
+\r
+ for (Synonym syn :inferredSynonyms){\r
+ name = getZoologicalName(syn.getName().getUuid(), zooHashMap);\r
+ if (!synNotInCDM.contains(name.getNameCache())){\r
+ inferredSynonymsToBeRemoved.add(syn);\r
+ }\r
+ }\r
+\r
+ // Remove identified Synonyms from inferredSynonyms\r
+ for (Synonym synonym : inferredSynonymsToBeRemoved) {\r
+ inferredSynonyms.remove(synonym);\r
+ }\r
+ }\r
+ }\r
+\r
+ }else if (type.equals(SynonymRelationshipType.INFERRED_GENUS_OF())){\r
+\r
+\r
+ for (SynonymRelationship synonymRelationOfTaxon:synonymRelationshipsOfTaxon){\r
+ TaxonNameBase synName;\r
+ ZoologicalName inferredSynName;\r
+\r
+ Synonym syn = synonymRelationOfTaxon.getSynonym();\r
+ inferredGenus = createInferredGenus(taxon,\r
+ zooHashMap, taxonName, epithetOfTaxon,\r
+ genusOfTaxon, taxonNames, zooParentName, syn);\r
+\r
+ inferredSynonyms.add(inferredGenus);\r
+ zooHashMap.put(inferredGenus.getName().getUuid(), (ZoologicalName)inferredGenus.getName());\r
+ taxonNames.add(( (ZoologicalName)inferredGenus.getName()).getNameCache());\r
+\r
+\r
+ }\r
+\r
+ if (doWithMisappliedNames){\r
+\r
+ for (TaxonRelationship taxonRelationship: taxonRelListTaxon){\r
+ Taxon misappliedName = taxonRelationship.getFromTaxon();\r
+ inferredGenus = createInferredGenus(taxon, zooHashMap, taxonName, infraspecificEpithetOfTaxon, genusOfTaxon, taxonNames, zooParentName, misappliedName);\r
+\r
+ inferredSynonyms.add(inferredGenus);\r
+ zooHashMap.put(inferredGenus.getName().getUuid(), (ZoologicalName)inferredGenus.getName());\r
+ taxonNames.add(( (ZoologicalName)inferredGenus.getName()).getNameCache());\r
+ }\r
+ }\r
+\r
+\r
+ if (!taxonNames.isEmpty()){\r
+ List<String> synNotInCDM = dao.taxaByNameNotInDB(taxonNames);\r
+ ZoologicalName name;\r
+ if (!synNotInCDM.isEmpty()){\r
+ inferredSynonymsToBeRemoved.clear();\r
+\r
+ for (Synonym syn :inferredSynonyms){\r
+ name = getZoologicalName(syn.getName().getUuid(), zooHashMap);\r
+ if (!synNotInCDM.contains(name.getNameCache())){\r
+ inferredSynonymsToBeRemoved.add(syn);\r
+ }\r
+ }\r
+\r
+ // Remove identified Synonyms from inferredSynonyms\r
+ for (Synonym synonym : inferredSynonymsToBeRemoved) {\r
+ inferredSynonyms.remove(synonym);\r
+ }\r
+ }\r
+ }\r
+\r
+ }else if (type.equals(SynonymRelationshipType.POTENTIAL_COMBINATION_OF())){\r
+\r
+ Reference sourceReference = null; // TODO: Determination of sourceReference is redundant\r
+ ZoologicalName inferredSynName;\r
+ //for all synonyms of the parent...\r
+ for (SynonymRelationship synonymRelationOfParent:synonymRelationshipsOfParent){\r
+ TaxonNameBase synName;\r
+ Synonym synParent = synonymRelationOfParent.getSynonym();\r
+ synName = synParent.getName();\r
+\r
+ HibernateProxyHelper.deproxy(synParent);\r
+\r
+ // Set the sourceReference\r
+ sourceReference = synParent.getSec();\r
+\r
+ // Determine the idInSource\r
+ String idInSourceParent = getIdInSource(synParent);\r
+\r
+ ZoologicalName parentSynZooName = getZoologicalName(synName.getUuid(), zooHashMap);\r
+ String synParentGenus = parentSynZooName.getGenusOrUninomial();\r
+ String synParentInfragenericName = null;\r
+ String synParentSpecificEpithet = null;\r
+\r
+ if (parentSynZooName.isInfraGeneric()){\r
+ synParentInfragenericName = parentSynZooName.getInfraGenericEpithet();\r
+ }\r
+ if (parentSynZooName.isSpecies()){\r
+ synParentSpecificEpithet = parentSynZooName.getSpecificEpithet();\r
+ }\r
+\r
+ /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){\r
+ synonymsGenus.put(synGenusName, idInSource);\r
+ }*/\r
+\r
+ //for all synonyms of the taxon\r
+\r
+ for (SynonymRelationship synonymRelationOfTaxon:synonymRelationshipsOfTaxon){\r
+\r
+ Synonym syn = synonymRelationOfTaxon.getSynonym();\r
+ ZoologicalName zooSynName = getZoologicalName(syn.getName().getUuid(), zooHashMap);\r
+ potentialCombination = createPotentialCombination(idInSourceParent, parentSynZooName, zooSynName,\r
+ synParentGenus,\r
+ synParentInfragenericName,\r
+ synParentSpecificEpithet, syn, zooHashMap);\r
+\r
+ taxon.addSynonym(potentialCombination, SynonymRelationshipType.POTENTIAL_COMBINATION_OF());\r
+ inferredSynonyms.add(potentialCombination);\r
+ zooHashMap.put(potentialCombination.getName().getUuid(), (ZoologicalName)potentialCombination.getName());\r
+ taxonNames.add(( (ZoologicalName)potentialCombination.getName()).getNameCache());\r
+\r
+ }\r
+\r
+\r
+ }\r
+\r
+ if (doWithMisappliedNames){\r
+\r
+ for (TaxonRelationship parentRelationship: taxonRelListParent){\r
+\r
+ TaxonNameBase misappliedParentName;\r
+\r
+ Taxon misappliedParent = parentRelationship.getFromTaxon();\r
+ misappliedParentName = misappliedParent.getName();\r
+\r
+ HibernateProxyHelper.deproxy(misappliedParent);\r
+\r
+ // Set the sourceReference\r
+ sourceReference = misappliedParent.getSec();\r
+\r
+ // Determine the idInSource\r
+ String idInSourceParent = getIdInSource(misappliedParent);\r
+\r
+ ZoologicalName parentSynZooName = getZoologicalName(misappliedParentName.getUuid(), zooHashMap);\r
+ String synParentGenus = parentSynZooName.getGenusOrUninomial();\r
+ String synParentInfragenericName = null;\r
+ String synParentSpecificEpithet = null;\r
+\r
+ if (parentSynZooName.isInfraGeneric()){\r
+ synParentInfragenericName = parentSynZooName.getInfraGenericEpithet();\r
+ }\r
+ if (parentSynZooName.isSpecies()){\r
+ synParentSpecificEpithet = parentSynZooName.getSpecificEpithet();\r
+ }\r
+\r
+\r
+ for (TaxonRelationship taxonRelationship: taxonRelListTaxon){\r
+ Taxon misappliedName = taxonRelationship.getFromTaxon();\r
+ ZoologicalName zooMisappliedName = getZoologicalName(misappliedName.getName().getUuid(), zooHashMap);\r
+ potentialCombination = createPotentialCombination(\r
+ idInSourceParent, parentSynZooName, zooMisappliedName,\r
+ synParentGenus,\r
+ synParentInfragenericName,\r
+ synParentSpecificEpithet, misappliedName, zooHashMap);\r
+\r
+\r
+ taxon.addSynonym(potentialCombination, SynonymRelationshipType.POTENTIAL_COMBINATION_OF());\r
+ inferredSynonyms.add(potentialCombination);\r
+ zooHashMap.put(potentialCombination.getName().getUuid(), (ZoologicalName)potentialCombination.getName());\r
+ taxonNames.add(( (ZoologicalName)potentialCombination.getName()).getNameCache());\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!taxonNames.isEmpty()){\r
+ List<String> synNotInCDM = dao.taxaByNameNotInDB(taxonNames);\r
+ ZoologicalName name;\r
+ if (!synNotInCDM.isEmpty()){\r
+ inferredSynonymsToBeRemoved.clear();\r
+ for (Synonym syn :inferredSynonyms){\r
+ try{\r
+ name = (ZoologicalName) syn.getName();\r
+ }catch (ClassCastException e){\r
+ name = getZoologicalName(syn.getName().getUuid(), zooHashMap);\r
+ }\r
+ if (!synNotInCDM.contains(name.getNameCache())){\r
+ inferredSynonymsToBeRemoved.add(syn);\r
+ }\r
+ }\r
+ // Remove identified Synonyms from inferredSynonyms\r
+ for (Synonym synonym : inferredSynonymsToBeRemoved) {\r
+ inferredSynonyms.remove(synonym);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }else {\r
+ logger.info("The synonymrelationship type is not defined.");\r
+ return inferredSynonyms;\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ return inferredSynonyms;\r
+ }\r
+\r
+ private Synonym createPotentialCombination(String idInSourceParent,\r
+ ZoologicalName parentSynZooName, ZoologicalName zooSynName, String synParentGenus,\r
+ String synParentInfragenericName, String synParentSpecificEpithet,\r
+ TaxonBase syn, HashMap<UUID, ZoologicalName> zooHashMap) {\r
+ Synonym potentialCombination;\r
+ Reference sourceReference;\r
+ ZoologicalName inferredSynName;\r
+ HibernateProxyHelper.deproxy(syn);\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
+ String synTaxonSpecificEpithet = zooSynName.getSpecificEpithet();\r
+\r
+ String synTaxonInfraSpecificName= null;\r
+\r
+ if (parentSynZooName.isSpecies()){\r
+ synTaxonInfraSpecificName = zooSynName.getInfraSpecificEpithet();\r
+ }\r
+\r
+ /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){\r
+ synonymsEpithet.add(epithetName);\r
+ }*/\r
+\r
+ //create potential combinations...\r
+ inferredSynName = ZoologicalName.NewInstance(syn.getName().getRank());\r
+\r
+ inferredSynName.setGenusOrUninomial(synParentGenus);\r
+ if (zooSynName.isSpecies()){\r
+ inferredSynName.setSpecificEpithet(synTaxonSpecificEpithet);\r
+ if (parentSynZooName.isInfraGeneric()){\r
+ inferredSynName.setInfraGenericEpithet(synParentInfragenericName);\r
+ }\r
+ }\r
+ if (zooSynName.isInfraSpecific()){\r
+ inferredSynName.setSpecificEpithet(synParentSpecificEpithet);\r
+ inferredSynName.setInfraSpecificEpithet(synTaxonInfraSpecificName);\r
+ }\r
+ if (parentSynZooName.isInfraGeneric()){\r
+ inferredSynName.setInfraGenericEpithet(synParentInfragenericName);\r
+ }\r
+\r
+\r
+ potentialCombination = Synonym.NewInstance(inferredSynName, null);\r
+\r
+ // Set the sourceReference\r
+ potentialCombination.setSec(sourceReference);\r
+\r
+\r
+ // Determine the idInSource\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
+ inferredSynName.addSource(originalSource);\r
+ originalSource = IdentifiableSource.NewInstance(idInSourceSyn + "; " + idInSourceParent, POTENTIAL_COMBINATION_NAMESPACE, sourceReference, null);\r
+ potentialCombination.addSource(originalSource);\r
+ }\r
+\r
+ inferredSynName.generateTitle();\r
+\r
+ return potentialCombination;\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
+ /* 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
+\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
+\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
+ /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){\r
+ synonymsGenus.put(synGenusName, idInSource);\r
+ }*/\r
+\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
+ 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
+ }\r
+\r
+ /**\r
+ * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.\r
+ * Very likely only useful for createInferredSynonyms().\r
+ * @param uuid\r
+ * @param zooHashMap\r
+ * @return\r
+ */\r
+ private ZoologicalName getZoologicalName(UUID uuid, HashMap <UUID, ZoologicalName> zooHashMap) {\r
+ ZoologicalName taxonName =nameDao.findZoologicalNameByUUID(uuid);\r
+ if (taxonName == null) {\r
+ taxonName = zooHashMap.get(uuid);\r
+ }\r
+ return taxonName;\r
+ }\r
+\r
+ /**\r
+ * Returns the idInSource for a given Synonym.\r
+ * @param syn\r
+ */\r
+ private String getIdInSource(TaxonBase taxonBase) {\r
+ String idInSource = null;\r
+ Set<IdentifiableSource> sources = taxonBase.getSources();\r
+ if (sources.size() == 1) {\r
+ IdentifiableSource source = sources.iterator().next();\r
+ if (source != null) {\r
+ idInSource = source.getIdInSource();\r
+ }\r
+ } else if (sources.size() > 1) {\r
+ int count = 1;\r
+ idInSource = "";\r
+ for (IdentifiableSource source : sources) {\r
+ idInSource += source.getIdInSource();\r
+ if (count < sources.size()) {\r
+ idInSource += "; ";\r
+ }\r
+ count++;\r
+ }\r
+ } else if (sources.size() == 0){\r
+ logger.warn("No idInSource for TaxonBase " + taxonBase.getUuid() + " - " + taxonBase.getTitleCache());\r
+ }\r
+\r
+\r
+ return idInSource;\r
+ }\r
+\r
+\r
+ /**\r
+ * Returns the citation for a given Synonym.\r
+ * @param syn\r
+ */\r
+ private Reference getCitation(Synonym syn) {\r
+ Reference citation = null;\r
+ Set<IdentifiableSource> sources = syn.getSources();\r
+ if (sources.size() == 1) {\r
+ IdentifiableSource source = sources.iterator().next();\r
+ if (source != null) {\r
+ citation = source.getCitation();\r
+ }\r
+ } else if (sources.size() > 1) {\r
+ logger.warn("This Synonym has more than one source: " + syn.getUuid() + " (" + syn.getTitleCache() +")");\r
+ }\r
+\r
+ return citation;\r
+ }\r
+\r
+ public List<Synonym> createAllInferredSynonyms(Taxon taxon, Classification tree, boolean doWithMisappliedNames){\r
+ List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\r
+\r
+ inferredSynonyms.addAll(createInferredSynonyms(taxon, tree, SynonymRelationshipType.INFERRED_EPITHET_OF(), doWithMisappliedNames));\r
+ inferredSynonyms.addAll(createInferredSynonyms(taxon, tree, SynonymRelationshipType.INFERRED_GENUS_OF(), doWithMisappliedNames));\r
+ inferredSynonyms.addAll(createInferredSynonyms(taxon, tree, SynonymRelationshipType.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames));\r
+\r
+ return inferredSynonyms;\r
+ }\r
+\r
+\r
+\r
\r
}\r