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
.Transactional
;
33 import eu
.etaxonomy
.cdm
.api
.service
.config
.IFindTaxaAndNamesConfigurator
;
34 import eu
.etaxonomy
.cdm
.api
.service
.config
.MatchingTaxonConfigurator
;
35 import eu
.etaxonomy
.cdm
.api
.service
.config
.NameDeletionConfigurator
;
36 import eu
.etaxonomy
.cdm
.api
.service
.config
.TaxonDeletionConfigurator
;
37 import eu
.etaxonomy
.cdm
.api
.service
.exception
.DataChangeNoRollbackException
;
38 import eu
.etaxonomy
.cdm
.api
.service
.exception
.HomotypicalGroupChangeException
;
39 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
40 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
41 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
42 import eu
.etaxonomy
.cdm
.api
.service
.search
.ISearchResultBuilder
;
43 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneMultiSearch
;
44 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
;
45 import eu
.etaxonomy
.cdm
.api
.service
.search
.LuceneSearch
.TopGroupsWithMaxScore
;
46 import eu
.etaxonomy
.cdm
.api
.service
.search
.QueryFactory
;
47 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
48 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResultBuilder
;
49 import eu
.etaxonomy
.cdm
.api
.service
.util
.TaxonRelationshipEdge
;
50 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
51 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
52 import eu
.etaxonomy
.cdm
.hibernate
.search
.DefinedTermBaseClassBridge
;
53 import eu
.etaxonomy
.cdm
.hibernate
.search
.GroupByTaxonClassBridge
;
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(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 Set
<Taxon
> listRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Integer maxDepth
,
504 Integer limit
, Integer start
, List
<String
> propertyPaths
) {
506 Set
<Taxon
> relatedTaxa
= collectRelatedTaxa(taxon
, includeRelationships
, new HashSet
<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 Set
<Taxon
> collectRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Set
<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 Set
<Taxon
> taxa
= new HashSet
<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(), GroupByTaxonClassBridge
.GROUPBY_TAXON_FIELD
, 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(), false), 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 logger
.info("prepareByDescriptionElementFullTextSearch() query: " + finalQuery
.toString());
1533 luceneSearch
.setQuery(finalQuery
);
1535 if(highlightFragments
){
1536 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1538 return luceneSearch
;
1542 * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}
1543 * and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.
1544 * This method is a convenient means to retrieve a Lucene query string for such the fields.
1546 * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}
1547 * or {@link MultilanguageTextFieldBridge }
1548 * @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages
1549 * @param stringBuilder a StringBuilder to be reused, if <code>null</code> a new StringBuilder will be instantiated and is returned
1550 * @return the StringBuilder given a parameter or a new one if the stringBuilder parameter was null.
1552 * TODO move to utiliy class !!!!!!!!
1554 private StringBuilder
appendLocalizedFieldQuery(String name
, List
<Language
> languages
, StringBuilder stringBuilder
) {
1556 if(stringBuilder
== null){
1557 stringBuilder
= new StringBuilder();
1559 if(languages
== null || languages
.size() == 0){
1560 stringBuilder
.append(name
+ ".ALL:(%1$s) ");
1562 for(Language lang
: languages
){
1563 stringBuilder
.append(name
+ "." + lang
.getUuid().toString() + ":(%1$s) ");
1566 return stringBuilder
;
1570 public List
<Synonym
> createInferredSynonyms(Taxon taxon
, Classification classification
, SynonymRelationshipType type
, boolean doWithMisappliedNames
){
1571 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1572 List
<Synonym
> inferredSynonymsToBeRemoved
= new ArrayList
<Synonym
>();
1574 HashMap
<UUID
, ZoologicalName
> zooHashMap
= new HashMap
<UUID
, ZoologicalName
>();
1577 UUID nameUuid
= taxon
.getName().getUuid();
1578 ZoologicalName taxonName
= getZoologicalName(nameUuid
, zooHashMap
);
1579 String epithetOfTaxon
= null;
1580 String infragenericEpithetOfTaxon
= null;
1581 String infraspecificEpithetOfTaxon
= null;
1582 if (taxonName
.isSpecies()){
1583 epithetOfTaxon
= taxonName
.getSpecificEpithet();
1584 } else if (taxonName
.isInfraGeneric()){
1585 infragenericEpithetOfTaxon
= taxonName
.getInfraGenericEpithet();
1586 } else if (taxonName
.isInfraSpecific()){
1587 infraspecificEpithetOfTaxon
= taxonName
.getInfraSpecificEpithet();
1589 String genusOfTaxon
= taxonName
.getGenusOrUninomial();
1590 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1591 List
<String
> taxonNames
= new ArrayList
<String
>();
1593 for (TaxonNode node
: nodes
){
1594 // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName
1595 // List<String> synonymsEpithet = new ArrayList<String>();
1597 if (node
.getClassification().equals(classification
)){
1598 if (!node
.isTopmostNode()){
1599 TaxonNode parent
= node
.getParent();
1600 parent
= (TaxonNode
)HibernateProxyHelper
.deproxy(parent
);
1601 TaxonNameBase
<?
,?
> parentName
= parent
.getTaxon().getName();
1602 ZoologicalName zooParentName
= HibernateProxyHelper
.deproxy(parentName
, ZoologicalName
.class);
1603 Taxon parentTaxon
= (Taxon
)HibernateProxyHelper
.deproxy(parent
.getTaxon());
1604 Rank rankOfTaxon
= taxonName
.getRank();
1607 //create inferred synonyms for species, subspecies
1608 if ((parentName
.isGenus() || parentName
.isSpecies() || parentName
.getRank().equals(Rank
.SUBGENUS())) ){
1610 Synonym inferredEpithet
= null;
1611 Synonym inferredGenus
= null;
1612 Synonym potentialCombination
= null;
1614 List
<String
> propertyPaths
= new ArrayList
<String
>();
1615 propertyPaths
.add("synonym");
1616 propertyPaths
.add("synonym.name");
1617 List
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
1618 orderHints
.add(new OrderHint("relatedFrom.titleCache", SortOrder
.ASCENDING
));
1620 List
<SynonymRelationship
> synonymRelationshipsOfParent
= dao
.getSynonyms(parentTaxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1621 List
<SynonymRelationship
> synonymRelationshipsOfTaxon
= dao
.getSynonyms(taxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1623 List
<TaxonRelationship
> taxonRelListParent
= null;
1624 List
<TaxonRelationship
> taxonRelListTaxon
= null;
1625 if (doWithMisappliedNames
){
1626 taxonRelListParent
= dao
.getTaxonRelationships(parentTaxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1627 taxonRelListTaxon
= dao
.getTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1631 if (type
.equals(SynonymRelationshipType
.INFERRED_EPITHET_OF())){
1634 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1635 Synonym syn
= synonymRelationOfParent
.getSynonym();
1637 inferredEpithet
= createInferredEpithets(taxon
,
1638 zooHashMap
, taxonName
, epithetOfTaxon
,
1639 infragenericEpithetOfTaxon
,
1640 infraspecificEpithetOfTaxon
,
1641 taxonNames
, parentName
,
1645 inferredSynonyms
.add(inferredEpithet
);
1646 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1647 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1650 if (doWithMisappliedNames
){
1652 for (TaxonRelationship taxonRelationship
: taxonRelListParent
){
1653 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1655 inferredEpithet
= createInferredEpithets(taxon
,
1656 zooHashMap
, taxonName
, epithetOfTaxon
,
1657 infragenericEpithetOfTaxon
,
1658 infraspecificEpithetOfTaxon
,
1659 taxonNames
, parentName
,
1662 inferredSynonyms
.add(inferredEpithet
);
1663 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1664 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1668 if (!taxonNames
.isEmpty()){
1669 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1670 ZoologicalName name
;
1671 if (!synNotInCDM
.isEmpty()){
1672 inferredSynonymsToBeRemoved
.clear();
1674 for (Synonym syn
:inferredSynonyms
){
1675 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1676 if (!synNotInCDM
.contains(name
.getNameCache())){
1677 inferredSynonymsToBeRemoved
.add(syn
);
1681 // Remove identified Synonyms from inferredSynonyms
1682 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1683 inferredSynonyms
.remove(synonym
);
1688 }else if (type
.equals(SynonymRelationshipType
.INFERRED_GENUS_OF())){
1691 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1692 TaxonNameBase synName
;
1693 ZoologicalName inferredSynName
;
1695 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1696 inferredGenus
= createInferredGenus(taxon
,
1697 zooHashMap
, taxonName
, epithetOfTaxon
,
1698 genusOfTaxon
, taxonNames
, zooParentName
, syn
);
1700 inferredSynonyms
.add(inferredGenus
);
1701 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1702 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1707 if (doWithMisappliedNames
){
1709 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1710 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1711 inferredGenus
= createInferredGenus(taxon
, zooHashMap
, taxonName
, infraspecificEpithetOfTaxon
, genusOfTaxon
, taxonNames
, zooParentName
, misappliedName
);
1713 inferredSynonyms
.add(inferredGenus
);
1714 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1715 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1720 if (!taxonNames
.isEmpty()){
1721 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1722 ZoologicalName name
;
1723 if (!synNotInCDM
.isEmpty()){
1724 inferredSynonymsToBeRemoved
.clear();
1726 for (Synonym syn
:inferredSynonyms
){
1727 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1728 if (!synNotInCDM
.contains(name
.getNameCache())){
1729 inferredSynonymsToBeRemoved
.add(syn
);
1733 // Remove identified Synonyms from inferredSynonyms
1734 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1735 inferredSynonyms
.remove(synonym
);
1740 }else if (type
.equals(SynonymRelationshipType
.POTENTIAL_COMBINATION_OF())){
1742 Reference sourceReference
= null; // TODO: Determination of sourceReference is redundant
1743 ZoologicalName inferredSynName
;
1744 //for all synonyms of the parent...
1745 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1746 TaxonNameBase synName
;
1747 Synonym synParent
= synonymRelationOfParent
.getSynonym();
1748 synName
= synParent
.getName();
1750 HibernateProxyHelper
.deproxy(synParent
);
1752 // Set the sourceReference
1753 sourceReference
= synParent
.getSec();
1755 // Determine the idInSource
1756 String idInSourceParent
= getIdInSource(synParent
);
1758 ZoologicalName parentSynZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1759 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1760 String synParentInfragenericName
= null;
1761 String synParentSpecificEpithet
= null;
1763 if (parentSynZooName
.isInfraGeneric()){
1764 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1766 if (parentSynZooName
.isSpecies()){
1767 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1770 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1771 synonymsGenus.put(synGenusName, idInSource);
1774 //for all synonyms of the taxon
1776 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1778 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1779 ZoologicalName zooSynName
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1780 potentialCombination
= createPotentialCombination(idInSourceParent
, parentSynZooName
, zooSynName
,
1782 synParentInfragenericName
,
1783 synParentSpecificEpithet
, syn
, zooHashMap
);
1785 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1786 inferredSynonyms
.add(potentialCombination
);
1787 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1788 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1795 if (doWithMisappliedNames
){
1797 for (TaxonRelationship parentRelationship
: taxonRelListParent
){
1799 TaxonNameBase misappliedParentName
;
1801 Taxon misappliedParent
= parentRelationship
.getFromTaxon();
1802 misappliedParentName
= misappliedParent
.getName();
1804 HibernateProxyHelper
.deproxy(misappliedParent
);
1806 // Set the sourceReference
1807 sourceReference
= misappliedParent
.getSec();
1809 // Determine the idInSource
1810 String idInSourceParent
= getIdInSource(misappliedParent
);
1812 ZoologicalName parentSynZooName
= getZoologicalName(misappliedParentName
.getUuid(), zooHashMap
);
1813 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1814 String synParentInfragenericName
= null;
1815 String synParentSpecificEpithet
= null;
1817 if (parentSynZooName
.isInfraGeneric()){
1818 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1820 if (parentSynZooName
.isSpecies()){
1821 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1825 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1826 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1827 ZoologicalName zooMisappliedName
= getZoologicalName(misappliedName
.getName().getUuid(), zooHashMap
);
1828 potentialCombination
= createPotentialCombination(
1829 idInSourceParent
, parentSynZooName
, zooMisappliedName
,
1831 synParentInfragenericName
,
1832 synParentSpecificEpithet
, misappliedName
, zooHashMap
);
1835 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1836 inferredSynonyms
.add(potentialCombination
);
1837 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1838 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1843 if (!taxonNames
.isEmpty()){
1844 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1845 ZoologicalName name
;
1846 if (!synNotInCDM
.isEmpty()){
1847 inferredSynonymsToBeRemoved
.clear();
1848 for (Synonym syn
:inferredSynonyms
){
1850 name
= (ZoologicalName
) syn
.getName();
1851 }catch (ClassCastException e
){
1852 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1854 if (!synNotInCDM
.contains(name
.getNameCache())){
1855 inferredSynonymsToBeRemoved
.add(syn
);
1858 // Remove identified Synonyms from inferredSynonyms
1859 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1860 inferredSynonyms
.remove(synonym
);
1866 logger
.info("The synonymrelationship type is not defined.");
1867 return inferredSynonyms
;
1874 return inferredSynonyms
;
1877 private Synonym
createPotentialCombination(String idInSourceParent
,
1878 ZoologicalName parentSynZooName
, ZoologicalName zooSynName
, String synParentGenus
,
1879 String synParentInfragenericName
, String synParentSpecificEpithet
,
1880 TaxonBase syn
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1881 Synonym potentialCombination
;
1882 Reference sourceReference
;
1883 ZoologicalName inferredSynName
;
1884 HibernateProxyHelper
.deproxy(syn
);
1886 // Set sourceReference
1887 sourceReference
= syn
.getSec();
1888 if (sourceReference
== null){
1889 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
1891 if (!parentSynZooName
.getTaxa().isEmpty()){
1892 TaxonBase taxon
= parentSynZooName
.getTaxa().iterator().next();
1894 sourceReference
= taxon
.getSec();
1897 String synTaxonSpecificEpithet
= zooSynName
.getSpecificEpithet();
1899 String synTaxonInfraSpecificName
= null;
1901 if (parentSynZooName
.isSpecies()){
1902 synTaxonInfraSpecificName
= zooSynName
.getInfraSpecificEpithet();
1905 /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){
1906 synonymsEpithet.add(epithetName);
1909 //create potential combinations...
1910 inferredSynName
= ZoologicalName
.NewInstance(syn
.getName().getRank());
1912 inferredSynName
.setGenusOrUninomial(synParentGenus
);
1913 if (zooSynName
.isSpecies()){
1914 inferredSynName
.setSpecificEpithet(synTaxonSpecificEpithet
);
1915 if (parentSynZooName
.isInfraGeneric()){
1916 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1919 if (zooSynName
.isInfraSpecific()){
1920 inferredSynName
.setSpecificEpithet(synParentSpecificEpithet
);
1921 inferredSynName
.setInfraSpecificEpithet(synTaxonInfraSpecificName
);
1923 if (parentSynZooName
.isInfraGeneric()){
1924 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1928 potentialCombination
= Synonym
.NewInstance(inferredSynName
, null);
1930 // Set the sourceReference
1931 potentialCombination
.setSec(sourceReference
);
1934 // Determine the idInSource
1935 String idInSourceSyn
= getIdInSource(syn
);
1937 if (idInSourceParent
!= null && idInSourceSyn
!= null) {
1938 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1939 inferredSynName
.addSource(originalSource
);
1940 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1941 potentialCombination
.addSource(originalSource
);
1944 inferredSynName
.generateTitle();
1946 return potentialCombination
;
1949 private Synonym
createInferredGenus(Taxon taxon
,
1950 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1951 String epithetOfTaxon
, String genusOfTaxon
,
1952 List
<String
> taxonNames
, ZoologicalName zooParentName
,
1955 Synonym inferredGenus
;
1956 TaxonNameBase synName
;
1957 ZoologicalName inferredSynName
;
1958 synName
=syn
.getName();
1959 HibernateProxyHelper
.deproxy(syn
);
1961 // Determine the idInSource
1962 String idInSourceSyn
= getIdInSource(syn
);
1963 String idInSourceTaxon
= getIdInSource(taxon
);
1964 // Determine the sourceReference
1965 Reference sourceReference
= syn
.getSec();
1967 //logger.warn(sourceReference.getTitleCache());
1969 synName
= syn
.getName();
1970 ZoologicalName synZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1971 String synSpeciesEpithetName
= synZooName
.getSpecificEpithet();
1972 /* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){
1973 synonymsEpithet.add(synSpeciesEpithetName);
1976 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1977 //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...
1980 inferredSynName
.setGenusOrUninomial(genusOfTaxon
);
1981 if (zooParentName
.isInfraGeneric()){
1982 inferredSynName
.setInfraGenericEpithet(zooParentName
.getInfraGenericEpithet());
1985 if (taxonName
.isSpecies()){
1986 inferredSynName
.setSpecificEpithet(synSpeciesEpithetName
);
1988 if (taxonName
.isInfraSpecific()){
1989 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
1990 inferredSynName
.setInfraSpecificEpithet(synZooName
.getInfraGenericEpithet());
1994 inferredGenus
= Synonym
.NewInstance(inferredSynName
, null);
1996 // Set the sourceReference
1997 inferredGenus
.setSec(sourceReference
);
1999 // Add the original source
2000 if (idInSourceSyn
!= null && idInSourceTaxon
!= null) {
2001 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2002 inferredGenus
.addSource(originalSource
);
2004 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2005 inferredSynName
.addSource(originalSource
);
2006 originalSource
= null;
2009 logger
.error("There is an idInSource missing: " + idInSourceSyn
+ " of Synonym or " + idInSourceTaxon
+ " of Taxon");
2010 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2011 inferredGenus
.addSource(originalSource
);
2013 originalSource
= IdentifiableSource
.NewInstance(idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2014 inferredSynName
.addSource(originalSource
);
2015 originalSource
= null;
2018 taxon
.addSynonym(inferredGenus
, SynonymRelationshipType
.INFERRED_GENUS_OF());
2020 inferredSynName
.generateTitle();
2023 return inferredGenus
;
2026 private Synonym
createInferredEpithets(Taxon taxon
,
2027 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
2028 String epithetOfTaxon
, String infragenericEpithetOfTaxon
,
2029 String infraspecificEpithetOfTaxon
, List
<String
> taxonNames
,
2030 TaxonNameBase parentName
, TaxonBase syn
) {
2032 Synonym inferredEpithet
;
2033 TaxonNameBase
<?
,?
> synName
;
2034 ZoologicalName inferredSynName
;
2035 HibernateProxyHelper
.deproxy(syn
);
2037 // Determine the idInSource
2038 String idInSourceSyn
= getIdInSource(syn
);
2039 String idInSourceTaxon
= getIdInSource(taxon
);
2040 // Determine the sourceReference
2041 Reference
<?
> sourceReference
= syn
.getSec();
2043 if (sourceReference
== null){
2044 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
2046 System
.out
.println("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon
.getSec());
2047 sourceReference
= taxon
.getSec();
2050 synName
= syn
.getName();
2051 ZoologicalName zooSynName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
2052 String synGenusName
= zooSynName
.getGenusOrUninomial();
2053 String synInfraGenericEpithet
= null;
2054 String synSpecificEpithet
= null;
2056 if (zooSynName
.getInfraGenericEpithet() != null){
2057 synInfraGenericEpithet
= zooSynName
.getInfraGenericEpithet();
2060 if (zooSynName
.isInfraSpecific()){
2061 synSpecificEpithet
= zooSynName
.getSpecificEpithet();
2064 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
2065 synonymsGenus.put(synGenusName, idInSource);
2068 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
2070 // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!
2071 if (epithetOfTaxon
== null && infragenericEpithetOfTaxon
== null && infraspecificEpithetOfTaxon
== null) {
2072 logger
.error("This specificEpithet is NULL" + taxon
.getTitleCache());
2074 inferredSynName
.setGenusOrUninomial(synGenusName
);
2076 if (parentName
.isInfraGeneric()){
2077 inferredSynName
.setInfraGenericEpithet(synInfraGenericEpithet
);
2079 if (taxonName
.isSpecies()){
2080 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2081 }else if (taxonName
.isInfraSpecific()){
2082 inferredSynName
.setSpecificEpithet(synSpecificEpithet
);
2083 inferredSynName
.setInfraSpecificEpithet(infraspecificEpithetOfTaxon
);
2086 inferredEpithet
= Synonym
.NewInstance(inferredSynName
, null);
2088 // Set the sourceReference
2089 inferredEpithet
.setSec(sourceReference
);
2091 /* Add the original source
2092 if (idInSource != null) {
2093 IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);
2096 Reference citation = getCitation(syn);
2097 if (citation != null) {
2098 originalSource.setCitation(citation);
2099 inferredEpithet.addSource(originalSource);
2102 String taxonId
= idInSourceTaxon
+ "; " + idInSourceSyn
;
2105 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2107 inferredEpithet
.addSource(originalSource
);
2109 originalSource
= IdentifiableSource
.NewInstance(taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2111 inferredSynName
.addSource(originalSource
);
2115 taxon
.addSynonym(inferredEpithet
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
2117 inferredSynName
.generateTitle();
2118 return inferredEpithet
;
2122 * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.
2123 * Very likely only useful for createInferredSynonyms().
2128 private ZoologicalName
getZoologicalName(UUID uuid
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
2129 ZoologicalName taxonName
=nameDao
.findZoologicalNameByUUID(uuid
);
2130 if (taxonName
== null) {
2131 taxonName
= zooHashMap
.get(uuid
);
2137 * Returns the idInSource for a given Synonym.
2140 private String
getIdInSource(TaxonBase taxonBase
) {
2141 String idInSource
= null;
2142 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
2143 if (sources
.size() == 1) {
2144 IdentifiableSource source
= sources
.iterator().next();
2145 if (source
!= null) {
2146 idInSource
= source
.getIdInSource();
2148 } else if (sources
.size() > 1) {
2151 for (IdentifiableSource source
: sources
) {
2152 idInSource
+= source
.getIdInSource();
2153 if (count
< sources
.size()) {
2158 } else if (sources
.size() == 0){
2159 logger
.warn("No idInSource for TaxonBase " + taxonBase
.getUuid() + " - " + taxonBase
.getTitleCache());
2168 * Returns the citation for a given Synonym.
2171 private Reference
getCitation(Synonym syn
) {
2172 Reference citation
= null;
2173 Set
<IdentifiableSource
> sources
= syn
.getSources();
2174 if (sources
.size() == 1) {
2175 IdentifiableSource source
= sources
.iterator().next();
2176 if (source
!= null) {
2177 citation
= source
.getCitation();
2179 } else if (sources
.size() > 1) {
2180 logger
.warn("This Synonym has more than one source: " + syn
.getUuid() + " (" + syn
.getTitleCache() +")");
2187 public List
<Synonym
> createAllInferredSynonyms(Taxon taxon
, Classification tree
, boolean doWithMisappliedNames
){
2188 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
2190 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_EPITHET_OF(), doWithMisappliedNames
));
2191 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_GENUS_OF(), doWithMisappliedNames
));
2192 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames
));
2194 return inferredSynonyms
;
2198 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)
2201 public List
<Classification
> listClassifications(TaxonBase taxonBase
, Integer limit
, Integer start
, List
<String
> propertyPaths
) {
2203 // TODO quickly implemented, create according dao !!!!
2204 Set
<TaxonNode
> nodes
= new HashSet
<TaxonNode
>();
2205 Set
<Classification
> classifications
= new HashSet
<Classification
>();
2206 List
<Classification
> list
= new ArrayList
<Classification
>();
2208 if (taxonBase
== null) {
2212 taxonBase
= load(taxonBase
.getUuid());
2214 if (taxonBase
instanceof Taxon
) {
2215 nodes
.addAll(((Taxon
)taxonBase
).getTaxonNodes());
2217 for (Taxon taxon
: ((Synonym
)taxonBase
).getAcceptedTaxa() ) {
2218 nodes
.addAll(taxon
.getTaxonNodes());
2221 for (TaxonNode node
: nodes
) {
2222 classifications
.add(node
.getClassification());
2224 list
.addAll(classifications
);