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
;
20 import java
.util
.UUID
;
22 import org
.apache
.log4j
.Logger
;
23 import org
.apache
.lucene
.index
.CorruptIndexException
;
24 import org
.apache
.lucene
.queryParser
.ParseException
;
25 import org
.apache
.lucene
.search
.BooleanClause
.Occur
;
26 import org
.apache
.lucene
.search
.BooleanQuery
;
27 import org
.apache
.lucene
.search
.Query
;
28 import org
.apache
.lucene
.search
.SortField
;
29 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
30 import org
.springframework
.stereotype
.Service
;
31 import org
.springframework
.transaction
.annotation
.Propagation
;
32 import org
.springframework
.transaction
.annotation
.Transactional
;
34 import eu
.etaxonomy
.cdm
.api
.service
.config
.IFindTaxaAndNamesConfigurator
;
35 import eu
.etaxonomy
.cdm
.api
.service
.config
.MatchingTaxonConfigurator
;
36 import eu
.etaxonomy
.cdm
.api
.service
.config
.NameDeletionConfigurator
;
37 import eu
.etaxonomy
.cdm
.api
.service
.config
.TaxonDeletionConfigurator
;
38 import eu
.etaxonomy
.cdm
.api
.service
.exception
.DataChangeNoRollbackException
;
39 import eu
.etaxonomy
.cdm
.api
.service
.exception
.HomotypicalGroupChangeException
;
40 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
41 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
42 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
43 import eu
.etaxonomy
.cdm
.api
.service
.search
.ISearchResultBuilder
;
44 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneMultiSearch
;
45 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
;
46 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
.TopGroupsWithMaxScore
;
47 import eu
.etaxonomy
.cdm
.api
.service
.search
.QueryFactory
;
48 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
49 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResultBuilder
;
50 import eu
.etaxonomy
.cdm
.api
.service
.util
.TaxonRelationshipEdge
;
51 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
52 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
53 import eu
.etaxonomy
.cdm
.hibernate
.search
.DefinedTermBaseClassBridge
;
54 import eu
.etaxonomy
.cdm
.hibernate
.search
.MultilanguageTextFieldBridge
;
55 import eu
.etaxonomy
.cdm
.model
.CdmBaseType
;
56 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
57 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
58 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
59 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
60 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
61 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
62 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
63 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
64 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
65 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
66 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
67 import eu
.etaxonomy
.cdm
.model
.description
.IIdentificationKey
;
68 import eu
.etaxonomy
.cdm
.model
.description
.PolytomousKeyNode
;
69 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
70 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
71 import eu
.etaxonomy
.cdm
.model
.description
.TaxonInteraction
;
72 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
73 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
74 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
75 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
76 import eu
.etaxonomy
.cdm
.model
.molecular
.DnaSample
;
77 import eu
.etaxonomy
.cdm
.model
.molecular
.Sequence
;
78 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
79 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
80 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
81 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
82 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnitBase
;
83 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
84 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
85 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
86 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
87 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
88 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
89 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
90 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
91 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
92 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
93 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
94 import eu
.etaxonomy
.cdm
.persistence
.dao
.AbstractBeanInitializer
;
95 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
96 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
97 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
98 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
99 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
100 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
101 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
102 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
103 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
.SortOrder
;
104 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
108 * @author a.kohlbecker
113 @Transactional(propagation
= Propagation
.SUPPORTS
, readOnly
= true)
114 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
115 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
117 public static final String POTENTIAL_COMBINATION_NAMESPACE
= "Potential combination";
119 public static final String INFERRED_EPITHET_NAMESPACE
= "Inferred epithet";
121 public static final String INFERRED_GENUS_NAMESPACE
= "Inferred genus";
125 private ITaxonNameDao nameDao
;
128 private INameService nameService
;
131 private ICdmGenericDao genericDao
;
134 private IDescriptionService descriptionService
;
137 private IOrderedTermVocabularyDao orderedVocabularyDao
;
140 private IOccurrenceDao occurrenceDao
;
143 private AbstractBeanInitializer beanInitializer
;
148 public TaxonServiceImpl(){
149 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
153 * FIXME Candidate for harmonization
154 * rename searchByName ?
157 public List
<TaxonBase
> searchTaxaByName(String name
, Reference sec
) {
158 return dao
.getTaxaByName(name
, sec
);
162 * FIXME Candidate for harmonization
163 * list(Synonym.class, ...)
165 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
168 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
169 return dao
.getAllSynonyms(limit
, start
);
173 * FIXME Candidate for harmonization
174 * list(Taxon.class, ...)
176 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
179 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
180 return dao
.getAllTaxa(limit
, start
);
184 * FIXME Candidate for harmonization
185 * merge with getRootTaxa(Reference sec, ..., ...)
187 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)
190 public List
<Taxon
> getRootTaxa(Reference sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
191 if (cdmFetch
== null){
192 cdmFetch
= CdmFetch
.NO_FETCH();
194 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
199 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
202 public List
<Taxon
> getRootTaxa(Rank rank
, Reference sec
, boolean onlyWithChildren
,boolean withMisapplications
, List
<String
> propertyPaths
) {
203 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
207 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)
210 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
211 return dao
.getAllRelationships(limit
, start
);
215 * FIXME Candidate for harmonization
216 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
220 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
222 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
223 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
224 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
225 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
226 return taxonRelTypeVocabulary
;
233 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
236 @Transactional(readOnly
= false)
237 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
239 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
240 synonymName
.removeTaxonBase(synonym
);
241 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
242 taxonName
.removeTaxonBase(acceptedTaxon
);
244 synonym
.setName(taxonName
);
245 acceptedTaxon
.setName(synonymName
);
247 // the accepted taxon needs a new uuid because the concept has changed
248 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
249 //acceptedTaxon.setUuid(UUID.randomUUID());
254 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
256 //TODO correct delete handling still needs to be implemented / checked
258 @Transactional(readOnly
= false)
259 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
, boolean deleteSynonym
, boolean copyCitationInfo
, Reference citation
, String microCitation
) throws HomotypicalGroupChangeException
{
261 TaxonNameBase
<?
,?
> acceptedName
= acceptedTaxon
.getName();
262 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
263 HomotypicalGroup synonymHomotypicGroup
= synonymName
.getHomotypicalGroup();
265 //check synonym is not homotypic
266 if (acceptedName
.getHomotypicalGroup().equals(synonymHomotypicGroup
)){
267 String message
= "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";
268 throw new HomotypicalGroupChangeException(message
);
271 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonymName
, acceptedTaxon
.getSec());
273 SynonymRelationshipType relTypeForGroup
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
274 List
<Synonym
> heteroSynonyms
= acceptedTaxon
.getSynonymsInGroup(synonymHomotypicGroup
);
276 for (Synonym heteroSynonym
: heteroSynonyms
){
277 if (synonym
.equals(heteroSynonym
)){
278 acceptedTaxon
.removeSynonym(heteroSynonym
, false);
280 //move synonyms in same homotypic group to new accepted taxon
281 heteroSynonym
.replaceAcceptedTaxon(newAcceptedTaxon
, relTypeForGroup
, copyCitationInfo
, citation
, microCitation
);
285 //synonym.getName().removeTaxonBase(synonym);
286 //TODO correct delete handling still needs to be implemented / checked
288 // deleteSynonym(synonym, taxon, false);
291 this.delete(synonym
);
293 } catch (Exception e
) {
294 logger
.info("Can't delete old synonym from database");
298 return newAcceptedTaxon
;
303 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, Reference citation
, String microcitation
){
305 // Get name from synonym
306 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
308 // remove synonym from taxon
309 toTaxon
.removeSynonym(synonym
);
311 // Create a taxon with synonym name
312 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
314 // Add taxon relation
315 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
317 // since we are swapping names, we have to detach the name from the synonym completely.
318 // Otherwise the synonym will still be in the list of typified names.
319 synonym
.getName().removeTaxonBase(synonym
);
326 * @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)
328 @Transactional(readOnly
= false)
330 public void changeHomotypicalGroupOfSynonym(Synonym synonym
, HomotypicalGroup newHomotypicalGroup
, Taxon targetTaxon
,
331 boolean removeFromOtherTaxa
, boolean setBasionymRelationIfApplicable
){
333 TaxonNameBase synonymName
= synonym
.getName();
334 HomotypicalGroup oldHomotypicalGroup
= synonymName
.getHomotypicalGroup();
338 oldHomotypicalGroup
.removeTypifiedName(synonymName
);
339 newHomotypicalGroup
.addTypifiedName(synonymName
);
341 //remove existing basionym relationships
342 synonymName
.removeBasionyms();
344 //add basionym relationship
345 if (setBasionymRelationIfApplicable
){
346 Set
<TaxonNameBase
> basionyms
= newHomotypicalGroup
.getBasionyms();
347 for (TaxonNameBase basionym
: basionyms
){
348 synonymName
.addBasionym(basionym
);
352 //set synonym relationship correctly
353 // SynonymRelationship relToTaxon = null;
354 boolean relToTargetTaxonExists
= false;
355 Set
<SynonymRelationship
> existingRelations
= synonym
.getSynonymRelations();
356 for (SynonymRelationship rel
: existingRelations
){
357 Taxon acceptedTaxon
= rel
.getAcceptedTaxon();
358 boolean isTargetTaxon
= acceptedTaxon
!= null && acceptedTaxon
.equals(targetTaxon
);
359 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
360 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
361 SynonymRelationshipType newRelationType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
362 rel
.setType(newRelationType
);
363 //TODO handle citation and microCitation
366 relToTargetTaxonExists
= true;
368 if (removeFromOtherTaxa
){
369 acceptedTaxon
.removeSynonym(synonym
, false);
375 if (targetTaxon
!= null && ! relToTargetTaxonExists
){
376 Taxon acceptedTaxon
= targetTaxon
;
377 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
378 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
379 SynonymRelationshipType relType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
380 //TODO handle citation and microCitation
381 Reference citation
= null;
382 String microCitation
= null;
383 acceptedTaxon
.addSynonym(synonym
, relType
, citation
, microCitation
);
390 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
393 @Transactional(readOnly
= false)
394 public void updateTitleCache(Class
<?
extends TaxonBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<TaxonBase
> cacheStrategy
, IProgressMonitor monitor
) {
396 clazz
= TaxonBase
.class;
398 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
403 protected void setDao(ITaxonDao dao
) {
408 * @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)
411 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
412 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
414 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
415 if(numberOfResults
> 0) { // no point checking again
416 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
419 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
423 * @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)
426 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
427 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
429 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
430 if(numberOfResults
> 0) { // no point checking again
431 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
438 * @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)
441 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
442 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
444 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
445 if(numberOfResults
> 0) { // no point checking again
446 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
452 * @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)
455 public Pager
<TaxonRelationship
> pageToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
456 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
458 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
459 if(numberOfResults
> 0) { // no point checking again
460 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
462 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
466 * @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)
469 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
470 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
472 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
473 if(numberOfResults
> 0) { // no point checking again
474 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
480 * @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)
483 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
484 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
486 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
487 if(numberOfResults
> 0) { // no point checking again
488 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
490 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
495 * @param includeRelationships
499 * @param propertyPaths
500 * @return an List which is not specifically ordered
503 public List
<Taxon
> listRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Integer maxDepth
,
504 Integer limit
, Integer start
, List
<String
> propertyPaths
) {
506 List
<Taxon
> relatedTaxa
= collectRelatedTaxa(taxon
, includeRelationships
, new ArrayList
<Taxon
>(), maxDepth
);
507 relatedTaxa
.remove(taxon
);
508 beanInitializer
.initializeAll(relatedTaxa
, propertyPaths
);
514 * recursively collect related taxa for the given <code>taxon</code> . The returned list will also include the
515 * <code>taxon</code> supplied as parameter.
518 * @param includeRelationships
520 * @param maxDepth can be <code>null</code> for infinite depth
523 private List
<Taxon
> collectRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, List
<Taxon
> taxa
, Integer maxDepth
) {
529 if(maxDepth
!= null) {
532 if(logger
.isDebugEnabled()){
533 logger
.debug("collecting related taxa for " + taxon
+ " with maxDepth=" + maxDepth
);
535 List
<TaxonRelationship
> taxonRelationships
= dao
.getTaxonRelationships(taxon
, null, null, null, null, null, null);
536 for (TaxonRelationship taxRel
: taxonRelationships
) {
539 if (taxRel
.getToTaxon() == null || taxRel
.getFromTaxon() == null || taxRel
.getType() == null) {
542 // filter by includeRelationships
543 for (TaxonRelationshipEdge relationshipEdgeFilter
: includeRelationships
) {
544 if ( relationshipEdgeFilter
.getTaxonRelationshipType().equals(taxRel
.getType()) ) {
545 if (relationshipEdgeFilter
.getDirections().contains(Direction
.relatedTo
) && !taxa
.contains(taxRel
.getToTaxon())) {
546 if(logger
.isDebugEnabled()){
547 logger
.debug(maxDepth
+ ": " + taxon
.getTitleCache() + " --[" + taxRel
.getType().getLabel() + "]--> " + taxRel
.getToTaxon().getTitleCache());
549 taxa
.add(taxRel
.getToTaxon());
550 if(maxDepth
== null || maxDepth
> 0) {
551 taxa
.addAll(collectRelatedTaxa(taxRel
.getToTaxon(), includeRelationships
, taxa
, maxDepth
));
554 if(relationshipEdgeFilter
.getDirections().contains(Direction
.relatedFrom
) && !taxa
.contains(taxRel
.getFromTaxon())) {
555 taxa
.add(taxRel
.getFromTaxon());
556 if(logger
.isDebugEnabled()){
557 logger
.debug(maxDepth
+ ": " +taxRel
.getFromTaxon().getTitleCache() + " --[" + taxRel
.getType().getLabel() + "]--> " + taxon
.getTitleCache() );
559 if(maxDepth
== null || maxDepth
> 0) {
560 taxa
.addAll(collectRelatedTaxa(taxRel
.getFromTaxon(), includeRelationships
, taxa
, maxDepth
));
570 * @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)
573 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
574 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
576 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
577 if(numberOfResults
> 0) { // no point checking again
578 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
581 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
585 * @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)
588 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
589 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
591 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
592 if(numberOfResults
> 0) { // no point checking again
593 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
596 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
600 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
603 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
604 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
605 return t
.getHomotypicSynonymsByHomotypicGroup();
609 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
612 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
613 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
614 List
<HomotypicalGroup
> homotypicalGroups
= t
.getHeterotypicSynonymyGroups();
615 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(homotypicalGroups
.size());
616 for(HomotypicalGroup homotypicalGroup
: homotypicalGroups
){
617 heterotypicSynonymyGroups
.add(t
.getSynonymsInGroup(homotypicalGroup
));
619 return heterotypicSynonymyGroups
;
623 public List
<UuidAndTitleCache
<TaxonBase
>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator
){
625 List
<UuidAndTitleCache
<TaxonBase
>> result
= new ArrayList
<UuidAndTitleCache
<TaxonBase
>>();
626 // Class<? extends TaxonBase> clazz = null;
627 // if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
628 // clazz = TaxonBase.class;
629 // //propertyPath.addAll(configurator.getTaxonPropertyPath());
630 // //propertyPath.addAll(configurator.getSynonymPropertyPath());
631 // } else if(configurator.isDoTaxa()) {
632 // clazz = Taxon.class;
633 // //propertyPath = configurator.getTaxonPropertyPath();
634 // } else if (configurator.isDoSynonyms()) {
635 // clazz = Synonym.class;
636 // //propertyPath = configurator.getSynonymPropertyPath();
640 result
= dao
.getTaxaByNameForEditor(configurator
.isDoTaxa(), configurator
.isDoSynonyms(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
645 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
648 public Pager
<IdentifiableEntity
> findTaxaAndNames(IFindTaxaAndNamesConfigurator configurator
) {
650 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
651 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
652 List
<TaxonBase
> taxa
= null;
655 long numberTaxaResults
= 0L;
658 List
<String
> propertyPath
= new ArrayList
<String
>();
659 if(configurator
.getTaxonPropertyPath() != null){
660 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
664 if (configurator
.isDoMisappliedNames() || configurator
.isDoSynonyms() || configurator
.isDoTaxa()){
665 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
667 dao
.countTaxaByName(configurator
.isDoTaxa(),configurator
.isDoSynonyms(), configurator
.isDoMisappliedNames(),
668 configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(),
669 configurator
.getNamedAreas());
672 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
673 taxa
= dao
.getTaxaByName(configurator
.isDoTaxa(), configurator
.isDoSynonyms(),
674 configurator
.isDoMisappliedNames(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(),
675 configurator
.getMatchMode(), configurator
.getNamedAreas(),
676 configurator
.getPageSize(), configurator
.getPageNumber(), propertyPath
);
680 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
683 results
.addAll(taxa
);
686 numberOfResults
+= numberTaxaResults
;
688 // Names without taxa
689 if (configurator
.isDoNamesWithoutTaxa()) {
690 int numberNameResults
= 0;
692 List
<?
extends TaxonNameBase
<?
,?
>> names
=
693 nameDao
.findByName(configurator
.getTitleSearchStringSqlized(), configurator
.getMatchMode(),
694 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
695 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
696 if (names
.size() > 0) {
697 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
698 if (taxonName
.getTaxonBases().size() == 0) {
699 results
.add(taxonName
);
703 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
704 numberOfResults
+= numberNameResults
;
708 // Taxa from common names
710 if (configurator
.isDoTaxaByCommonNames()) {
711 taxa
= new ArrayList
<TaxonBase
>();
712 numberTaxaResults
= 0;
713 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
714 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
716 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
717 List
<Object
[]> commonNameResults
= dao
.getTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
718 for( Object
[] entry
: commonNameResults
) {
719 taxa
.add((TaxonBase
) entry
[0]);
723 results
.addAll(taxa
);
725 numberOfResults
+= numberTaxaResults
;
729 return new DefaultPagerImpl
<IdentifiableEntity
>
730 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
733 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
734 return dao
.getUuidAndTitleCache();
738 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])
741 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
742 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
743 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
744 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
745 for (TaxonDescription taxDesc
: descriptions
){
746 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
747 for (DescriptionElementBase descElem
: elements
){
748 for(Media media
: descElem
.getMedia()){
750 //find the best matching representation
751 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, null, size
, height
, widthOrDuration
, mimeTypes
));
760 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxonDescriptionMedia(eu.etaxonomy.cdm.model.taxon.Taxon, boolean)
763 public List
<Media
> listTaxonDescriptionMedia(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, boolean limitToGalleries
, List
<String
> propertyPath
){
764 return listMedia(taxon
, includeRelationships
, limitToGalleries
, true, false, false, propertyPath
);
769 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listMedia(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, boolean, java.util.List)
772 public List
<Media
> listMedia(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
,
773 Boolean limitToGalleries
, Boolean includeTaxonDescriptions
, Boolean includeOccurrences
,
774 Boolean includeTaxonNameDescriptions
, List
<String
> propertyPath
) {
776 List
<Taxon
> taxa
= new ArrayList
<Taxon
>();
777 List
<Media
> taxonMedia
= new ArrayList
<Media
>();
779 if (limitToGalleries
== null) {
780 limitToGalleries
= false;
783 // --- resolve related taxa
784 if (includeRelationships
!= null) {
785 taxa
= listRelatedTaxa(taxon
, includeRelationships
, null, null, null, null);
788 taxa
.add((Taxon
) dao
.load(taxon
.getUuid()));
790 if(includeTaxonDescriptions
!= null && includeTaxonDescriptions
){
791 List
<TaxonDescription
> taxonDescriptions
= new ArrayList
<TaxonDescription
>();
792 // --- TaxonDescriptions
793 for (Taxon t
: taxa
) {
794 taxonDescriptions
.addAll(descriptionService
.listTaxonDescriptions(t
, null, null, null, null, propertyPath
));
796 for (TaxonDescription taxonDescription
: taxonDescriptions
) {
797 if (!limitToGalleries
|| taxonDescription
.isImageGallery()) {
798 for (DescriptionElementBase element
: taxonDescription
.getElements()) {
799 for (Media media
: element
.getMedia()) {
800 taxonMedia
.add(media
);
807 if(includeOccurrences
!= null && includeOccurrences
) {
808 Set
<SpecimenOrObservationBase
> specimensOrObservations
= new HashSet
<SpecimenOrObservationBase
>();
810 for (Taxon t
: taxa
) {
811 specimensOrObservations
.addAll(occurrenceDao
.listByAssociatedTaxon(null, t
, null, null, null, null));
813 for (SpecimenOrObservationBase occurrence
: specimensOrObservations
) {
815 taxonMedia
.addAll(occurrence
.getMedia());
817 // SpecimenDescriptions
818 Set
<SpecimenDescription
> specimenDescriptions
= occurrence
.getSpecimenDescriptions();
819 for (DescriptionBase specimenDescription
: specimenDescriptions
) {
820 if (!limitToGalleries
|| specimenDescription
.isImageGallery()) {
821 Set
<DescriptionElementBase
> elements
= specimenDescription
.getElements();
822 for (DescriptionElementBase element
: elements
) {
823 for (Media media
: element
.getMedia()) {
824 taxonMedia
.add(media
);
831 if (occurrence
instanceof DerivedUnitBase
) {
832 if (((DerivedUnitBase
) occurrence
).getCollection() != null){
833 taxonMedia
.addAll(((DerivedUnitBase
) occurrence
).getCollection().getMedia());
838 if (occurrence
instanceof DnaSample
) {
839 Set
<Sequence
> sequences
= ((DnaSample
) occurrence
).getSequences();
840 for (Sequence sequence
: sequences
) {
841 taxonMedia
.addAll(sequence
.getChromatograms());
848 if(includeTaxonNameDescriptions
!= null && includeTaxonNameDescriptions
) {
849 // --- TaxonNameDescription
850 Set
<TaxonNameDescription
> nameDescriptions
= new HashSet
<TaxonNameDescription
>();
851 for (Taxon t
: taxa
) {
852 nameDescriptions
.addAll(t
.getName().getDescriptions());
854 for(TaxonNameDescription nameDescription
: nameDescriptions
){
855 if (!limitToGalleries
|| nameDescription
.isImageGallery()) {
856 Set
<DescriptionElementBase
> elements
= nameDescription
.getElements();
857 for (DescriptionElementBase element
: elements
) {
858 for (Media media
: element
.getMedia()) {
859 taxonMedia
.add(media
);
866 beanInitializer
.initializeAll(taxonMedia
, propertyPath
);
871 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)
874 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
875 return this.dao
.listByIds(listOfIDs
, null, null, null, null);
879 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)
882 public TaxonBase
findTaxonByUuid(UUID uuid
, List
<String
> propertyPaths
){
883 return this.dao
.findByUuid(uuid
, null ,propertyPaths
);
887 * @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()
890 public int countAllRelationships() {
891 return this.dao
.countAllRelationships();
898 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)
901 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
902 return this.dao
.findIdenticalTaxonNames(propertyPath
);
907 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)
910 public void deleteTaxon(Taxon taxon
, TaxonDeletionConfigurator config
) throws ReferencedObjectUndeletableException
{
912 config
= new TaxonDeletionConfigurator();
916 if (! config
.isDeleteTaxonNodes()){
917 if (taxon
.getTaxonNodes().size() > 0){
918 String message
= "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";
919 throw new ReferencedObjectUndeletableException(message
);
924 // SynonymRelationShip
925 if (config
.isDeleteSynonymRelations()){
926 boolean removeSynonymNameFromHomotypicalGroup
= false;
927 for (SynonymRelationship synRel
: taxon
.getSynonymRelations()){
928 Synonym synonym
= synRel
.getSynonym();
929 taxon
.removeSynonymRelation(synRel
, removeSynonymNameFromHomotypicalGroup
);
930 if (config
.isDeleteSynonymsIfPossible()){
932 boolean newHomotypicGroupIfNeeded
= true;
933 deleteSynonym(synonym
, taxon
, config
.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded
);
935 deleteSynonymRelationships(synonym
, taxon
);
941 if (! config
.isDeleteTaxonRelationships()){
942 if (taxon
.getTaxonRelations().size() > 0){
943 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.";
944 throw new ReferencedObjectUndeletableException(message
);
950 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
952 for (TaxonDescription desc
: descriptions
){
953 if (config
.isDeleteDescriptions()){
954 //TODO use description delete configurator ?
955 //FIXME check if description is ALWAYS deletable
956 descriptionService
.delete(desc
);
958 if (desc
.getDescribedSpecimenOrObservations().size()>0){
959 String message
= "Taxon can't be deleted as it is used in a TaxonDescription" +
960 " which also describes specimens or abservations";
961 throw new ReferencedObjectUndeletableException(message
);
967 //check references with only reverse mapping
968 Set
<CdmBase
> referencingObjects
= genericDao
.getReferencingObjects(taxon
);
969 for (CdmBase referencingObject
: referencingObjects
){
970 //IIdentificationKeys (Media, Polytomous, MultiAccess)
971 if (HibernateProxyHelper
.isInstanceOf(referencingObject
, IIdentificationKey
.class)){
972 String message
= "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";
973 message
= String
.format(message
, CdmBase
.deproxy(referencingObject
, DerivedUnitBase
.class).getTitleCache());
974 throw new ReferencedObjectUndeletableException(message
);
979 if (referencingObject
.isInstanceOf(PolytomousKeyNode
.class)){
980 String message
= "Taxon can't be deleted as it is used in polytomous key node";
981 throw new ReferencedObjectUndeletableException(message
);
985 if (referencingObject
.isInstanceOf(TaxonInteraction
.class)){
986 String message
= "Taxon can't be deleted as it is used in taxonInteraction#taxon2";
987 throw new ReferencedObjectUndeletableException(message
);
993 if (config
.isDeleteNameIfPossible()){
995 nameService
.delete(taxon
.getName(), config
.getNameDeletionConfig());
996 } catch (ReferencedObjectUndeletableException e
) {
998 if (logger
.isDebugEnabled()){logger
.debug("Name could not be deleted");}
1005 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)
1007 @Transactional(readOnly
= false)
1009 public void deleteSynonym(Synonym synonym
, Taxon taxon
, boolean removeNameIfPossible
,boolean newHomotypicGroupIfNeeded
) {
1010 if (synonym
== null){
1013 synonym
= CdmBase
.deproxy(dao
.merge(synonym
), Synonym
.class);
1015 //remove synonymRelationship
1016 Set
<Taxon
> taxonSet
= new HashSet
<Taxon
>();
1018 taxonSet
.add(taxon
);
1020 taxonSet
.addAll(synonym
.getAcceptedTaxa());
1022 for (Taxon relatedTaxon
: taxonSet
){
1023 // dao.deleteSynonymRelationships(synonym, relatedTaxon);
1024 relatedTaxon
.removeSynonym(synonym
, newHomotypicGroupIfNeeded
);
1026 this.saveOrUpdate(synonym
);
1028 //TODO remove name from homotypical group?
1030 //remove synonym (if necessary)
1031 if (synonym
.getSynonymRelations().isEmpty()){
1032 TaxonNameBase
<?
,?
> name
= synonym
.getName();
1033 synonym
.setName(null);
1034 dao
.delete(synonym
);
1036 //remove name if possible (and required)
1037 if (name
!= null && removeNameIfPossible
){
1039 nameService
.delete(name
, new NameDeletionConfigurator());
1040 }catch (DataChangeNoRollbackException ex
){
1041 if (logger
.isDebugEnabled()) {
1042 logger
.debug("Name wasn't deleted as it is referenced");
1051 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)
1054 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
1056 return this.dao
.findIdenticalNamesNew(propertyPath
);
1060 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
1063 public String
getPhylumName(TaxonNameBase name
){
1064 return this.dao
.getPhylumName(name
);
1068 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
1071 public long deleteSynonymRelationships(Synonym syn
, Taxon taxon
) {
1072 return dao
.deleteSynonymRelationships(syn
, taxon
);
1076 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)
1079 public long deleteSynonymRelationships(Synonym syn
) {
1080 return dao
.deleteSynonymRelationships(syn
, null);
1085 * @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)
1088 public List
<SynonymRelationship
> listSynonymRelationships(
1089 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
1090 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
1091 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
1093 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
1094 if(numberOfResults
> 0) { // no point checking again
1095 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
1101 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingTaxon(java.lang.String)
1104 public Taxon
findBestMatchingTaxon(String taxonName
) {
1105 MatchingTaxonConfigurator config
= MatchingTaxonConfigurator
.NewInstance();
1106 config
.setTaxonNameTitle(taxonName
);
1107 return findBestMatchingTaxon(config
);
1113 public Taxon
findBestMatchingTaxon(MatchingTaxonConfigurator config
) {
1115 Taxon bestCandidate
= null;
1117 // 1. search for acceptet taxa
1118 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(true, false, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
1119 boolean bestCandidateMatchesSecUuid
= false;
1120 boolean bestCandidateIsInClassification
= false;
1121 int countEqualCandidates
= 0;
1122 for(TaxonBase taxonBaseCandidate
: taxonList
){
1123 if(taxonBaseCandidate
instanceof Taxon
){
1124 Taxon newCanditate
= CdmBase
.deproxy(taxonBaseCandidate
, Taxon
.class);
1125 boolean newCandidateMatchesSecUuid
= isMatchesSecUuid(newCanditate
, config
);
1126 if (! newCandidateMatchesSecUuid
&& config
.isOnlyMatchingSecUuid() ){
1128 }else if(newCandidateMatchesSecUuid
&& ! bestCandidateMatchesSecUuid
){
1129 bestCandidate
= newCanditate
;
1130 countEqualCandidates
= 1;
1131 bestCandidateMatchesSecUuid
= true;
1135 boolean newCandidateInClassification
= isInClassification(newCanditate
, config
);
1136 if (! newCandidateInClassification
&& config
.isOnlyMatchingClassificationUuid()){
1138 }else if (newCandidateInClassification
&& ! bestCandidateIsInClassification
){
1139 bestCandidate
= newCanditate
;
1140 countEqualCandidates
= 1;
1141 bestCandidateIsInClassification
= true;
1144 if (bestCandidate
== null){
1145 bestCandidate
= newCanditate
;
1146 countEqualCandidates
= 1;
1150 }else{ //not Taxon.class
1153 countEqualCandidates
++;
1156 if (bestCandidate
!= null){
1157 if(countEqualCandidates
> 1){
1158 logger
.info(countEqualCandidates
+ " equally matching TaxonBases found, using first accepted Taxon: " + bestCandidate
.getTitleCache());
1159 return bestCandidate
;
1161 logger
.info("using accepted Taxon: " + bestCandidate
.getTitleCache());
1162 return bestCandidate
;
1167 // 2. search for synonyms
1168 if (config
.isIncludeSynonyms()){
1169 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
1170 for(TaxonBase taxonBase
: synonymList
){
1171 if(taxonBase
instanceof Synonym
){
1172 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
1173 Set
<Taxon
> acceptetdCandidates
= synonym
.getAcceptedTaxa();
1174 if(!acceptetdCandidates
.isEmpty()){
1175 bestCandidate
= acceptetdCandidates
.iterator().next();
1176 if(acceptetdCandidates
.size() == 1){
1177 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + bestCandidate
.getTitleCache());
1178 return bestCandidate
;
1180 logger
.info("using accepted Taxon " + bestCandidate
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
1181 return bestCandidate
;
1183 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
1189 } catch (Exception e
){
1193 return bestCandidate
;
1196 private boolean isInClassification(Taxon taxon
, MatchingTaxonConfigurator config
) {
1197 UUID configClassificationUuid
= config
.getClassificationUuid();
1198 if (configClassificationUuid
== null){
1201 for (TaxonNode node
: taxon
.getTaxonNodes()){
1202 UUID classUuid
= node
.getClassification().getUuid();
1203 if (configClassificationUuid
.equals(classUuid
)){
1210 private boolean isMatchesSecUuid(Taxon taxon
, MatchingTaxonConfigurator config
) {
1211 UUID configSecUuid
= config
.getSecUuid();
1212 if (configSecUuid
== null){
1215 UUID taxonSecUuid
= (taxon
.getSec() == null)?
null : taxon
.getSec().getUuid();
1216 return configSecUuid
.equals(taxonSecUuid
);
1220 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
1223 public Synonym
findBestMatchingSynonym(String taxonName
) {
1224 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
1225 if(! synonymList
.isEmpty()){
1226 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
1227 if(synonymList
.size() == 1){
1228 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
1231 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());
1240 * @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)
1243 public SynonymRelationship
moveSynonymToAnotherTaxon(SynonymRelationship oldSynonymRelation
, Taxon newTaxon
, boolean moveHomotypicGroup
,
1244 SynonymRelationshipType newSynonymRelationshipType
, Reference reference
, String referenceDetail
, boolean keepReference
) throws HomotypicalGroupChangeException
{
1246 Synonym synonym
= oldSynonymRelation
.getSynonym();
1247 Taxon fromTaxon
= oldSynonymRelation
.getAcceptedTaxon();
1248 //TODO what if there is no name ?? Concepts may be cached (e.g. via TCS import)
1249 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
1250 TaxonNameBase
<?
,?
> fromTaxonName
= fromTaxon
.getName();
1251 //set default relationship type
1252 if (newSynonymRelationshipType
== null){
1253 newSynonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
1255 boolean newRelTypeIsHomotypic
= newSynonymRelationshipType
.equals(SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF());
1257 HomotypicalGroup homotypicGroup
= synonymName
.getHomotypicalGroup();
1258 int hgSize
= homotypicGroup
.getTypifiedNames().size();
1259 boolean isSingleInGroup
= !(hgSize
> 1);
1261 if (! isSingleInGroup
){
1262 boolean isHomotypicToAccepted
= synonymName
.isHomotypic(fromTaxonName
);
1263 boolean hasHomotypicSynonymRelatives
= isHomotypicToAccepted ? hgSize
> 2 : hgSize
> 1;
1264 if (isHomotypicToAccepted
){
1265 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.";
1266 String homotypicRelatives
= hasHomotypicSynonymRelatives ?
" and other synonym(s)":"";
1267 message
= String
.format(message
, homotypicRelatives
);
1268 throw new HomotypicalGroupChangeException(message
);
1270 if (! moveHomotypicGroup
){
1271 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.";
1272 throw new HomotypicalGroupChangeException(message
);
1275 moveHomotypicGroup
= true; //single synonym always allows to moveCompleteGroup
1277 // Assert.assertTrue("Synonym can only be moved with complete homotypic group", moveHomotypicGroup);
1279 SynonymRelationship result
= null;
1280 //move all synonyms to new taxon
1281 List
<Synonym
> homotypicSynonyms
= fromTaxon
.getSynonymsInGroup(homotypicGroup
);
1282 for (Synonym syn
: homotypicSynonyms
){
1283 Set
<SynonymRelationship
> synRelations
= syn
.getSynonymRelations();
1284 for (SynonymRelationship synRelation
: synRelations
){
1285 if (fromTaxon
.equals(synRelation
.getAcceptedTaxon())){
1286 Reference
<?
> newReference
= reference
;
1287 if (newReference
== null && keepReference
){
1288 newReference
= synRelation
.getCitation();
1290 String newRefDetail
= referenceDetail
;
1291 if (newRefDetail
== null && keepReference
){
1292 newRefDetail
= synRelation
.getCitationMicroReference();
1294 SynonymRelationship newSynRelation
= newTaxon
.addSynonym(syn
, newSynonymRelationshipType
, newReference
, newRefDetail
);
1295 fromTaxon
.removeSynonymRelation(synRelation
, false);
1297 //change homotypic group of synonym if relType is 'homotypic'
1298 // if (newRelTypeIsHomotypic){
1299 // newTaxon.getName().getHomotypicalGroup().addTypifiedName(syn.getName());
1302 if (synRelation
.equals(oldSynonymRelation
)){
1303 result
= newSynRelation
;
1309 saveOrUpdate(newTaxon
);
1310 //Assert that there is a result
1311 if (result
== null){
1312 String message
= "Old synonym relation could not be transformed into new relation. This should not happen.";
1313 throw new IllegalStateException(message
);
1319 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
1322 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheTaxon() {
1323 return dao
.getUuidAndTitleCacheTaxon();
1327 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
1330 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheSynonym() {
1331 return dao
.getUuidAndTitleCacheSynonym();
1335 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findByFullText(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
1338 public Pager
<SearchResult
<TaxonBase
>> findByFullText(
1339 Class
<?
extends TaxonBase
> clazz
, String queryString
,
1340 Classification classification
, List
<Language
> languages
,
1341 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1344 LuceneSearch luceneSearch
= prepareFindByFullTextSearch(clazz
, queryString
, classification
, languages
, highlightFragments
);
1346 // --- execute search
1347 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1349 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1350 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1352 // --- initialize taxa, thighlight matches ....
1353 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1354 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1355 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1357 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1358 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1363 * @param queryString
1364 * @param classification
1366 * @param highlightFragments
1367 * @param directorySelectClass
1370 protected LuceneSearch
prepareFindByFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Language
> languages
,
1371 boolean highlightFragments
) {
1372 BooleanQuery finalQuery
= new BooleanQuery();
1373 BooleanQuery textQuery
= new BooleanQuery();
1375 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), TaxonBase
.class);
1376 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1378 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("titleCache__sort", SortField
.STRING
, false)};
1379 luceneSearch
.setSortFields(sortFields
);
1381 // ---- search criteria
1382 luceneSearch
.setClazz(clazz
);
1384 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1385 textQuery
.add(queryFactory
.newDefinedTermQuery("name.rank", queryString
, languages
), Occur
.SHOULD
);
1387 finalQuery
.add(textQuery
, Occur
.MUST
);
1389 if(classification
!= null){
1390 finalQuery
.add(queryFactory
.newEntityIdQuery("taxonNodes.classification.id", classification
), Occur
.MUST
);
1392 luceneSearch
.setQuery(finalQuery
);
1394 if(highlightFragments
){
1395 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1397 return luceneSearch
;
1402 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findByDescriptionElementFullText(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.List, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
1405 public Pager
<SearchResult
<TaxonBase
>> findByDescriptionElementFullText(
1406 Class
<?
extends DescriptionElementBase
> clazz
, String queryString
,
1407 Classification classification
, List
<Feature
> features
, List
<Language
> languages
,
1408 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1411 LuceneSearch luceneSearch
= prepareByDescriptionElementFullTextSearch(clazz
, queryString
, classification
, features
, languages
, highlightFragments
);
1413 // --- execute search
1414 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1416 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1417 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1419 // --- initialize taxa, highlight matches ....
1420 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1421 @SuppressWarnings("rawtypes")
1422 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1423 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1425 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupCount
: 0;
1426 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1432 public Pager
<SearchResult
<TaxonBase
>> findByEverythingFullText(String queryString
,
1433 Classification classification
, List
<Language
> languages
, boolean highlightFragments
,
1434 Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1436 LuceneSearch luceneSearchByDescriptionElement
= prepareByDescriptionElementFullTextSearch(null, queryString
, classification
, null, languages
, highlightFragments
);
1437 LuceneSearch luceneSearchByTaxonBase
= prepareFindByFullTextSearch(null, queryString
, classification
, languages
, highlightFragments
);
1439 LuceneMultiSearch multiSearch
= new LuceneMultiSearch(luceneSearchByDescriptionElement
, luceneSearchByTaxonBase
);
1441 // --- execute search
1442 TopGroupsWithMaxScore topDocsResultSet
= multiSearch
.executeSearch(pageSize
, pageNumber
);
1444 // --- initialize taxa, highlight matches ....
1445 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(multiSearch
, multiSearch
.getQuery());
1447 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1448 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1449 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1451 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1452 topDocsResultSet
, multiSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1454 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1455 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1462 * @param queryString
1463 * @param classification
1466 * @param highlightFragments
1467 * @param directorySelectClass
1470 protected LuceneSearch
prepareByDescriptionElementFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Feature
> features
,
1471 List
<Language
> languages
, boolean highlightFragments
) {
1472 BooleanQuery finalQuery
= new BooleanQuery();
1473 BooleanQuery textQuery
= new BooleanQuery();
1475 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), DescriptionElementBase
.class);
1476 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1478 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("inDescription.taxon.titleCache__sort", SortField
.STRING
, false)};
1479 luceneSearch
.setSortFields(sortFields
);
1481 // ---- search criteria
1482 luceneSearch
.setClazz(clazz
);
1483 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1487 if(languages
== null || languages
.size() == 0){
1488 nameQuery
= queryFactory
.newTermQuery("name", queryString
);
1490 nameQuery
= new BooleanQuery();
1491 BooleanQuery languageSubQuery
= new BooleanQuery();
1492 for(Language lang
: languages
){
1493 languageSubQuery
.add(queryFactory
.newTermQuery("language.uuid", lang
.getUuid().toString()), Occur
.SHOULD
);
1495 ((BooleanQuery
) nameQuery
).add(queryFactory
.newTermQuery("name", queryString
), Occur
.MUST
);
1496 ((BooleanQuery
) nameQuery
).add(languageSubQuery
, Occur
.MUST
);
1498 textQuery
.add(nameQuery
, Occur
.SHOULD
);
1501 // text field from TextData
1502 textQuery
.add(queryFactory
.newMultilanguageTextQuery("text", queryString
, languages
), Occur
.SHOULD
);
1504 // --- TermBase fields - by representation ----
1505 // state field from CategoricalData
1506 textQuery
.add(queryFactory
.newDefinedTermQuery("states.state", queryString
, languages
), Occur
.SHOULD
);
1508 // state field from CategoricalData
1509 textQuery
.add(queryFactory
.newDefinedTermQuery("states.modifyingText", queryString
, languages
), Occur
.SHOULD
);
1511 // area field from Distribution
1512 textQuery
.add(queryFactory
.newDefinedTermQuery("area", queryString
, languages
), Occur
.SHOULD
);
1514 // status field from Distribution
1515 textQuery
.add(queryFactory
.newDefinedTermQuery("status", queryString
, languages
), Occur
.SHOULD
);
1517 finalQuery
.add(textQuery
, Occur
.MUST
);
1518 // --- classification ----
1520 if(classification
!= null){
1521 finalQuery
.add(queryFactory
.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification
), Occur
.MUST
);
1524 // --- IdentifieableEntity fields - by uuid
1525 if(features
!= null && features
.size() > 0 ){
1526 finalQuery
.add(queryFactory
.newEntityUuidQuery("feature.uuid", features
), Occur
.MUST
);
1529 // the description must be associated with a taxon
1530 finalQuery
.add(queryFactory
.newIsNotNullQuery("inDescription.taxon.id"), Occur
.MUST
);
1532 luceneSearch
.setQuery(finalQuery
);
1534 if(highlightFragments
){
1535 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1537 return luceneSearch
;
1541 * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}
1542 * and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.
1543 * This method is a convenient means to retrieve a Lucene query string for such the fields.
1545 * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}
1546 * or {@link MultilanguageTextFieldBridge }
1547 * @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages
1548 * @param stringBuilder a StringBuilder to be reused, if <code>null</code> a new StringBuilder will be instantiated and is returned
1549 * @return the StringBuilder given a parameter or a new one if the stringBuilder parameter was null.
1551 * TODO move to utiliy class !!!!!!!!
1553 private StringBuilder
appendLocalizedFieldQuery(String name
, List
<Language
> languages
, StringBuilder stringBuilder
) {
1555 if(stringBuilder
== null){
1556 stringBuilder
= new StringBuilder();
1558 if(languages
== null || languages
.size() == 0){
1559 stringBuilder
.append(name
+ ".ALL:(%1$s) ");
1561 for(Language lang
: languages
){
1562 stringBuilder
.append(name
+ "." + lang
.getUuid().toString() + ":(%1$s) ");
1565 return stringBuilder
;
1569 public List
<Synonym
> createInferredSynonyms(Taxon taxon
, Classification classification
, SynonymRelationshipType type
, boolean doWithMisappliedNames
){
1570 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1571 List
<Synonym
> inferredSynonymsToBeRemoved
= new ArrayList
<Synonym
>();
1573 HashMap
<UUID
, ZoologicalName
> zooHashMap
= new HashMap
<UUID
, ZoologicalName
>();
1576 UUID nameUuid
= taxon
.getName().getUuid();
1577 ZoologicalName taxonName
= getZoologicalName(nameUuid
, zooHashMap
);
1578 String epithetOfTaxon
= null;
1579 String infragenericEpithetOfTaxon
= null;
1580 String infraspecificEpithetOfTaxon
= null;
1581 if (taxonName
.isSpecies()){
1582 epithetOfTaxon
= taxonName
.getSpecificEpithet();
1583 } else if (taxonName
.isInfraGeneric()){
1584 infragenericEpithetOfTaxon
= taxonName
.getInfraGenericEpithet();
1585 } else if (taxonName
.isInfraSpecific()){
1586 infraspecificEpithetOfTaxon
= taxonName
.getInfraSpecificEpithet();
1588 String genusOfTaxon
= taxonName
.getGenusOrUninomial();
1589 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1590 List
<String
> taxonNames
= new ArrayList
<String
>();
1592 for (TaxonNode node
: nodes
){
1593 // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName
1594 // List<String> synonymsEpithet = new ArrayList<String>();
1596 if (node
.getClassification().equals(classification
)){
1597 if (!node
.isTopmostNode()){
1598 TaxonNode parent
= node
.getParent();
1599 parent
= (TaxonNode
)HibernateProxyHelper
.deproxy(parent
);
1600 TaxonNameBase
<?
,?
> parentName
= parent
.getTaxon().getName();
1601 ZoologicalName zooParentName
= HibernateProxyHelper
.deproxy(parentName
, ZoologicalName
.class);
1602 Taxon parentTaxon
= (Taxon
)HibernateProxyHelper
.deproxy(parent
.getTaxon());
1603 Rank rankOfTaxon
= taxonName
.getRank();
1606 //create inferred synonyms for species, subspecies
1607 if ((parentName
.isGenus() || parentName
.isSpecies() || parentName
.getRank().equals(Rank
.SUBGENUS())) ){
1609 Synonym inferredEpithet
= null;
1610 Synonym inferredGenus
= null;
1611 Synonym potentialCombination
= null;
1613 List
<String
> propertyPaths
= new ArrayList
<String
>();
1614 propertyPaths
.add("synonym");
1615 propertyPaths
.add("synonym.name");
1616 List
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
1617 orderHints
.add(new OrderHint("relatedFrom.titleCache", SortOrder
.ASCENDING
));
1619 List
<SynonymRelationship
> synonymRelationshipsOfParent
= dao
.getSynonyms(parentTaxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1620 List
<SynonymRelationship
> synonymRelationshipsOfTaxon
= dao
.getSynonyms(taxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1622 List
<TaxonRelationship
> taxonRelListParent
= null;
1623 List
<TaxonRelationship
> taxonRelListTaxon
= null;
1624 if (doWithMisappliedNames
){
1625 taxonRelListParent
= dao
.getTaxonRelationships(parentTaxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1626 taxonRelListTaxon
= dao
.getTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1630 if (type
.equals(SynonymRelationshipType
.INFERRED_EPITHET_OF())){
1633 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1634 Synonym syn
= synonymRelationOfParent
.getSynonym();
1636 inferredEpithet
= createInferredEpithets(taxon
,
1637 zooHashMap
, taxonName
, epithetOfTaxon
,
1638 infragenericEpithetOfTaxon
,
1639 infraspecificEpithetOfTaxon
,
1640 taxonNames
, parentName
,
1644 inferredSynonyms
.add(inferredEpithet
);
1645 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1646 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1649 if (doWithMisappliedNames
){
1651 for (TaxonRelationship taxonRelationship
: taxonRelListParent
){
1652 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1654 inferredEpithet
= createInferredEpithets(taxon
,
1655 zooHashMap
, taxonName
, epithetOfTaxon
,
1656 infragenericEpithetOfTaxon
,
1657 infraspecificEpithetOfTaxon
,
1658 taxonNames
, parentName
,
1661 inferredSynonyms
.add(inferredEpithet
);
1662 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1663 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1667 if (!taxonNames
.isEmpty()){
1668 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1669 ZoologicalName name
;
1670 if (!synNotInCDM
.isEmpty()){
1671 inferredSynonymsToBeRemoved
.clear();
1673 for (Synonym syn
:inferredSynonyms
){
1674 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1675 if (!synNotInCDM
.contains(name
.getNameCache())){
1676 inferredSynonymsToBeRemoved
.add(syn
);
1680 // Remove identified Synonyms from inferredSynonyms
1681 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1682 inferredSynonyms
.remove(synonym
);
1687 }else if (type
.equals(SynonymRelationshipType
.INFERRED_GENUS_OF())){
1690 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1691 TaxonNameBase synName
;
1692 ZoologicalName inferredSynName
;
1694 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1695 inferredGenus
= createInferredGenus(taxon
,
1696 zooHashMap
, taxonName
, epithetOfTaxon
,
1697 genusOfTaxon
, taxonNames
, zooParentName
, syn
);
1699 inferredSynonyms
.add(inferredGenus
);
1700 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1701 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1706 if (doWithMisappliedNames
){
1708 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1709 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1710 inferredGenus
= createInferredGenus(taxon
, zooHashMap
, taxonName
, infraspecificEpithetOfTaxon
, genusOfTaxon
, taxonNames
, zooParentName
, misappliedName
);
1712 inferredSynonyms
.add(inferredGenus
);
1713 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1714 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1719 if (!taxonNames
.isEmpty()){
1720 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1721 ZoologicalName name
;
1722 if (!synNotInCDM
.isEmpty()){
1723 inferredSynonymsToBeRemoved
.clear();
1725 for (Synonym syn
:inferredSynonyms
){
1726 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1727 if (!synNotInCDM
.contains(name
.getNameCache())){
1728 inferredSynonymsToBeRemoved
.add(syn
);
1732 // Remove identified Synonyms from inferredSynonyms
1733 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1734 inferredSynonyms
.remove(synonym
);
1739 }else if (type
.equals(SynonymRelationshipType
.POTENTIAL_COMBINATION_OF())){
1741 Reference sourceReference
= null; // TODO: Determination of sourceReference is redundant
1742 ZoologicalName inferredSynName
;
1743 //for all synonyms of the parent...
1744 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1745 TaxonNameBase synName
;
1746 Synonym synParent
= synonymRelationOfParent
.getSynonym();
1747 synName
= synParent
.getName();
1749 HibernateProxyHelper
.deproxy(synParent
);
1751 // Set the sourceReference
1752 sourceReference
= synParent
.getSec();
1754 // Determine the idInSource
1755 String idInSourceParent
= getIdInSource(synParent
);
1757 ZoologicalName parentSynZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1758 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1759 String synParentInfragenericName
= null;
1760 String synParentSpecificEpithet
= null;
1762 if (parentSynZooName
.isInfraGeneric()){
1763 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1765 if (parentSynZooName
.isSpecies()){
1766 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1769 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1770 synonymsGenus.put(synGenusName, idInSource);
1773 //for all synonyms of the taxon
1775 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1777 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1778 ZoologicalName zooSynName
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1779 potentialCombination
= createPotentialCombination(idInSourceParent
, parentSynZooName
, zooSynName
,
1781 synParentInfragenericName
,
1782 synParentSpecificEpithet
, syn
, zooHashMap
);
1784 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1785 inferredSynonyms
.add(potentialCombination
);
1786 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1787 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1794 if (doWithMisappliedNames
){
1796 for (TaxonRelationship parentRelationship
: taxonRelListParent
){
1798 TaxonNameBase misappliedParentName
;
1800 Taxon misappliedParent
= parentRelationship
.getFromTaxon();
1801 misappliedParentName
= misappliedParent
.getName();
1803 HibernateProxyHelper
.deproxy(misappliedParent
);
1805 // Set the sourceReference
1806 sourceReference
= misappliedParent
.getSec();
1808 // Determine the idInSource
1809 String idInSourceParent
= getIdInSource(misappliedParent
);
1811 ZoologicalName parentSynZooName
= getZoologicalName(misappliedParentName
.getUuid(), zooHashMap
);
1812 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1813 String synParentInfragenericName
= null;
1814 String synParentSpecificEpithet
= null;
1816 if (parentSynZooName
.isInfraGeneric()){
1817 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1819 if (parentSynZooName
.isSpecies()){
1820 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1824 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1825 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1826 ZoologicalName zooMisappliedName
= getZoologicalName(misappliedName
.getName().getUuid(), zooHashMap
);
1827 potentialCombination
= createPotentialCombination(
1828 idInSourceParent
, parentSynZooName
, zooMisappliedName
,
1830 synParentInfragenericName
,
1831 synParentSpecificEpithet
, misappliedName
, zooHashMap
);
1834 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1835 inferredSynonyms
.add(potentialCombination
);
1836 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1837 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1842 if (!taxonNames
.isEmpty()){
1843 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1844 ZoologicalName name
;
1845 if (!synNotInCDM
.isEmpty()){
1846 inferredSynonymsToBeRemoved
.clear();
1847 for (Synonym syn
:inferredSynonyms
){
1849 name
= (ZoologicalName
) syn
.getName();
1850 }catch (ClassCastException e
){
1851 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1853 if (!synNotInCDM
.contains(name
.getNameCache())){
1854 inferredSynonymsToBeRemoved
.add(syn
);
1857 // Remove identified Synonyms from inferredSynonyms
1858 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1859 inferredSynonyms
.remove(synonym
);
1865 logger
.info("The synonymrelationship type is not defined.");
1866 return inferredSynonyms
;
1873 return inferredSynonyms
;
1876 private Synonym
createPotentialCombination(String idInSourceParent
,
1877 ZoologicalName parentSynZooName
, ZoologicalName zooSynName
, String synParentGenus
,
1878 String synParentInfragenericName
, String synParentSpecificEpithet
,
1879 TaxonBase syn
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1880 Synonym potentialCombination
;
1881 Reference sourceReference
;
1882 ZoologicalName inferredSynName
;
1883 HibernateProxyHelper
.deproxy(syn
);
1885 // Set sourceReference
1886 sourceReference
= syn
.getSec();
1887 if (sourceReference
== null){
1888 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
1890 if (!parentSynZooName
.getTaxa().isEmpty()){
1891 TaxonBase taxon
= parentSynZooName
.getTaxa().iterator().next();
1893 sourceReference
= taxon
.getSec();
1896 String synTaxonSpecificEpithet
= zooSynName
.getSpecificEpithet();
1898 String synTaxonInfraSpecificName
= null;
1900 if (parentSynZooName
.isSpecies()){
1901 synTaxonInfraSpecificName
= zooSynName
.getInfraSpecificEpithet();
1904 /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){
1905 synonymsEpithet.add(epithetName);
1908 //create potential combinations...
1909 inferredSynName
= ZoologicalName
.NewInstance(syn
.getName().getRank());
1911 inferredSynName
.setGenusOrUninomial(synParentGenus
);
1912 if (zooSynName
.isSpecies()){
1913 inferredSynName
.setSpecificEpithet(synTaxonSpecificEpithet
);
1914 if (parentSynZooName
.isInfraGeneric()){
1915 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1918 if (zooSynName
.isInfraSpecific()){
1919 inferredSynName
.setSpecificEpithet(synParentSpecificEpithet
);
1920 inferredSynName
.setInfraSpecificEpithet(synTaxonInfraSpecificName
);
1922 if (parentSynZooName
.isInfraGeneric()){
1923 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1927 potentialCombination
= Synonym
.NewInstance(inferredSynName
, null);
1929 // Set the sourceReference
1930 potentialCombination
.setSec(sourceReference
);
1933 // Determine the idInSource
1934 String idInSourceSyn
= getIdInSource(syn
);
1936 if (idInSourceParent
!= null && idInSourceSyn
!= null) {
1937 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1938 inferredSynName
.addSource(originalSource
);
1939 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1940 potentialCombination
.addSource(originalSource
);
1943 inferredSynName
.generateTitle();
1945 return potentialCombination
;
1948 private Synonym
createInferredGenus(Taxon taxon
,
1949 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1950 String epithetOfTaxon
, String genusOfTaxon
,
1951 List
<String
> taxonNames
, ZoologicalName zooParentName
,
1954 Synonym inferredGenus
;
1955 TaxonNameBase synName
;
1956 ZoologicalName inferredSynName
;
1957 synName
=syn
.getName();
1958 HibernateProxyHelper
.deproxy(syn
);
1960 // Determine the idInSource
1961 String idInSourceSyn
= getIdInSource(syn
);
1962 String idInSourceTaxon
= getIdInSource(taxon
);
1963 // Determine the sourceReference
1964 Reference sourceReference
= syn
.getSec();
1966 //logger.warn(sourceReference.getTitleCache());
1968 synName
= syn
.getName();
1969 ZoologicalName synZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1970 String synSpeciesEpithetName
= synZooName
.getSpecificEpithet();
1971 /* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){
1972 synonymsEpithet.add(synSpeciesEpithetName);
1975 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1976 //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...
1979 inferredSynName
.setGenusOrUninomial(genusOfTaxon
);
1980 if (zooParentName
.isInfraGeneric()){
1981 inferredSynName
.setInfraGenericEpithet(zooParentName
.getInfraGenericEpithet());
1984 if (taxonName
.isSpecies()){
1985 inferredSynName
.setSpecificEpithet(synSpeciesEpithetName
);
1987 if (taxonName
.isInfraSpecific()){
1988 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
1989 inferredSynName
.setInfraSpecificEpithet(synZooName
.getInfraGenericEpithet());
1993 inferredGenus
= Synonym
.NewInstance(inferredSynName
, null);
1995 // Set the sourceReference
1996 inferredGenus
.setSec(sourceReference
);
1998 // Add the original source
1999 if (idInSourceSyn
!= null && idInSourceTaxon
!= null) {
2000 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2001 inferredGenus
.addSource(originalSource
);
2003 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2004 inferredSynName
.addSource(originalSource
);
2005 originalSource
= null;
2008 logger
.error("There is an idInSource missing: " + idInSourceSyn
+ " of Synonym or " + idInSourceTaxon
+ " of Taxon");
2009 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2010 inferredGenus
.addSource(originalSource
);
2012 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2013 inferredSynName
.addSource(originalSource
);
2014 originalSource
= null;
2017 taxon
.addSynonym(inferredGenus
, SynonymRelationshipType
.INFERRED_GENUS_OF());
2019 inferredSynName
.generateTitle();
2022 return inferredGenus
;
2025 private Synonym
createInferredEpithets(Taxon taxon
,
2026 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
2027 String epithetOfTaxon
, String infragenericEpithetOfTaxon
,
2028 String infraspecificEpithetOfTaxon
, List
<String
> taxonNames
,
2029 TaxonNameBase parentName
, TaxonBase syn
) {
2031 Synonym inferredEpithet
;
2032 TaxonNameBase
<?
,?
> synName
;
2033 ZoologicalName inferredSynName
;
2034 HibernateProxyHelper
.deproxy(syn
);
2036 // Determine the idInSource
2037 String idInSourceSyn
= getIdInSource(syn
);
2038 String idInSourceTaxon
= getIdInSource(taxon
);
2039 // Determine the sourceReference
2040 Reference
<?
> sourceReference
= syn
.getSec();
2042 if (sourceReference
== null){
2043 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
2045 System
.out
.println("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon
.getSec());
2046 sourceReference
= taxon
.getSec();
2049 synName
= syn
.getName();
2050 ZoologicalName zooSynName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
2051 String synGenusName
= zooSynName
.getGenusOrUninomial();
2052 String synInfraGenericEpithet
= null;
2053 String synSpecificEpithet
= null;
2055 if (zooSynName
.getInfraGenericEpithet() != null){
2056 synInfraGenericEpithet
= zooSynName
.getInfraGenericEpithet();
2059 if (zooSynName
.isInfraSpecific()){
2060 synSpecificEpithet
= zooSynName
.getSpecificEpithet();
2063 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
2064 synonymsGenus.put(synGenusName, idInSource);
2067 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
2069 // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!
2070 if (epithetOfTaxon
== null && infragenericEpithetOfTaxon
== null && infraspecificEpithetOfTaxon
== null) {
2071 logger
.error("This specificEpithet is NULL" + taxon
.getTitleCache());
2073 inferredSynName
.setGenusOrUninomial(synGenusName
);
2075 if (parentName
.isInfraGeneric()){
2076 inferredSynName
.setInfraGenericEpithet(synInfraGenericEpithet
);
2078 if (taxonName
.isSpecies()){
2079 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2080 }else if (taxonName
.isInfraSpecific()){
2081 inferredSynName
.setSpecificEpithet(synSpecificEpithet
);
2082 inferredSynName
.setInfraSpecificEpithet(infraspecificEpithetOfTaxon
);
2085 inferredEpithet
= Synonym
.NewInstance(inferredSynName
, null);
2087 // Set the sourceReference
2088 inferredEpithet
.setSec(sourceReference
);
2090 /* Add the original source
2091 if (idInSource != null) {
2092 IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);
2095 Reference citation = getCitation(syn);
2096 if (citation != null) {
2097 originalSource.setCitation(citation);
2098 inferredEpithet.addSource(originalSource);
2101 String taxonId
= idInSourceTaxon
+ "; " + idInSourceSyn
;
2104 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2106 inferredEpithet
.addSource(originalSource
);
2108 originalSource
= IdentifiableSource
.NewInstance(taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2110 inferredSynName
.addSource(originalSource
);
2114 taxon
.addSynonym(inferredEpithet
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
2116 inferredSynName
.generateTitle();
2117 return inferredEpithet
;
2121 * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.
2122 * Very likely only useful for createInferredSynonyms().
2127 private ZoologicalName
getZoologicalName(UUID uuid
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
2128 ZoologicalName taxonName
=nameDao
.findZoologicalNameByUUID(uuid
);
2129 if (taxonName
== null) {
2130 taxonName
= zooHashMap
.get(uuid
);
2136 * Returns the idInSource for a given Synonym.
2139 private String
getIdInSource(TaxonBase taxonBase
) {
2140 String idInSource
= null;
2141 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
2142 if (sources
.size() == 1) {
2143 IdentifiableSource source
= sources
.iterator().next();
2144 if (source
!= null) {
2145 idInSource
= source
.getIdInSource();
2147 } else if (sources
.size() > 1) {
2150 for (IdentifiableSource source
: sources
) {
2151 idInSource
+= source
.getIdInSource();
2152 if (count
< sources
.size()) {
2157 } else if (sources
.size() == 0){
2158 logger
.warn("No idInSource for TaxonBase " + taxonBase
.getUuid() + " - " + taxonBase
.getTitleCache());
2167 * Returns the citation for a given Synonym.
2170 private Reference
getCitation(Synonym syn
) {
2171 Reference citation
= null;
2172 Set
<IdentifiableSource
> sources
= syn
.getSources();
2173 if (sources
.size() == 1) {
2174 IdentifiableSource source
= sources
.iterator().next();
2175 if (source
!= null) {
2176 citation
= source
.getCitation();
2178 } else if (sources
.size() > 1) {
2179 logger
.warn("This Synonym has more than one source: " + syn
.getUuid() + " (" + syn
.getTitleCache() +")");
2186 public List
<Synonym
> createAllInferredSynonyms(Taxon taxon
, Classification tree
, boolean doWithMisappliedNames
){
2187 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
2189 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_EPITHET_OF(), doWithMisappliedNames
));
2190 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_GENUS_OF(), doWithMisappliedNames
));
2191 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames
));
2193 return inferredSynonyms
;
2197 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)
2200 public List
<Classification
> listClassifications(TaxonBase taxonBase
, Integer limit
, Integer start
, List
<String
> propertyPaths
) {
2202 // TODO quickly implemented, create according dao !!!!
2203 Set
<TaxonNode
> nodes
= new HashSet
<TaxonNode
>();
2204 Set
<Classification
> classifications
= new HashSet
<Classification
>();
2205 List
<Classification
> list
= new ArrayList
<Classification
>();
2207 if (taxonBase
== null) {
2211 taxonBase
= load(taxonBase
.getUuid());
2213 if (taxonBase
instanceof Taxon
) {
2214 nodes
.addAll(((Taxon
)taxonBase
).getTaxonNodes());
2216 for (Taxon taxon
: ((Synonym
)taxonBase
).getAcceptedTaxa() ) {
2217 nodes
.addAll(taxon
.getTaxonNodes());
2220 for (TaxonNode node
: nodes
) {
2221 classifications
.add(node
.getClassification());
2223 list
.addAll(classifications
);