3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.io
.IOException
;
14 import java
.util
.ArrayList
;
15 import java
.util
.HashMap
;
16 import java
.util
.HashSet
;
17 import java
.util
.List
;
19 import java
.util
.UUID
;
21 import org
.apache
.log4j
.Logger
;
22 import org
.apache
.lucene
.index
.CorruptIndexException
;
23 import org
.apache
.lucene
.queryParser
.ParseException
;
24 import org
.apache
.lucene
.search
.TopDocs
;
25 import org
.hibernate
.criterion
.Criterion
;
26 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
27 import org
.springframework
.stereotype
.Service
;
28 import org
.springframework
.transaction
.annotation
.Propagation
;
29 import org
.springframework
.transaction
.annotation
.Transactional
;
31 import eu
.etaxonomy
.cdm
.api
.service
.config
.ITaxonServiceConfigurator
;
32 import eu
.etaxonomy
.cdm
.api
.service
.config
.MatchingTaxonConfigurator
;
33 import eu
.etaxonomy
.cdm
.api
.service
.config
.NameDeletionConfigurator
;
34 import eu
.etaxonomy
.cdm
.api
.service
.config
.TaxonDeletionConfigurator
;
35 import eu
.etaxonomy
.cdm
.api
.service
.exception
.DataChangeNoRollbackException
;
36 import eu
.etaxonomy
.cdm
.api
.service
.exception
.HomotypicalGroupChangeException
;
37 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
38 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
39 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
40 import eu
.etaxonomy
.cdm
.api
.service
.search
.ISearchResultBuilder
;
41 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
42 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
43 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
44 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
45 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
46 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
47 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
48 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
49 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
50 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
51 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
52 import eu
.etaxonomy
.cdm
.model
.description
.IIdentificationKey
;
53 import eu
.etaxonomy
.cdm
.model
.description
.PolytomousKeyNode
;
54 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
55 import eu
.etaxonomy
.cdm
.model
.description
.TaxonInteraction
;
56 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
57 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
58 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
59 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
60 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
61 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
62 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
63 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
64 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnitBase
;
65 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
66 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
67 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
68 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
69 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
70 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
71 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
72 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
73 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
74 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
75 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
76 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
77 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
78 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
79 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
80 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
81 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
82 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
.SortOrder
;
83 import eu
.etaxonomy
.cdm
.search
.LuceneSearch
;
84 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
88 * @author a.kohlbecker
93 @Transactional(propagation
= Propagation
.SUPPORTS
, readOnly
= true)
94 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
95 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
97 public static final String POTENTIAL_COMBINATION_NAMESPACE
= "Potential combination";
99 public static final String INFERRED_EPITHET_NAMESPACE
= "Inferred epithet";
101 public static final String INFERRED_GENUS_NAMESPACE
= "Inferred genus";
105 private ITaxonNameDao nameDao
;
108 private ISearchResultBuilder searchResultBuilder
;
111 private INameService nameService
;
114 private ICdmGenericDao genericDao
;
117 private IDescriptionService descriptionService
;
120 private IOrderedTermVocabularyDao orderedVocabularyDao
;
125 public TaxonServiceImpl(){
126 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
130 * FIXME Candidate for harmonization
131 * rename searchByName ?
133 public List
<TaxonBase
> searchTaxaByName(String name
, Reference sec
) {
134 return dao
.getTaxaByName(name
, sec
);
138 * FIXME Candidate for harmonization
139 * list(Synonym.class, ...)
141 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
143 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
144 return dao
.getAllSynonyms(limit
, start
);
148 * FIXME Candidate for harmonization
149 * list(Taxon.class, ...)
151 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
153 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
154 return dao
.getAllTaxa(limit
, start
);
158 * FIXME Candidate for harmonization
159 * merge with getRootTaxa(Reference sec, ..., ...)
161 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)
163 public List
<Taxon
> getRootTaxa(Reference sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
164 if (cdmFetch
== null){
165 cdmFetch
= CdmFetch
.NO_FETCH();
167 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
172 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
174 public List
<Taxon
> getRootTaxa(Rank rank
, Reference sec
, boolean onlyWithChildren
,boolean withMisapplications
, List
<String
> propertyPaths
) {
175 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
179 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)
181 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
182 return dao
.getAllRelationships(limit
, start
);
186 * FIXME Candidate for harmonization
187 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
190 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
192 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
193 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
194 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
195 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
196 return taxonRelTypeVocabulary
;
203 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
205 @Transactional(readOnly
= false)
206 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
208 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
209 synonymName
.removeTaxonBase(synonym
);
210 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
211 taxonName
.removeTaxonBase(acceptedTaxon
);
213 synonym
.setName(taxonName
);
214 acceptedTaxon
.setName(synonymName
);
216 // the accepted taxon needs a new uuid because the concept has changed
217 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
218 //acceptedTaxon.setUuid(UUID.randomUUID());
223 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
225 //TODO correct delete handling still needs to be implemented / checked
227 @Transactional(readOnly
= false)
228 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
, boolean deleteSynonym
, boolean copyCitationInfo
, Reference citation
, String microCitation
) throws HomotypicalGroupChangeException
{
230 TaxonNameBase
<?
,?
> acceptedName
= acceptedTaxon
.getName();
231 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
232 HomotypicalGroup synonymHomotypicGroup
= synonymName
.getHomotypicalGroup();
234 //check synonym is not homotypic
235 if (acceptedName
.getHomotypicalGroup().equals(synonymHomotypicGroup
)){
236 String message
= "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";
237 throw new HomotypicalGroupChangeException(message
);
240 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonymName
, acceptedTaxon
.getSec());
242 SynonymRelationshipType relTypeForGroup
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
243 List
<Synonym
> heteroSynonyms
= acceptedTaxon
.getSynonymsInGroup(synonymHomotypicGroup
);
245 for (Synonym heteroSynonym
: heteroSynonyms
){
246 if (synonym
.equals(heteroSynonym
)){
247 acceptedTaxon
.removeSynonym(heteroSynonym
, false);
249 //move synonyms in same homotypic group to new accepted taxon
250 heteroSynonym
.replaceAcceptedTaxon(newAcceptedTaxon
, relTypeForGroup
, copyCitationInfo
, citation
, microCitation
);
254 //synonym.getName().removeTaxonBase(synonym);
255 //TODO correct delete handling still needs to be implemented / checked
257 // deleteSynonym(synonym, taxon, false);
260 this.delete(synonym
);
262 } catch (Exception e
) {
263 logger
.info("Can't delete old synonym from database");
267 return newAcceptedTaxon
;
271 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, Reference citation
, String microcitation
){
273 // Get name from synonym
274 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
276 // remove synonym from taxon
277 toTaxon
.removeSynonym(synonym
);
279 // Create a taxon with synonym name
280 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
282 // Add taxon relation
283 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
285 // since we are swapping names, we have to detach the name from the synonym completely.
286 // Otherwise the synonym will still be in the list of typified names.
287 synonym
.getName().removeTaxonBase(synonym
);
294 * @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)
296 @Transactional(readOnly
= false)
298 public void changeHomotypicalGroupOfSynonym(Synonym synonym
, HomotypicalGroup newHomotypicalGroup
, Taxon targetTaxon
,
299 boolean removeFromOtherTaxa
, boolean setBasionymRelationIfApplicable
){
301 TaxonNameBase synonymName
= synonym
.getName();
302 HomotypicalGroup oldHomotypicalGroup
= synonymName
.getHomotypicalGroup();
306 oldHomotypicalGroup
.removeTypifiedName(synonymName
);
307 newHomotypicalGroup
.addTypifiedName(synonymName
);
309 //remove existing basionym relationships
310 synonymName
.removeBasionyms();
312 //add basionym relationship
313 if (setBasionymRelationIfApplicable
){
314 Set
<TaxonNameBase
> basionyms
= newHomotypicalGroup
.getBasionyms();
315 for (TaxonNameBase basionym
: basionyms
){
316 synonymName
.addBasionym(basionym
);
320 //set synonym relationship correctly
321 // SynonymRelationship relToTaxon = null;
322 boolean relToTargetTaxonExists
= false;
323 Set
<SynonymRelationship
> existingRelations
= synonym
.getSynonymRelations();
324 for (SynonymRelationship rel
: existingRelations
){
325 Taxon acceptedTaxon
= rel
.getAcceptedTaxon();
326 boolean isTargetTaxon
= acceptedTaxon
!= null && acceptedTaxon
.equals(targetTaxon
);
327 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
328 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
329 SynonymRelationshipType newRelationType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
330 rel
.setType(newRelationType
);
331 //TODO handle citation and microCitation
334 relToTargetTaxonExists
= true;
336 if (removeFromOtherTaxa
){
337 acceptedTaxon
.removeSynonym(synonym
, false);
343 if (targetTaxon
!= null && ! relToTargetTaxonExists
){
344 Taxon acceptedTaxon
= targetTaxon
;
345 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
346 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
347 SynonymRelationshipType relType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
348 //TODO handle citation and microCitation
349 Reference citation
= null;
350 String microCitation
= null;
351 acceptedTaxon
.addSynonym(synonym
, relType
, citation
, microCitation
);
358 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
361 public void updateTitleCache(Class
<?
extends TaxonBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<TaxonBase
> cacheStrategy
, IProgressMonitor monitor
) {
363 clazz
= TaxonBase
.class;
365 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
369 protected void setDao(ITaxonDao dao
) {
374 * @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)
376 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
377 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
379 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
380 if(numberOfResults
> 0) { // no point checking again
381 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
384 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
388 * @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)
390 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
391 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
393 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
394 if(numberOfResults
> 0) { // no point checking again
395 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
402 * @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)
404 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
405 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
407 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
408 if(numberOfResults
> 0) { // no point checking again
409 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
415 * @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)
417 public Pager
<TaxonRelationship
> pageToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
418 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
420 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
421 if(numberOfResults
> 0) { // no point checking again
422 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
424 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
428 * @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)
430 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
431 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
433 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
434 if(numberOfResults
> 0) { // no point checking again
435 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
441 * @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)
443 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
444 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
446 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
447 if(numberOfResults
> 0) { // no point checking again
448 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
450 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
454 * @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)
456 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
457 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
459 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
460 if(numberOfResults
> 0) { // no point checking again
461 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
464 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
468 * @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)
470 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
471 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
473 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
474 if(numberOfResults
> 0) { // no point checking again
475 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
478 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
482 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
484 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
485 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
486 return t
.getHomotypicSynonymsByHomotypicGroup();
490 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
492 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
493 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
494 List
<HomotypicalGroup
> homotypicalGroups
= t
.getHeterotypicSynonymyGroups();
495 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(homotypicalGroups
.size());
496 for(HomotypicalGroup homotypicalGroup
: homotypicalGroups
){
497 heterotypicSynonymyGroups
.add(t
.getSynonymsInGroup(homotypicalGroup
));
499 return heterotypicSynonymyGroups
;
502 public List
<UuidAndTitleCache
<TaxonBase
>> findTaxaAndNamesForEditor(ITaxonServiceConfigurator configurator
){
504 List
<UuidAndTitleCache
<TaxonBase
>> result
= new ArrayList
<UuidAndTitleCache
<TaxonBase
>>();
505 // Class<? extends TaxonBase> clazz = null;
506 // if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
507 // clazz = TaxonBase.class;
508 // //propertyPath.addAll(configurator.getTaxonPropertyPath());
509 // //propertyPath.addAll(configurator.getSynonymPropertyPath());
510 // } else if(configurator.isDoTaxa()) {
511 // clazz = Taxon.class;
512 // //propertyPath = configurator.getTaxonPropertyPath();
513 // } else if (configurator.isDoSynonyms()) {
514 // clazz = Synonym.class;
515 // //propertyPath = configurator.getSynonymPropertyPath();
519 result
= dao
.getTaxaByNameForEditor(configurator
.isDoTaxa(), configurator
.isDoSynonyms(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
524 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
526 public Pager
<IdentifiableEntity
> findTaxaAndNames(ITaxonServiceConfigurator configurator
) {
528 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
529 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
530 List
<TaxonBase
> taxa
= null;
533 long numberTaxaResults
= 0L;
536 List
<String
> propertyPath
= new ArrayList
<String
>();
537 if(configurator
.getTaxonPropertyPath() != null){
538 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
542 if (configurator
.isDoMisappliedNames() || configurator
.isDoSynonyms() || configurator
.isDoTaxa()){
543 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
545 dao
.countTaxaByName(configurator
.isDoTaxa(),configurator
.isDoSynonyms(), configurator
.isDoMisappliedNames(),
546 configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(),
547 configurator
.getNamedAreas());
550 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
551 taxa
= dao
.getTaxaByName(configurator
.isDoTaxa(), configurator
.isDoSynonyms(),
552 configurator
.isDoMisappliedNames(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(),
553 configurator
.getMatchMode(), configurator
.getNamedAreas(),
554 configurator
.getPageSize(), configurator
.getPageNumber(), propertyPath
);
558 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
561 results
.addAll(taxa
);
564 numberOfResults
+= numberTaxaResults
;
566 // Names without taxa
567 if (configurator
.isDoNamesWithoutTaxa()) {
568 int numberNameResults
= 0;
570 List
<?
extends TaxonNameBase
<?
,?
>> names
=
571 nameDao
.findByName(configurator
.getTitleSearchStringSqlized(), configurator
.getMatchMode(),
572 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
573 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
574 if (names
.size() > 0) {
575 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
576 if (taxonName
.getTaxonBases().size() == 0) {
577 results
.add(taxonName
);
581 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
582 numberOfResults
+= numberNameResults
;
586 // Taxa from common names
588 if (configurator
.isDoTaxaByCommonNames()) {
589 taxa
= new ArrayList
<TaxonBase
>();
590 numberTaxaResults
= 0;
591 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
592 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
594 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
595 List
<Object
[]> commonNameResults
= dao
.getTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
596 for( Object
[] entry
: commonNameResults
) {
597 taxa
.add((TaxonBase
) entry
[0]);
601 results
.addAll(taxa
);
603 numberOfResults
+= numberTaxaResults
;
607 return new DefaultPagerImpl
<IdentifiableEntity
>
608 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
611 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
612 return dao
.getUuidAndTitleCache();
616 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])
618 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
619 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
620 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
621 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
622 for (TaxonDescription taxDesc
: descriptions
){
623 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
624 for (DescriptionElementBase descElem
: elements
){
625 for(Media media
: descElem
.getMedia()){
627 //find the best matching representation
628 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, null, size
, height
, widthOrDuration
, mimeTypes
));
637 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)
639 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
640 return this.dao
.findById(listOfIDs
);
644 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)
646 public TaxonBase
findTaxonByUuid(UUID uuid
, List
<String
> propertyPaths
){
647 return this.dao
.findByUuid(uuid
, null ,propertyPaths
);
651 * @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()
653 public int countAllRelationships() {
654 return this.dao
.countAllRelationships();
661 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)
663 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
664 return this.dao
.findIdenticalTaxonNames(propertyPath
);
669 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)
672 public void deleteTaxon(Taxon taxon
, TaxonDeletionConfigurator config
) throws ReferencedObjectUndeletableException
{
674 config
= new TaxonDeletionConfigurator();
678 if (! config
.isDeleteTaxonNodes()){
679 if (taxon
.getTaxonNodes().size() > 0){
680 String message
= "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";
681 throw new ReferencedObjectUndeletableException(message
);
686 // SynonymRelationShip
687 if (config
.isDeleteSynonymRelations()){
688 boolean removeSynonymNameFromHomotypicalGroup
= false;
689 for (SynonymRelationship synRel
: taxon
.getSynonymRelations()){
690 Synonym synonym
= synRel
.getSynonym();
691 taxon
.removeSynonymRelation(synRel
, removeSynonymNameFromHomotypicalGroup
);
692 if (config
.isDeleteSynonymsIfPossible()){
694 boolean newHomotypicGroupIfNeeded
= true;
695 deleteSynonym(synonym
, taxon
, config
.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded
);
697 deleteSynonymRelationships(synonym
, taxon
);
703 if (! config
.isDeleteTaxonRelationships()){
704 if (taxon
.getTaxonRelations().size() > 0){
705 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.";
706 throw new ReferencedObjectUndeletableException(message
);
712 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
714 for (TaxonDescription desc
: descriptions
){
715 if (config
.isDeleteDescriptions()){
716 //TODO use description delete configurator ?
717 //FIXME check if description is ALWAYS deletable
718 descriptionService
.delete(desc
);
720 if (desc
.getDescribedSpecimenOrObservations().size()>0){
721 String message
= "Taxon can't be deleted as it is used in a TaxonDescription" +
722 " which also describes specimens or abservations";
723 throw new ReferencedObjectUndeletableException(message
);
729 //check references with only reverse mapping
730 Set
<CdmBase
> referencingObjects
= genericDao
.getReferencingObjects(taxon
);
731 for (CdmBase referencingObject
: referencingObjects
){
732 //IIdentificationKeys (Media, Polytomous, MultiAccess)
733 if (HibernateProxyHelper
.isInstanceOf(referencingObject
, IIdentificationKey
.class)){
734 String message
= "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";
735 message
= String
.format(message
, CdmBase
.deproxy(referencingObject
, DerivedUnitBase
.class).getTitleCache());
736 throw new ReferencedObjectUndeletableException(message
);
741 if (referencingObject
.isInstanceOf(PolytomousKeyNode
.class)){
742 String message
= "Taxon can't be deleted as it is used in polytomous key node";
743 throw new ReferencedObjectUndeletableException(message
);
747 if (referencingObject
.isInstanceOf(TaxonInteraction
.class)){
748 String message
= "Taxon can't be deleted as it is used in taxonInteraction#taxon2";
749 throw new ReferencedObjectUndeletableException(message
);
755 if (config
.isDeleteNameIfPossible()){
757 nameService
.delete(taxon
.getName(), config
.getNameDeletionConfig());
758 } catch (ReferencedObjectUndeletableException e
) {
760 if (logger
.isDebugEnabled()){logger
.debug("Name could not be deleted");}
767 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)
769 @Transactional(readOnly
= false)
771 public void deleteSynonym(Synonym synonym
, Taxon taxon
, boolean removeNameIfPossible
,boolean newHomotypicGroupIfNeeded
) {
772 if (synonym
== null){
775 synonym
= CdmBase
.deproxy(dao
.merge(synonym
), Synonym
.class);
777 //remove synonymRelationship
778 Set
<Taxon
> taxonSet
= new HashSet
<Taxon
>();
782 taxonSet
.addAll(synonym
.getAcceptedTaxa());
784 for (Taxon relatedTaxon
: taxonSet
){
785 // dao.deleteSynonymRelationships(synonym, relatedTaxon);
786 relatedTaxon
.removeSynonym(synonym
, newHomotypicGroupIfNeeded
);
788 this.saveOrUpdate(synonym
);
790 //TODO remove name from homotypical group?
792 //remove synonym (if necessary)
793 if (synonym
.getSynonymRelations().isEmpty()){
794 TaxonNameBase
<?
,?
> name
= synonym
.getName();
795 synonym
.setName(null);
798 //remove name if possible (and required)
799 if (name
!= null && removeNameIfPossible
){
801 nameService
.delete(name
, new NameDeletionConfigurator());
802 }catch (DataChangeNoRollbackException ex
){
803 if (logger
.isDebugEnabled())logger
.debug("Name wasn't deleted as it is referenced");
811 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)
813 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
815 return this.dao
.findIdenticalNamesNew(propertyPath
);
819 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
821 public String
getPhylumName(TaxonNameBase name
){
822 return this.dao
.getPhylumName(name
);
826 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
828 public long deleteSynonymRelationships(Synonym syn
, Taxon taxon
) {
829 return dao
.deleteSynonymRelationships(syn
, taxon
);
833 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)
835 public long deleteSynonymRelationships(Synonym syn
) {
836 return dao
.deleteSynonymRelationships(syn
, null);
841 * @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)
843 public List
<SynonymRelationship
> listSynonymRelationships(
844 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
845 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
846 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
848 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
849 if(numberOfResults
> 0) { // no point checking again
850 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
856 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingTaxon(java.lang.String)
859 public Taxon
findBestMatchingTaxon(String taxonName
) {
860 MatchingTaxonConfigurator config
= MatchingTaxonConfigurator
.NewInstance();
861 config
.setTaxonNameTitle(taxonName
);
862 return findBestMatchingTaxon(config
);
868 public Taxon
findBestMatchingTaxon(MatchingTaxonConfigurator config
) {
870 Taxon bestCandidate
= null;
872 // 1. search for acceptet taxa
873 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(true, false, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
874 boolean bestCandidateMatchesSecUuid
= false;
875 boolean bestCandidateIsInClassification
= false;
876 int countEqualCandidates
= 0;
877 for(TaxonBase taxonBaseCandidate
: taxonList
){
878 if(taxonBaseCandidate
instanceof Taxon
){
879 Taxon newCanditate
= CdmBase
.deproxy(taxonBaseCandidate
, Taxon
.class);
880 boolean newCandidateMatchesSecUuid
= isMatchesSecUuid(newCanditate
, config
);
881 if (! newCandidateMatchesSecUuid
&& config
.isOnlyMatchingSecUuid() ){
883 }else if(newCandidateMatchesSecUuid
&& ! bestCandidateMatchesSecUuid
){
884 bestCandidate
= newCanditate
;
885 countEqualCandidates
= 1;
886 bestCandidateMatchesSecUuid
= true;
890 boolean newCandidateInClassification
= isInClassification(newCanditate
, config
);
891 if (! newCandidateInClassification
&& config
.isOnlyMatchingClassificationUuid()){
893 }else if (newCandidateInClassification
&& ! bestCandidateIsInClassification
){
894 bestCandidate
= newCanditate
;
895 countEqualCandidates
= 1;
896 bestCandidateIsInClassification
= true;
899 if (bestCandidate
== null){
900 bestCandidate
= newCanditate
;
901 countEqualCandidates
= 1;
905 }else{ //not Taxon.class
908 countEqualCandidates
++;
911 if (bestCandidate
!= null){
912 if(countEqualCandidates
> 1){
913 logger
.info(countEqualCandidates
+ " equally matching TaxonBases found, using first accepted Taxon: " + bestCandidate
.getTitleCache());
914 return bestCandidate
;
916 logger
.info("using accepted Taxon: " + bestCandidate
.getTitleCache());
917 return bestCandidate
;
922 // 2. search for synonyms
923 if (config
.isIncludeSynonyms()){
924 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
925 for(TaxonBase taxonBase
: synonymList
){
926 if(taxonBase
instanceof Synonym
){
927 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
928 Set
<Taxon
> acceptetdCandidates
= synonym
.getAcceptedTaxa();
929 if(!acceptetdCandidates
.isEmpty()){
930 bestCandidate
= acceptetdCandidates
.iterator().next();
931 if(acceptetdCandidates
.size() == 1){
932 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + bestCandidate
.getTitleCache());
933 return bestCandidate
;
935 logger
.info("using accepted Taxon " + bestCandidate
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
936 return bestCandidate
;
938 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
944 } catch (Exception e
){
948 return bestCandidate
;
951 private boolean isInClassification(Taxon taxon
, MatchingTaxonConfigurator config
) {
952 UUID configClassificationUuid
= config
.getClassificationUuid();
953 if (configClassificationUuid
== null){
956 for (TaxonNode node
: taxon
.getTaxonNodes()){
957 UUID classUuid
= node
.getClassification().getUuid();
958 if (configClassificationUuid
.equals(classUuid
)){
965 private boolean isMatchesSecUuid(Taxon taxon
, MatchingTaxonConfigurator config
) {
966 UUID configSecUuid
= config
.getSecUuid();
967 if (configSecUuid
== null){
970 UUID taxonSecUuid
= (taxon
.getSec() == null)?
null : taxon
.getSec().getUuid();
971 return configSecUuid
.equals(taxonSecUuid
);
975 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
978 public Synonym
findBestMatchingSynonym(String taxonName
) {
979 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
980 if(! synonymList
.isEmpty()){
981 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
982 if(synonymList
.size() == 1){
983 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
986 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());
995 * @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)
998 public SynonymRelationship
moveSynonymToAnotherTaxon(SynonymRelationship oldSynonymRelation
, Taxon newTaxon
, boolean moveHomotypicGroup
,
999 SynonymRelationshipType newSynonymRelationshipType
, Reference reference
, String referenceDetail
, boolean keepReference
) throws HomotypicalGroupChangeException
{
1001 Synonym synonym
= oldSynonymRelation
.getSynonym();
1002 Taxon fromTaxon
= oldSynonymRelation
.getAcceptedTaxon();
1003 //TODO what if there is no name ?? Concepts may be cached (e.g. via TCS import)
1004 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
1005 TaxonNameBase
<?
,?
> fromTaxonName
= fromTaxon
.getName();
1006 //set default relationship type
1007 if (newSynonymRelationshipType
== null){
1008 newSynonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
1010 boolean newRelTypeIsHomotypic
= newSynonymRelationshipType
.equals(SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF());
1012 HomotypicalGroup homotypicGroup
= synonymName
.getHomotypicalGroup();
1013 int hgSize
= homotypicGroup
.getTypifiedNames().size();
1014 boolean isSingleInGroup
= !(hgSize
> 1);
1016 if (! isSingleInGroup
){
1017 boolean isHomotypicToAccepted
= synonymName
.isHomotypic(fromTaxonName
);
1018 boolean hasHomotypicSynonymRelatives
= isHomotypicToAccepted ? hgSize
> 2 : hgSize
> 1;
1019 if (isHomotypicToAccepted
){
1020 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.";
1021 String homotypicRelatives
= hasHomotypicSynonymRelatives ?
" and other synonym(s)":"";
1022 message
= String
.format(message
, homotypicRelatives
);
1023 throw new HomotypicalGroupChangeException(message
);
1025 if (! moveHomotypicGroup
){
1026 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.";
1027 throw new HomotypicalGroupChangeException(message
);
1030 moveHomotypicGroup
= true; //single synonym always allows to moveCompleteGroup
1032 // Assert.assertTrue("Synonym can only be moved with complete homotypic group", moveHomotypicGroup);
1034 SynonymRelationship result
= null;
1035 //move all synonyms to new taxon
1036 List
<Synonym
> homotypicSynonyms
= fromTaxon
.getSynonymsInGroup(homotypicGroup
);
1037 for (Synonym syn
: homotypicSynonyms
){
1038 Set
<SynonymRelationship
> synRelations
= syn
.getSynonymRelations();
1039 for (SynonymRelationship synRelation
: synRelations
){
1040 if (fromTaxon
.equals(synRelation
.getAcceptedTaxon())){
1041 Reference
<?
> newReference
= reference
;
1042 if (newReference
== null && keepReference
){
1043 newReference
= synRelation
.getCitation();
1045 String newRefDetail
= referenceDetail
;
1046 if (newRefDetail
== null && keepReference
){
1047 newRefDetail
= synRelation
.getCitationMicroReference();
1049 SynonymRelationship newSynRelation
= newTaxon
.addSynonym(syn
, newSynonymRelationshipType
, newReference
, newRefDetail
);
1050 fromTaxon
.removeSynonymRelation(synRelation
, false);
1052 //change homotypic group of synonym if relType is 'homotypic'
1053 // if (newRelTypeIsHomotypic){
1054 // newTaxon.getName().getHomotypicalGroup().addTypifiedName(syn.getName());
1057 if (synRelation
.equals(oldSynonymRelation
)){
1058 result
= newSynRelation
;
1064 saveOrUpdate(newTaxon
);
1065 //Assert that there is a result
1066 if (result
== null){
1067 String message
= "Old synonym relation could not be transformed into new relation. This should not happen.";
1068 throw new IllegalStateException(message
);
1074 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
1077 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheTaxon() {
1078 return dao
.getUuidAndTitleCacheTaxon();
1082 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
1085 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheSynonym() {
1086 return dao
.getUuidAndTitleCacheSynonym();
1090 public Pager
<SearchResult
<TaxonBase
>> findByDescriptionElementFullText(Class
<?
extends DescriptionElementBase
> clazz
, String queryString
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
1091 List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1093 String luceneQueryTemplate
= "titleCache:%1$s OR text.ALL:%1$s OR name:%1$s";
1094 String luceneQuery
= String
.format(luceneQueryTemplate
, queryString
);
1096 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), clazz
);
1097 TopDocs topDocsResultSet
= luceneSearch
.executeSearch(luceneQuery
);
1098 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSetFromIds(luceneSearch
, topDocsResultSet
, dao
, "inDescription.taxon.id");
1100 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, searchResults
.size(), pageSize
, searchResults
);
1104 public List
<Synonym
> createInferredSynonyms(Taxon taxon
, Classification classification
, SynonymRelationshipType type
, boolean doWithMisappliedNames
){
1105 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1106 List
<Synonym
> inferredSynonymsToBeRemoved
= new ArrayList
<Synonym
>();
1108 HashMap
<UUID
, ZoologicalName
> zooHashMap
= new HashMap
<UUID
, ZoologicalName
>();
1111 UUID uuid
= taxon
.getName().getUuid();
1112 ZoologicalName taxonName
= getZoologicalName(uuid
, zooHashMap
);
1113 String epithetOfTaxon
= null;
1114 String infragenericEpithetOfTaxon
= null;
1115 String infraspecificEpithetOfTaxon
= null;
1116 if (taxonName
.isSpecies()){
1117 epithetOfTaxon
= taxonName
.getSpecificEpithet();
1118 } else if (taxonName
.isInfraGeneric()){
1119 infragenericEpithetOfTaxon
= taxonName
.getInfraGenericEpithet();
1120 } else if (taxonName
.isInfraSpecific()){
1121 infraspecificEpithetOfTaxon
= taxonName
.getInfraSpecificEpithet();
1123 String genusOfTaxon
= taxonName
.getGenusOrUninomial();
1124 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1125 List
<String
> taxonNames
= new ArrayList
<String
>();
1127 for (TaxonNode node
: nodes
){
1128 // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName
1129 // List<String> synonymsEpithet = new ArrayList<String>();
1131 if (node
.getClassification().equals(classification
)){
1132 if (!node
.isTopmostNode()){
1133 TaxonNode parent
= (TaxonNode
)node
.getParent();
1134 parent
= (TaxonNode
)HibernateProxyHelper
.deproxy(parent
);
1135 TaxonNameBase parentName
= parent
.getTaxon().getName();
1136 ZoologicalName zooParentName
= HibernateProxyHelper
.deproxy(parentName
, ZoologicalName
.class);
1137 Taxon parentTaxon
= (Taxon
)HibernateProxyHelper
.deproxy(parent
.getTaxon());
1138 Rank rankOfTaxon
= taxonName
.getRank();
1141 //create inferred synonyms for species, subspecies
1142 if ((parentName
.isGenus() || parentName
.isSpecies() || parentName
.getRank().equals(Rank
.SUBGENUS())) ){
1144 Synonym inferredEpithet
= null;
1145 Synonym inferredGenus
= null;
1146 Synonym potentialCombination
= null;
1148 List
<String
> propertyPaths
= new ArrayList
<String
>();
1149 propertyPaths
.add("synonym");
1150 propertyPaths
.add("synonym.name");
1151 List
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
1152 orderHints
.add(new OrderHint("relatedFrom.titleCache", SortOrder
.ASCENDING
));
1154 List
<SynonymRelationship
> synonymRelationshipsOfParent
= dao
.getSynonyms(parentTaxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1155 List
<SynonymRelationship
> synonymRelationshipsOfTaxon
= dao
.getSynonyms(taxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1157 List
<TaxonRelationship
> taxonRelListParent
= null;
1158 List
<TaxonRelationship
> taxonRelListTaxon
= null;
1159 if (doWithMisappliedNames
){
1160 taxonRelListParent
= dao
.getTaxonRelationships(parentTaxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1161 taxonRelListTaxon
= dao
.getTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1165 if (type
.equals(SynonymRelationshipType
.INFERRED_EPITHET_OF())){
1166 Set
<String
> genusNames
= new HashSet
<String
>();
1168 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1169 Synonym syn
= synonymRelationOfParent
.getSynonym();
1171 inferredEpithet
= createInferredEpithets(taxon
,
1172 zooHashMap
, taxonName
, epithetOfTaxon
,
1173 infragenericEpithetOfTaxon
,
1174 infraspecificEpithetOfTaxon
,
1175 taxonNames
, parentName
,
1179 inferredSynonyms
.add(inferredEpithet
);
1180 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1181 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1184 if (doWithMisappliedNames
){
1186 for (TaxonRelationship taxonRelationship
: taxonRelListParent
){
1187 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1189 inferredEpithet
= createInferredEpithets(taxon
,
1190 zooHashMap
, taxonName
, epithetOfTaxon
,
1191 infragenericEpithetOfTaxon
,
1192 infraspecificEpithetOfTaxon
,
1193 taxonNames
, parentName
,
1196 inferredSynonyms
.add(inferredEpithet
);
1197 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1198 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1202 if (!taxonNames
.isEmpty()){
1203 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1204 ZoologicalName name
;
1205 if (!synNotInCDM
.isEmpty()){
1206 inferredSynonymsToBeRemoved
.clear();
1208 for (Synonym syn
:inferredSynonyms
){
1209 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1210 if (!synNotInCDM
.contains(name
.getNameCache())){
1211 inferredSynonymsToBeRemoved
.add(syn
);
1215 // Remove identified Synonyms from inferredSynonyms
1216 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1217 inferredSynonyms
.remove(synonym
);
1222 }else if (type
.equals(SynonymRelationshipType
.INFERRED_GENUS_OF())){
1225 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1226 TaxonNameBase synName
;
1227 ZoologicalName inferredSynName
;
1229 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1230 inferredGenus
= createInferredGenus(taxon
,
1231 zooHashMap
, taxonName
, epithetOfTaxon
,
1232 genusOfTaxon
, taxonNames
, zooParentName
, syn
);
1234 inferredSynonyms
.add(inferredGenus
);
1235 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1236 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1241 if (doWithMisappliedNames
){
1243 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1244 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1245 inferredGenus
= createInferredGenus(taxon
, zooHashMap
, taxonName
, infraspecificEpithetOfTaxon
, genusOfTaxon
, taxonNames
, zooParentName
, misappliedName
);
1247 inferredSynonyms
.add(inferredGenus
);
1248 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1249 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1254 if (!taxonNames
.isEmpty()){
1255 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1256 ZoologicalName name
;
1257 if (!synNotInCDM
.isEmpty()){
1258 inferredSynonymsToBeRemoved
.clear();
1260 for (Synonym syn
:inferredSynonyms
){
1261 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1262 if (!synNotInCDM
.contains(name
.getNameCache())){
1263 inferredSynonymsToBeRemoved
.add(syn
);
1267 // Remove identified Synonyms from inferredSynonyms
1268 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1269 inferredSynonyms
.remove(synonym
);
1274 }else if (type
.equals(SynonymRelationshipType
.POTENTIAL_COMBINATION_OF())){
1276 Reference sourceReference
= null; // TODO: Determination of sourceReference is redundant
1277 ZoologicalName inferredSynName
;
1278 //for all synonyms of the parent...
1279 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1280 TaxonNameBase synName
;
1281 Synonym synParent
= synonymRelationOfParent
.getSynonym();
1282 synName
= synParent
.getName();
1284 HibernateProxyHelper
.deproxy(synParent
);
1286 // Set the sourceReference
1287 sourceReference
= synParent
.getSec();
1289 // Determine the idInSource
1290 String idInSourceParent
= getIdInSource(synParent
);
1292 ZoologicalName parentSynZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1293 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1294 String synParentInfragenericName
= null;
1295 String synParentSpecificEpithet
= null;
1297 if (parentSynZooName
.isInfraGeneric()){
1298 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1300 if (parentSynZooName
.isSpecies()){
1301 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1304 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1305 synonymsGenus.put(synGenusName, idInSource);
1308 //for all synonyms of the taxon
1310 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1312 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1313 ZoologicalName zooSynName
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1314 potentialCombination
= createPotentialCombination(idInSourceParent
, parentSynZooName
, zooSynName
,
1316 synParentInfragenericName
,
1317 synParentSpecificEpithet
, syn
, zooHashMap
);
1319 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1320 inferredSynonyms
.add(potentialCombination
);
1321 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1322 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1329 if (doWithMisappliedNames
){
1331 for (TaxonRelationship parentRelationship
: taxonRelListParent
){
1333 TaxonNameBase misappliedParentName
;
1335 Taxon misappliedParent
= parentRelationship
.getFromTaxon();
1336 misappliedParentName
= misappliedParent
.getName();
1338 HibernateProxyHelper
.deproxy(misappliedParent
);
1340 // Set the sourceReference
1341 sourceReference
= misappliedParent
.getSec();
1343 // Determine the idInSource
1344 String idInSourceParent
= getIdInSource(misappliedParent
);
1346 ZoologicalName parentSynZooName
= getZoologicalName(misappliedParentName
.getUuid(), zooHashMap
);
1347 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1348 String synParentInfragenericName
= null;
1349 String synParentSpecificEpithet
= null;
1351 if (parentSynZooName
.isInfraGeneric()){
1352 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1354 if (parentSynZooName
.isSpecies()){
1355 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1359 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1360 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1361 ZoologicalName zooMisappliedName
= getZoologicalName(misappliedName
.getName().getUuid(), zooHashMap
);
1362 potentialCombination
= createPotentialCombination(
1363 idInSourceParent
, parentSynZooName
, zooMisappliedName
,
1365 synParentInfragenericName
,
1366 synParentSpecificEpithet
, misappliedName
, zooHashMap
);
1369 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1370 inferredSynonyms
.add(potentialCombination
);
1371 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1372 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1377 if (!taxonNames
.isEmpty()){
1378 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1379 ZoologicalName name
;
1380 if (!synNotInCDM
.isEmpty()){
1381 inferredSynonymsToBeRemoved
.clear();
1382 for (Synonym syn
:inferredSynonyms
){
1384 name
= (ZoologicalName
) syn
.getName();
1385 }catch (ClassCastException e
){
1386 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1388 if (!synNotInCDM
.contains(name
.getNameCache())){
1389 inferredSynonymsToBeRemoved
.add(syn
);
1392 // Remove identified Synonyms from inferredSynonyms
1393 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1394 inferredSynonyms
.remove(synonym
);
1400 logger
.info("The synonymrelationship type is not defined.");
1401 return inferredSynonyms
;
1408 return inferredSynonyms
;
1411 private Synonym
createPotentialCombination(String idInSourceParent
,
1412 ZoologicalName parentSynZooName
, ZoologicalName zooSynName
, String synParentGenus
,
1413 String synParentInfragenericName
, String synParentSpecificEpithet
,
1414 TaxonBase syn
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1415 Synonym potentialCombination
;
1416 Reference sourceReference
;
1417 ZoologicalName inferredSynName
;
1418 HibernateProxyHelper
.deproxy(syn
);
1420 // Set sourceReference
1421 sourceReference
= syn
.getSec();
1424 String synTaxonSpecificEpithet
= zooSynName
.getSpecificEpithet();
1426 String synTaxonInfraSpecificName
= null;
1428 if (parentSynZooName
.isSpecies()){
1429 synTaxonInfraSpecificName
= zooSynName
.getInfraSpecificEpithet();
1432 /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){
1433 synonymsEpithet.add(epithetName);
1436 //create potential combinations...
1437 inferredSynName
= ZoologicalName
.NewInstance(syn
.getName().getRank());
1439 inferredSynName
.setGenusOrUninomial(synParentGenus
);
1440 if (zooSynName
.isSpecies()){
1441 inferredSynName
.setSpecificEpithet(synTaxonSpecificEpithet
);
1442 if (parentSynZooName
.isInfraGeneric()){
1443 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1446 if (zooSynName
.isInfraSpecific()){
1447 inferredSynName
.setSpecificEpithet(synParentSpecificEpithet
);
1448 inferredSynName
.setInfraSpecificEpithet(synTaxonInfraSpecificName
);
1450 if (parentSynZooName
.isInfraGeneric()){
1451 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1455 potentialCombination
= Synonym
.NewInstance(inferredSynName
, null);
1457 // Set the sourceReference
1458 potentialCombination
.setSec(sourceReference
);
1461 // Determine the idInSource
1462 String idInSourceSyn
= getIdInSource(syn
);
1464 if (idInSourceParent
!= null && idInSourceSyn
!= null) {
1465 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1466 inferredSynName
.addSource(originalSource
);
1467 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1468 potentialCombination
.addSource(originalSource
);
1471 inferredSynName
.generateTitle();
1473 return potentialCombination
;
1476 private Synonym
createInferredGenus(Taxon taxon
,
1477 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1478 String epithetOfTaxon
, String genusOfTaxon
,
1479 List
<String
> taxonNames
, ZoologicalName zooParentName
,
1482 Synonym inferredGenus
;
1483 TaxonNameBase synName
;
1484 ZoologicalName inferredSynName
;
1485 synName
=syn
.getName();
1486 HibernateProxyHelper
.deproxy(syn
);
1488 // Determine the idInSource
1489 String idInSourceSyn
= getIdInSource(syn
);
1490 String idInSourceTaxon
= getIdInSource(taxon
);
1491 // Determine the sourceReference
1492 Reference sourceReference
= syn
.getSec();
1494 synName
= syn
.getName();
1495 ZoologicalName synZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1496 String synSpeciesEpithetName
= synZooName
.getSpecificEpithet();
1497 /* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){
1498 synonymsEpithet.add(synSpeciesEpithetName);
1501 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1502 //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...
1505 inferredSynName
.setGenusOrUninomial(genusOfTaxon
);
1506 if (zooParentName
.isInfraGeneric()){
1507 inferredSynName
.setInfraGenericEpithet(zooParentName
.getInfraGenericEpithet());
1510 if (taxonName
.isSpecies()){
1511 inferredSynName
.setSpecificEpithet(synSpeciesEpithetName
);
1513 if (taxonName
.isInfraSpecific()){
1514 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
1515 inferredSynName
.setInfraSpecificEpithet(synZooName
.getInfraGenericEpithet());
1519 inferredGenus
= Synonym
.NewInstance(inferredSynName
, null);
1521 // Set the sourceReference
1522 inferredGenus
.setSec(sourceReference
);
1524 // Add the original source
1525 if (idInSourceSyn
!= null && idInSourceTaxon
!= null) {
1526 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
1527 inferredGenus
.addSource(originalSource
);
1529 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
1530 inferredSynName
.addSource(originalSource
);
1534 taxon
.addSynonym(inferredGenus
, SynonymRelationshipType
.INFERRED_GENUS_OF());
1536 inferredSynName
.generateTitle();
1539 return inferredGenus
;
1542 private Synonym
createInferredEpithets(Taxon taxon
,
1543 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1544 String epithetOfTaxon
, String infragenericEpithetOfTaxon
,
1545 String infraspecificEpithetOfTaxon
, List
<String
> taxonNames
,
1546 TaxonNameBase parentName
, TaxonBase syn
) {
1548 Synonym inferredEpithet
;
1549 TaxonNameBase synName
;
1550 ZoologicalName inferredSynName
;
1551 HibernateProxyHelper
.deproxy(syn
);
1553 // Determine the idInSource
1554 String idInSourceSyn
= getIdInSource(syn
);
1555 String idInSourceTaxon
= getIdInSource(taxon
);
1556 // Determine the sourceReference
1557 Reference sourceReference
= syn
.getSec();
1559 synName
= syn
.getName();
1560 ZoologicalName zooSynName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1561 String synGenusName
= zooSynName
.getGenusOrUninomial();
1562 String synInfraGenericEpithet
= null;
1563 String synSpecificEpithet
= null;
1565 if (zooSynName
.getInfraGenericEpithet() != null){
1566 synInfraGenericEpithet
= zooSynName
.getInfraGenericEpithet();
1569 if (zooSynName
.isInfraSpecific()){
1570 synSpecificEpithet
= zooSynName
.getSpecificEpithet();
1573 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1574 synonymsGenus.put(synGenusName, idInSource);
1577 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1579 // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!
1580 if (epithetOfTaxon
== null && infragenericEpithetOfTaxon
== null && infraspecificEpithetOfTaxon
== null) {
1581 logger
.error("This specificEpithet is NULL" + taxon
.getTitleCache());
1583 inferredSynName
.setGenusOrUninomial(synGenusName
);
1585 if (parentName
.isInfraGeneric()){
1586 inferredSynName
.setInfraGenericEpithet(synInfraGenericEpithet
);
1588 if (taxonName
.isSpecies()){
1589 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
1590 }else if (taxonName
.isInfraSpecific()){
1591 inferredSynName
.setSpecificEpithet(synSpecificEpithet
);
1592 inferredSynName
.setInfraSpecificEpithet(infraspecificEpithetOfTaxon
);
1595 inferredEpithet
= Synonym
.NewInstance(inferredSynName
, null);
1597 // Set the sourceReference
1598 inferredEpithet
.setSec(sourceReference
);
1600 /* Add the original source
1601 if (idInSource != null) {
1602 IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);
1605 Reference citation = getCitation(syn);
1606 if (citation != null) {
1607 originalSource.setCitation(citation);
1608 inferredEpithet.addSource(originalSource);
1611 String taxonId
= idInSourceTaxon
+ "; " + idInSourceSyn
;
1613 IdentifiableSource originalSource
;
1614 originalSource
= IdentifiableSource
.NewInstance(taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
1616 inferredEpithet
.addSource(originalSource
);
1618 originalSource
= IdentifiableSource
.NewInstance(taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
1620 inferredSynName
.addSource(originalSource
);
1624 taxon
.addSynonym(inferredEpithet
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
1626 inferredSynName
.generateTitle();
1627 return inferredEpithet
;
1631 * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.
1632 * Very likely only useful for createInferredSynonyms().
1637 private ZoologicalName
getZoologicalName(UUID uuid
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1638 ZoologicalName taxonName
=nameDao
.findZoologicalNameByUUID(uuid
);
1639 if (taxonName
== null) {
1640 taxonName
= zooHashMap
.get(uuid
);
1646 * Returns the idInSource for a given Synonym.
1649 private String
getIdInSource(TaxonBase taxonBase
) {
1650 String idInSource
= null;
1651 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
1652 if (sources
.size() == 1) {
1653 IdentifiableSource source
= sources
.iterator().next();
1654 if (source
!= null) {
1655 idInSource
= source
.getIdInSource();
1657 } else if (sources
.size() > 1) {
1660 for (IdentifiableSource source
: sources
) {
1661 idInSource
+= source
.getIdInSource();
1662 if (count
< sources
.size()) {
1674 * Returns the citation for a given Synonym.
1677 private Reference
getCitation(Synonym syn
) {
1678 Reference citation
= null;
1679 Set
<IdentifiableSource
> sources
= syn
.getSources();
1680 if (sources
.size() == 1) {
1681 IdentifiableSource source
= sources
.iterator().next();
1682 if (source
!= null) {
1683 citation
= source
.getCitation();
1685 } else if (sources
.size() > 1) {
1686 logger
.warn("This Synonym has more than one source: " + syn
.getUuid() + " (" + syn
.getTitleCache() +")");
1692 public List
<Synonym
> createAllInferredSynonyms(Taxon taxon
, Classification tree
, boolean doWithMisappliedNames
){
1693 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1695 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_EPITHET_OF(), doWithMisappliedNames
));
1696 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_GENUS_OF(), doWithMisappliedNames
));
1697 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames
));
1699 return inferredSynonyms
;