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
.OriginalSourceType
;
62 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
63 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
64 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
65 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
66 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
67 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
68 import eu
.etaxonomy
.cdm
.model
.description
.IIdentificationKey
;
69 import eu
.etaxonomy
.cdm
.model
.description
.PolytomousKeyNode
;
70 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
71 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
72 import eu
.etaxonomy
.cdm
.model
.description
.TaxonInteraction
;
73 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
74 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
75 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
76 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
77 import eu
.etaxonomy
.cdm
.model
.molecular
.Amplification
;
78 import eu
.etaxonomy
.cdm
.model
.molecular
.DnaSample
;
79 import eu
.etaxonomy
.cdm
.model
.molecular
.Sequence
;
80 import eu
.etaxonomy
.cdm
.model
.molecular
.SingleSequence
;
81 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
82 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
83 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
84 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
85 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
86 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
87 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
88 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
89 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
90 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
91 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
92 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
93 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
94 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
95 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
96 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
97 import eu
.etaxonomy
.cdm
.persistence
.dao
.AbstractBeanInitializer
;
98 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
99 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
100 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
101 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
102 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
103 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
104 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
105 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
106 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
.SortOrder
;
107 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
111 * @author a.kohlbecker
116 @Transactional(readOnly
= true)
117 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
118 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
120 public static final String POTENTIAL_COMBINATION_NAMESPACE
= "Potential combination";
122 public static final String INFERRED_EPITHET_NAMESPACE
= "Inferred epithet";
124 public static final String INFERRED_GENUS_NAMESPACE
= "Inferred genus";
128 private ITaxonNameDao nameDao
;
131 private INameService nameService
;
134 private ICdmGenericDao genericDao
;
137 private IDescriptionService descriptionService
;
140 private IOrderedTermVocabularyDao orderedVocabularyDao
;
143 private IOccurrenceDao occurrenceDao
;
146 private AbstractBeanInitializer beanInitializer
;
151 public TaxonServiceImpl(){
152 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
156 * FIXME Candidate for harmonization
157 * rename searchByName ?
160 public List
<TaxonBase
> searchTaxaByName(String name
, Reference sec
) {
161 return dao
.getTaxaByName(name
, sec
);
165 * FIXME Candidate for harmonization
166 * list(Synonym.class, ...)
168 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
171 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
172 return dao
.getAllSynonyms(limit
, start
);
176 * FIXME Candidate for harmonization
177 * list(Taxon.class, ...)
179 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
182 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
183 return dao
.getAllTaxa(limit
, start
);
187 * FIXME Candidate for harmonization
188 * merge with getRootTaxa(Reference sec, ..., ...)
190 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)
193 public List
<Taxon
> getRootTaxa(Reference sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
194 if (cdmFetch
== null){
195 cdmFetch
= CdmFetch
.NO_FETCH();
197 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
202 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
205 public List
<Taxon
> getRootTaxa(Rank rank
, Reference sec
, boolean onlyWithChildren
,boolean withMisapplications
, List
<String
> propertyPaths
) {
206 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
210 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)
213 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
214 return dao
.getAllRelationships(limit
, start
);
218 * FIXME Candidate for harmonization
219 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
223 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
225 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
226 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
227 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
228 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
229 return taxonRelTypeVocabulary
;
236 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
239 @Transactional(readOnly
= false)
240 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
242 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
243 synonymName
.removeTaxonBase(synonym
);
244 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
245 taxonName
.removeTaxonBase(acceptedTaxon
);
247 synonym
.setName(taxonName
);
248 acceptedTaxon
.setName(synonymName
);
250 // the accepted taxon needs a new uuid because the concept has changed
251 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
252 //acceptedTaxon.setUuid(UUID.randomUUID());
257 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
259 //TODO correct delete handling still needs to be implemented / checked
261 @Transactional(readOnly
= false)
262 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
, boolean deleteSynonym
, boolean copyCitationInfo
, Reference citation
, String microCitation
) throws HomotypicalGroupChangeException
{
264 TaxonNameBase
<?
,?
> acceptedName
= acceptedTaxon
.getName();
265 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
266 HomotypicalGroup synonymHomotypicGroup
= synonymName
.getHomotypicalGroup();
268 //check synonym is not homotypic
269 if (acceptedName
.getHomotypicalGroup().equals(synonymHomotypicGroup
)){
270 String message
= "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";
271 throw new HomotypicalGroupChangeException(message
);
274 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonymName
, acceptedTaxon
.getSec());
276 SynonymRelationshipType relTypeForGroup
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
277 List
<Synonym
> heteroSynonyms
= acceptedTaxon
.getSynonymsInGroup(synonymHomotypicGroup
);
279 for (Synonym heteroSynonym
: heteroSynonyms
){
280 if (synonym
.equals(heteroSynonym
)){
281 acceptedTaxon
.removeSynonym(heteroSynonym
, false);
283 //move synonyms in same homotypic group to new accepted taxon
284 heteroSynonym
.replaceAcceptedTaxon(newAcceptedTaxon
, relTypeForGroup
, copyCitationInfo
, citation
, microCitation
);
288 //synonym.getName().removeTaxonBase(synonym);
289 //TODO correct delete handling still needs to be implemented / checked
291 // deleteSynonym(synonym, taxon, false);
294 this.delete(synonym
);
296 } catch (Exception e
) {
297 logger
.info("Can't delete old synonym from database");
301 return newAcceptedTaxon
;
306 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, Reference citation
, String microcitation
){
308 // Get name from synonym
309 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
311 // remove synonym from taxon
312 toTaxon
.removeSynonym(synonym
);
314 // Create a taxon with synonym name
315 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
317 // Add taxon relation
318 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
320 // since we are swapping names, we have to detach the name from the synonym completely.
321 // Otherwise the synonym will still be in the list of typified names.
322 synonym
.getName().removeTaxonBase(synonym
);
329 * @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)
331 @Transactional(readOnly
= false)
333 public void changeHomotypicalGroupOfSynonym(Synonym synonym
, HomotypicalGroup newHomotypicalGroup
, Taxon targetTaxon
,
334 boolean removeFromOtherTaxa
, boolean setBasionymRelationIfApplicable
){
336 TaxonNameBase synonymName
= synonym
.getName();
337 HomotypicalGroup oldHomotypicalGroup
= synonymName
.getHomotypicalGroup();
341 oldHomotypicalGroup
.removeTypifiedName(synonymName
);
342 newHomotypicalGroup
.addTypifiedName(synonymName
);
344 //remove existing basionym relationships
345 synonymName
.removeBasionyms();
347 //add basionym relationship
348 if (setBasionymRelationIfApplicable
){
349 Set
<TaxonNameBase
> basionyms
= newHomotypicalGroup
.getBasionyms();
350 for (TaxonNameBase basionym
: basionyms
){
351 synonymName
.addBasionym(basionym
);
355 //set synonym relationship correctly
356 // SynonymRelationship relToTaxon = null;
357 boolean relToTargetTaxonExists
= false;
358 Set
<SynonymRelationship
> existingRelations
= synonym
.getSynonymRelations();
359 for (SynonymRelationship rel
: existingRelations
){
360 Taxon acceptedTaxon
= rel
.getAcceptedTaxon();
361 boolean isTargetTaxon
= acceptedTaxon
!= null && acceptedTaxon
.equals(targetTaxon
);
362 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
363 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
364 SynonymRelationshipType newRelationType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
365 rel
.setType(newRelationType
);
366 //TODO handle citation and microCitation
369 relToTargetTaxonExists
= true;
371 if (removeFromOtherTaxa
){
372 acceptedTaxon
.removeSynonym(synonym
, false);
378 if (targetTaxon
!= null && ! relToTargetTaxonExists
){
379 Taxon acceptedTaxon
= targetTaxon
;
380 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
381 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
382 SynonymRelationshipType relType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
383 //TODO handle citation and microCitation
384 Reference citation
= null;
385 String microCitation
= null;
386 acceptedTaxon
.addSynonym(synonym
, relType
, citation
, microCitation
);
393 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
396 @Transactional(readOnly
= false)
397 public void updateTitleCache(Class
<?
extends TaxonBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<TaxonBase
> cacheStrategy
, IProgressMonitor monitor
) {
399 clazz
= TaxonBase
.class;
401 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
406 protected void setDao(ITaxonDao dao
) {
411 * @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)
414 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
415 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
417 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
418 if(numberOfResults
> 0) { // no point checking again
419 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
422 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
426 * @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)
429 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
430 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
432 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
433 if(numberOfResults
> 0) { // no point checking again
434 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
441 * @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)
444 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
445 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
447 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
448 if(numberOfResults
> 0) { // no point checking again
449 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
455 * @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)
458 public Pager
<TaxonRelationship
> pageToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
459 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
461 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
462 if(numberOfResults
> 0) { // no point checking again
463 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
465 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
469 * @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)
472 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
473 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
475 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
476 if(numberOfResults
> 0) { // no point checking again
477 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
483 * @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)
486 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
487 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
489 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
490 if(numberOfResults
> 0) { // no point checking again
491 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
493 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
498 * @param includeRelationships
502 * @param propertyPaths
503 * @return an List which is not specifically ordered
506 public Set
<Taxon
> listRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Integer maxDepth
,
507 Integer limit
, Integer start
, List
<String
> propertyPaths
) {
509 Set
<Taxon
> relatedTaxa
= collectRelatedTaxa(taxon
, includeRelationships
, new HashSet
<Taxon
>(), maxDepth
);
510 relatedTaxa
.remove(taxon
);
511 beanInitializer
.initializeAll(relatedTaxa
, propertyPaths
);
517 * recursively collect related taxa for the given <code>taxon</code> . The returned list will also include the
518 * <code>taxon</code> supplied as parameter.
521 * @param includeRelationships
523 * @param maxDepth can be <code>null</code> for infinite depth
526 private Set
<Taxon
> collectRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Set
<Taxon
> taxa
, Integer maxDepth
) {
532 if(maxDepth
!= null) {
535 if(logger
.isDebugEnabled()){
536 logger
.debug("collecting related taxa for " + taxon
+ " with maxDepth=" + maxDepth
);
538 List
<TaxonRelationship
> taxonRelationships
= dao
.getTaxonRelationships(taxon
, null, null, null, null, null, null);
539 for (TaxonRelationship taxRel
: taxonRelationships
) {
542 if (taxRel
.getToTaxon() == null || taxRel
.getFromTaxon() == null || taxRel
.getType() == null) {
545 // filter by includeRelationships
546 for (TaxonRelationshipEdge relationshipEdgeFilter
: includeRelationships
) {
547 if ( relationshipEdgeFilter
.getTaxonRelationshipType().equals(taxRel
.getType()) ) {
548 if (relationshipEdgeFilter
.getDirections().contains(Direction
.relatedTo
) && !taxa
.contains(taxRel
.getToTaxon())) {
549 if(logger
.isDebugEnabled()){
550 logger
.debug(maxDepth
+ ": " + taxon
.getTitleCache() + " --[" + taxRel
.getType().getLabel() + "]--> " + taxRel
.getToTaxon().getTitleCache());
552 taxa
.add(taxRel
.getToTaxon());
553 if(maxDepth
== null || maxDepth
> 0) {
554 taxa
.addAll(collectRelatedTaxa(taxRel
.getToTaxon(), includeRelationships
, taxa
, maxDepth
));
557 if(relationshipEdgeFilter
.getDirections().contains(Direction
.relatedFrom
) && !taxa
.contains(taxRel
.getFromTaxon())) {
558 taxa
.add(taxRel
.getFromTaxon());
559 if(logger
.isDebugEnabled()){
560 logger
.debug(maxDepth
+ ": " +taxRel
.getFromTaxon().getTitleCache() + " --[" + taxRel
.getType().getLabel() + "]--> " + taxon
.getTitleCache() );
562 if(maxDepth
== null || maxDepth
> 0) {
563 taxa
.addAll(collectRelatedTaxa(taxRel
.getFromTaxon(), includeRelationships
, taxa
, maxDepth
));
573 * @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)
576 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
577 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
579 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
580 if(numberOfResults
> 0) { // no point checking again
581 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
584 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
588 * @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)
591 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
592 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
594 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
595 if(numberOfResults
> 0) { // no point checking again
596 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
599 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
603 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
606 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
607 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
608 return t
.getHomotypicSynonymsByHomotypicGroup();
612 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
615 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
616 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
617 List
<HomotypicalGroup
> homotypicalGroups
= t
.getHeterotypicSynonymyGroups();
618 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(homotypicalGroups
.size());
619 for(HomotypicalGroup homotypicalGroup
: homotypicalGroups
){
620 heterotypicSynonymyGroups
.add(t
.getSynonymsInGroup(homotypicalGroup
));
622 return heterotypicSynonymyGroups
;
626 public List
<UuidAndTitleCache
<TaxonBase
>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator
){
628 List
<UuidAndTitleCache
<TaxonBase
>> result
= new ArrayList
<UuidAndTitleCache
<TaxonBase
>>();
629 // Class<? extends TaxonBase> clazz = null;
630 // if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
631 // clazz = TaxonBase.class;
632 // //propertyPath.addAll(configurator.getTaxonPropertyPath());
633 // //propertyPath.addAll(configurator.getSynonymPropertyPath());
634 // } else if(configurator.isDoTaxa()) {
635 // clazz = Taxon.class;
636 // //propertyPath = configurator.getTaxonPropertyPath();
637 // } else if (configurator.isDoSynonyms()) {
638 // clazz = Synonym.class;
639 // //propertyPath = configurator.getSynonymPropertyPath();
643 result
= dao
.getTaxaByNameForEditor(configurator
.isDoTaxa(), configurator
.isDoSynonyms(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
648 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
651 public Pager
<IdentifiableEntity
> findTaxaAndNames(IFindTaxaAndNamesConfigurator configurator
) {
653 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
654 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
655 List
<TaxonBase
> taxa
= null;
658 long numberTaxaResults
= 0L;
661 List
<String
> propertyPath
= new ArrayList
<String
>();
662 if(configurator
.getTaxonPropertyPath() != null){
663 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
667 if (configurator
.isDoMisappliedNames() || configurator
.isDoSynonyms() || configurator
.isDoTaxa()){
668 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
670 dao
.countTaxaByName(configurator
.isDoTaxa(),configurator
.isDoSynonyms(), configurator
.isDoMisappliedNames(),
671 configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(),
672 configurator
.getNamedAreas());
675 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
676 taxa
= dao
.getTaxaByName(configurator
.isDoTaxa(), configurator
.isDoSynonyms(),
677 configurator
.isDoMisappliedNames(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(),
678 configurator
.getMatchMode(), configurator
.getNamedAreas(),
679 configurator
.getPageSize(), configurator
.getPageNumber(), propertyPath
);
683 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
686 results
.addAll(taxa
);
689 numberOfResults
+= numberTaxaResults
;
691 // Names without taxa
692 if (configurator
.isDoNamesWithoutTaxa()) {
693 int numberNameResults
= 0;
695 List
<?
extends TaxonNameBase
<?
,?
>> names
=
696 nameDao
.findByName(configurator
.getTitleSearchStringSqlized(), configurator
.getMatchMode(),
697 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
698 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
699 if (names
.size() > 0) {
700 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
701 if (taxonName
.getTaxonBases().size() == 0) {
702 results
.add(taxonName
);
706 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
707 numberOfResults
+= numberNameResults
;
711 // Taxa from common names
713 if (configurator
.isDoTaxaByCommonNames()) {
714 taxa
= new ArrayList
<TaxonBase
>();
715 numberTaxaResults
= 0;
716 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
717 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
719 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
720 List
<Object
[]> commonNameResults
= dao
.getTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
721 for( Object
[] entry
: commonNameResults
) {
722 taxa
.add((TaxonBase
) entry
[0]);
726 results
.addAll(taxa
);
728 numberOfResults
+= numberTaxaResults
;
732 return new DefaultPagerImpl
<IdentifiableEntity
>
733 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
736 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
737 return dao
.getUuidAndTitleCache();
741 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])
744 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
745 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
746 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
747 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
748 for (TaxonDescription taxDesc
: descriptions
){
749 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
750 for (DescriptionElementBase descElem
: elements
){
751 for(Media media
: descElem
.getMedia()){
753 //find the best matching representation
754 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, null, size
, height
, widthOrDuration
, mimeTypes
));
763 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxonDescriptionMedia(eu.etaxonomy.cdm.model.taxon.Taxon, boolean)
766 public List
<Media
> listTaxonDescriptionMedia(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, boolean limitToGalleries
, List
<String
> propertyPath
){
767 return listMedia(taxon
, includeRelationships
, limitToGalleries
, true, false, false, propertyPath
);
772 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listMedia(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, boolean, java.util.List)
775 public List
<Media
> listMedia(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
,
776 Boolean limitToGalleries
, Boolean includeTaxonDescriptions
, Boolean includeOccurrences
,
777 Boolean includeTaxonNameDescriptions
, List
<String
> propertyPath
) {
779 Set
<Taxon
> taxa
= new HashSet
<Taxon
>();
780 List
<Media
> taxonMedia
= new ArrayList
<Media
>();
782 if (limitToGalleries
== null) {
783 limitToGalleries
= false;
786 // --- resolve related taxa
787 if (includeRelationships
!= null) {
788 taxa
= listRelatedTaxa(taxon
, includeRelationships
, null, null, null, null);
791 taxa
.add((Taxon
) dao
.load(taxon
.getUuid()));
793 if(includeTaxonDescriptions
!= null && includeTaxonDescriptions
){
794 List
<TaxonDescription
> taxonDescriptions
= new ArrayList
<TaxonDescription
>();
795 // --- TaxonDescriptions
796 for (Taxon t
: taxa
) {
797 taxonDescriptions
.addAll(descriptionService
.listTaxonDescriptions(t
, null, null, null, null, propertyPath
));
799 for (TaxonDescription taxonDescription
: taxonDescriptions
) {
800 if (!limitToGalleries
|| taxonDescription
.isImageGallery()) {
801 for (DescriptionElementBase element
: taxonDescription
.getElements()) {
802 for (Media media
: element
.getMedia()) {
803 taxonMedia
.add(media
);
810 if(includeOccurrences
!= null && includeOccurrences
) {
811 Set
<SpecimenOrObservationBase
> specimensOrObservations
= new HashSet
<SpecimenOrObservationBase
>();
813 for (Taxon t
: taxa
) {
814 specimensOrObservations
.addAll(occurrenceDao
.listByAssociatedTaxon(null, t
, null, null, null, null));
816 for (SpecimenOrObservationBase occurrence
: specimensOrObservations
) {
818 // direct media removed from specimen #3597
819 // taxonMedia.addAll(occurrence.getMedia());
821 // SpecimenDescriptions
822 Set
<SpecimenDescription
> specimenDescriptions
= occurrence
.getSpecimenDescriptions();
823 for (DescriptionBase specimenDescription
: specimenDescriptions
) {
824 if (!limitToGalleries
|| specimenDescription
.isImageGallery()) {
825 Set
<DescriptionElementBase
> elements
= specimenDescription
.getElements();
826 for (DescriptionElementBase element
: elements
) {
827 for (Media media
: element
.getMedia()) {
828 taxonMedia
.add(media
);
835 //TODO why may collections have media attached? #
836 if (occurrence
.isInstanceOf(DerivedUnit
.class)) {
837 DerivedUnit derivedUnit
= CdmBase
.deproxy(occurrence
, DerivedUnit
.class);
838 if (derivedUnit
.getCollection() != null){
839 taxonMedia
.addAll(derivedUnit
.getCollection().getMedia());
843 // pherograms & gelPhotos
844 if (occurrence
.isInstanceOf(DnaSample
.class)) {
845 DnaSample dnaSample
= CdmBase
.deproxy(occurrence
, DnaSample
.class);
846 Set
<Sequence
> sequences
= dnaSample
.getSequences();
847 //we do show only those gelPhotos which lead to a consensus sequence
848 for (Sequence sequence
: sequences
) {
849 Set
<Media
> dnaRelatedMedia
= new HashSet
<Media
>();
850 for (SingleSequence singleSequence
: sequence
.getSingleSequences()){
851 Amplification amplification
= singleSequence
.getAmplification();
852 dnaRelatedMedia
.add(amplification
.getGelPhoto());
853 dnaRelatedMedia
.add(singleSequence
.getPherogram());
854 dnaRelatedMedia
.remove(null);
856 taxonMedia
.addAll(dnaRelatedMedia
);
863 if(includeTaxonNameDescriptions
!= null && includeTaxonNameDescriptions
) {
864 // --- TaxonNameDescription
865 Set
<TaxonNameDescription
> nameDescriptions
= new HashSet
<TaxonNameDescription
>();
866 for (Taxon t
: taxa
) {
867 nameDescriptions
.addAll(t
.getName().getDescriptions());
869 for(TaxonNameDescription nameDescription
: nameDescriptions
){
870 if (!limitToGalleries
|| nameDescription
.isImageGallery()) {
871 Set
<DescriptionElementBase
> elements
= nameDescription
.getElements();
872 for (DescriptionElementBase element
: elements
) {
873 for (Media media
: element
.getMedia()) {
874 taxonMedia
.add(media
);
881 beanInitializer
.initializeAll(taxonMedia
, propertyPath
);
886 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)
889 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
890 return this.dao
.listByIds(listOfIDs
, null, null, null, null);
894 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)
897 public TaxonBase
findTaxonByUuid(UUID uuid
, List
<String
> propertyPaths
){
898 return this.dao
.findByUuid(uuid
, null ,propertyPaths
);
902 * @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()
905 public int countAllRelationships() {
906 return this.dao
.countAllRelationships();
913 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)
916 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
917 return this.dao
.findIdenticalTaxonNames(propertyPath
);
922 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)
925 public void deleteTaxon(Taxon taxon
, TaxonDeletionConfigurator config
) throws ReferencedObjectUndeletableException
{
927 config
= new TaxonDeletionConfigurator();
931 if (! config
.isDeleteTaxonNodes()){
932 if (taxon
.getTaxonNodes().size() > 0){
933 String message
= "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";
934 throw new ReferencedObjectUndeletableException(message
);
939 // SynonymRelationShip
940 if (config
.isDeleteSynonymRelations()){
941 boolean removeSynonymNameFromHomotypicalGroup
= false;
942 for (SynonymRelationship synRel
: taxon
.getSynonymRelations()){
943 Synonym synonym
= synRel
.getSynonym();
944 taxon
.removeSynonymRelation(synRel
, removeSynonymNameFromHomotypicalGroup
);
945 if (config
.isDeleteSynonymsIfPossible()){
947 boolean newHomotypicGroupIfNeeded
= true;
948 deleteSynonym(synonym
, taxon
, config
.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded
);
950 deleteSynonymRelationships(synonym
, taxon
);
956 if (! config
.isDeleteTaxonRelationships()){
957 if (taxon
.getTaxonRelations().size() > 0){
958 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.";
959 throw new ReferencedObjectUndeletableException(message
);
965 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
967 for (TaxonDescription desc
: descriptions
){
968 if (config
.isDeleteDescriptions()){
969 //TODO use description delete configurator ?
970 //FIXME check if description is ALWAYS deletable
971 descriptionService
.delete(desc
);
973 if (desc
.getDescribedSpecimenOrObservation() != null){
974 String message
= "Taxon can't be deleted as it is used in a TaxonDescription" +
975 " which also describes specimens or abservations";
976 throw new ReferencedObjectUndeletableException(message
);
982 //check references with only reverse mapping
983 Set
<CdmBase
> referencingObjects
= genericDao
.getReferencingObjects(taxon
);
984 for (CdmBase referencingObject
: referencingObjects
){
985 //IIdentificationKeys (Media, Polytomous, MultiAccess)
986 if (HibernateProxyHelper
.isInstanceOf(referencingObject
, IIdentificationKey
.class)){
987 String message
= "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";
988 message
= String
.format(message
, CdmBase
.deproxy(referencingObject
, DerivedUnit
.class).getTitleCache());
989 throw new ReferencedObjectUndeletableException(message
);
994 if (referencingObject
.isInstanceOf(PolytomousKeyNode
.class)){
995 String message
= "Taxon can't be deleted as it is used in polytomous key node";
996 throw new ReferencedObjectUndeletableException(message
);
1000 if (referencingObject
.isInstanceOf(TaxonInteraction
.class)){
1001 String message
= "Taxon can't be deleted as it is used in taxonInteraction#taxon2";
1002 throw new ReferencedObjectUndeletableException(message
);
1008 if (config
.isDeleteNameIfPossible()){
1010 nameService
.delete(taxon
.getName(), config
.getNameDeletionConfig());
1011 } catch (ReferencedObjectUndeletableException e
) {
1013 if (logger
.isDebugEnabled()){logger
.debug("Name could not be deleted");}
1020 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)
1022 @Transactional(readOnly
= false)
1024 public void deleteSynonym(Synonym synonym
, Taxon taxon
, boolean removeNameIfPossible
,boolean newHomotypicGroupIfNeeded
) {
1025 if (synonym
== null){
1028 synonym
= CdmBase
.deproxy(dao
.merge(synonym
), Synonym
.class);
1030 //remove synonymRelationship
1031 Set
<Taxon
> taxonSet
= new HashSet
<Taxon
>();
1033 taxonSet
.add(taxon
);
1035 taxonSet
.addAll(synonym
.getAcceptedTaxa());
1037 for (Taxon relatedTaxon
: taxonSet
){
1038 // dao.deleteSynonymRelationships(synonym, relatedTaxon);
1039 relatedTaxon
.removeSynonym(synonym
, newHomotypicGroupIfNeeded
);
1041 this.saveOrUpdate(synonym
);
1043 //TODO remove name from homotypical group?
1045 //remove synonym (if necessary)
1046 if (synonym
.getSynonymRelations().isEmpty()){
1047 TaxonNameBase
<?
,?
> name
= synonym
.getName();
1048 synonym
.setName(null);
1049 dao
.delete(synonym
);
1051 //remove name if possible (and required)
1052 if (name
!= null && removeNameIfPossible
){
1054 nameService
.delete(name
, new NameDeletionConfigurator());
1055 }catch (DataChangeNoRollbackException ex
){
1056 if (logger
.isDebugEnabled()) {
1057 logger
.debug("Name wasn't deleted as it is referenced");
1066 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)
1069 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
1071 return this.dao
.findIdenticalNamesNew(propertyPath
);
1075 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
1078 public String
getPhylumName(TaxonNameBase name
){
1079 return this.dao
.getPhylumName(name
);
1083 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
1086 public long deleteSynonymRelationships(Synonym syn
, Taxon taxon
) {
1087 return dao
.deleteSynonymRelationships(syn
, taxon
);
1091 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)
1094 public long deleteSynonymRelationships(Synonym syn
) {
1095 return dao
.deleteSynonymRelationships(syn
, null);
1100 * @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)
1103 public List
<SynonymRelationship
> listSynonymRelationships(
1104 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
1105 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
1106 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
1108 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
1109 if(numberOfResults
> 0) { // no point checking again
1110 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
1116 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingTaxon(java.lang.String)
1119 public Taxon
findBestMatchingTaxon(String taxonName
) {
1120 MatchingTaxonConfigurator config
= MatchingTaxonConfigurator
.NewInstance();
1121 config
.setTaxonNameTitle(taxonName
);
1122 return findBestMatchingTaxon(config
);
1128 public Taxon
findBestMatchingTaxon(MatchingTaxonConfigurator config
) {
1130 Taxon bestCandidate
= null;
1132 // 1. search for acceptet taxa
1133 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(true, false, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
1134 boolean bestCandidateMatchesSecUuid
= false;
1135 boolean bestCandidateIsInClassification
= false;
1136 int countEqualCandidates
= 0;
1137 for(TaxonBase taxonBaseCandidate
: taxonList
){
1138 if(taxonBaseCandidate
instanceof Taxon
){
1139 Taxon newCanditate
= CdmBase
.deproxy(taxonBaseCandidate
, Taxon
.class);
1140 boolean newCandidateMatchesSecUuid
= isMatchesSecUuid(newCanditate
, config
);
1141 if (! newCandidateMatchesSecUuid
&& config
.isOnlyMatchingSecUuid() ){
1143 }else if(newCandidateMatchesSecUuid
&& ! bestCandidateMatchesSecUuid
){
1144 bestCandidate
= newCanditate
;
1145 countEqualCandidates
= 1;
1146 bestCandidateMatchesSecUuid
= true;
1150 boolean newCandidateInClassification
= isInClassification(newCanditate
, config
);
1151 if (! newCandidateInClassification
&& config
.isOnlyMatchingClassificationUuid()){
1153 }else if (newCandidateInClassification
&& ! bestCandidateIsInClassification
){
1154 bestCandidate
= newCanditate
;
1155 countEqualCandidates
= 1;
1156 bestCandidateIsInClassification
= true;
1159 if (bestCandidate
== null){
1160 bestCandidate
= newCanditate
;
1161 countEqualCandidates
= 1;
1165 }else{ //not Taxon.class
1168 countEqualCandidates
++;
1171 if (bestCandidate
!= null){
1172 if(countEqualCandidates
> 1){
1173 logger
.info(countEqualCandidates
+ " equally matching TaxonBases found, using first accepted Taxon: " + bestCandidate
.getTitleCache());
1174 return bestCandidate
;
1176 logger
.info("using accepted Taxon: " + bestCandidate
.getTitleCache());
1177 return bestCandidate
;
1182 // 2. search for synonyms
1183 if (config
.isIncludeSynonyms()){
1184 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
1185 for(TaxonBase taxonBase
: synonymList
){
1186 if(taxonBase
instanceof Synonym
){
1187 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
1188 Set
<Taxon
> acceptetdCandidates
= synonym
.getAcceptedTaxa();
1189 if(!acceptetdCandidates
.isEmpty()){
1190 bestCandidate
= acceptetdCandidates
.iterator().next();
1191 if(acceptetdCandidates
.size() == 1){
1192 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + bestCandidate
.getTitleCache());
1193 return bestCandidate
;
1195 logger
.info("using accepted Taxon " + bestCandidate
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
1196 return bestCandidate
;
1198 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
1204 } catch (Exception e
){
1208 return bestCandidate
;
1211 private boolean isInClassification(Taxon taxon
, MatchingTaxonConfigurator config
) {
1212 UUID configClassificationUuid
= config
.getClassificationUuid();
1213 if (configClassificationUuid
== null){
1216 for (TaxonNode node
: taxon
.getTaxonNodes()){
1217 UUID classUuid
= node
.getClassification().getUuid();
1218 if (configClassificationUuid
.equals(classUuid
)){
1225 private boolean isMatchesSecUuid(Taxon taxon
, MatchingTaxonConfigurator config
) {
1226 UUID configSecUuid
= config
.getSecUuid();
1227 if (configSecUuid
== null){
1230 UUID taxonSecUuid
= (taxon
.getSec() == null)?
null : taxon
.getSec().getUuid();
1231 return configSecUuid
.equals(taxonSecUuid
);
1235 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
1238 public Synonym
findBestMatchingSynonym(String taxonName
) {
1239 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
1240 if(! synonymList
.isEmpty()){
1241 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
1242 if(synonymList
.size() == 1){
1243 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
1246 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());
1255 * @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)
1258 public SynonymRelationship
moveSynonymToAnotherTaxon(SynonymRelationship oldSynonymRelation
, Taxon newTaxon
, boolean moveHomotypicGroup
,
1259 SynonymRelationshipType newSynonymRelationshipType
, Reference reference
, String referenceDetail
, boolean keepReference
) throws HomotypicalGroupChangeException
{
1261 Synonym synonym
= oldSynonymRelation
.getSynonym();
1262 Taxon fromTaxon
= oldSynonymRelation
.getAcceptedTaxon();
1263 //TODO what if there is no name ?? Concepts may be cached (e.g. via TCS import)
1264 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
1265 TaxonNameBase
<?
,?
> fromTaxonName
= fromTaxon
.getName();
1266 //set default relationship type
1267 if (newSynonymRelationshipType
== null){
1268 newSynonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
1270 boolean newRelTypeIsHomotypic
= newSynonymRelationshipType
.equals(SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF());
1272 HomotypicalGroup homotypicGroup
= synonymName
.getHomotypicalGroup();
1273 int hgSize
= homotypicGroup
.getTypifiedNames().size();
1274 boolean isSingleInGroup
= !(hgSize
> 1);
1276 if (! isSingleInGroup
){
1277 boolean isHomotypicToAccepted
= synonymName
.isHomotypic(fromTaxonName
);
1278 boolean hasHomotypicSynonymRelatives
= isHomotypicToAccepted ? hgSize
> 2 : hgSize
> 1;
1279 if (isHomotypicToAccepted
){
1280 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.";
1281 String homotypicRelatives
= hasHomotypicSynonymRelatives ?
" and other synonym(s)":"";
1282 message
= String
.format(message
, homotypicRelatives
);
1283 throw new HomotypicalGroupChangeException(message
);
1285 if (! moveHomotypicGroup
){
1286 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.";
1287 throw new HomotypicalGroupChangeException(message
);
1290 moveHomotypicGroup
= true; //single synonym always allows to moveCompleteGroup
1292 // Assert.assertTrue("Synonym can only be moved with complete homotypic group", moveHomotypicGroup);
1294 SynonymRelationship result
= null;
1295 //move all synonyms to new taxon
1296 List
<Synonym
> homotypicSynonyms
= fromTaxon
.getSynonymsInGroup(homotypicGroup
);
1297 for (Synonym syn
: homotypicSynonyms
){
1298 Set
<SynonymRelationship
> synRelations
= syn
.getSynonymRelations();
1299 for (SynonymRelationship synRelation
: synRelations
){
1300 if (fromTaxon
.equals(synRelation
.getAcceptedTaxon())){
1301 Reference
<?
> newReference
= reference
;
1302 if (newReference
== null && keepReference
){
1303 newReference
= synRelation
.getCitation();
1305 String newRefDetail
= referenceDetail
;
1306 if (newRefDetail
== null && keepReference
){
1307 newRefDetail
= synRelation
.getCitationMicroReference();
1309 SynonymRelationship newSynRelation
= newTaxon
.addSynonym(syn
, newSynonymRelationshipType
, newReference
, newRefDetail
);
1310 fromTaxon
.removeSynonymRelation(synRelation
, false);
1312 //change homotypic group of synonym if relType is 'homotypic'
1313 // if (newRelTypeIsHomotypic){
1314 // newTaxon.getName().getHomotypicalGroup().addTypifiedName(syn.getName());
1317 if (synRelation
.equals(oldSynonymRelation
)){
1318 result
= newSynRelation
;
1324 saveOrUpdate(newTaxon
);
1325 //Assert that there is a result
1326 if (result
== null){
1327 String message
= "Old synonym relation could not be transformed into new relation. This should not happen.";
1328 throw new IllegalStateException(message
);
1334 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
1337 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheTaxon() {
1338 return dao
.getUuidAndTitleCacheTaxon();
1342 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
1345 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheSynonym() {
1346 return dao
.getUuidAndTitleCacheSynonym();
1350 * @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)
1353 public Pager
<SearchResult
<TaxonBase
>> findByFullText(
1354 Class
<?
extends TaxonBase
> clazz
, String queryString
,
1355 Classification classification
, List
<Language
> languages
,
1356 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1359 LuceneSearch luceneSearch
= prepareFindByFullTextSearch(clazz
, queryString
, classification
, languages
, highlightFragments
);
1361 // --- execute search
1362 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1364 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1365 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1367 // --- initialize taxa, thighlight matches ....
1368 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1369 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1370 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1372 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1373 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1378 * @param queryString
1379 * @param classification
1381 * @param highlightFragments
1382 * @param directorySelectClass
1385 protected LuceneSearch
prepareFindByFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Language
> languages
,
1386 boolean highlightFragments
) {
1387 BooleanQuery finalQuery
= new BooleanQuery();
1388 BooleanQuery textQuery
= new BooleanQuery();
1390 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), TaxonBase
.class);
1391 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1393 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("titleCache__sort", SortField
.STRING
, false)};
1394 luceneSearch
.setSortFields(sortFields
);
1396 // ---- search criteria
1397 luceneSearch
.setClazz(clazz
);
1399 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1400 textQuery
.add(queryFactory
.newDefinedTermQuery("name.rank", queryString
, languages
), Occur
.SHOULD
);
1402 finalQuery
.add(textQuery
, Occur
.MUST
);
1404 if(classification
!= null){
1405 finalQuery
.add(queryFactory
.newEntityIdQuery("taxonNodes.classification.id", classification
), Occur
.MUST
);
1407 luceneSearch
.setQuery(finalQuery
);
1409 if(highlightFragments
){
1410 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1412 return luceneSearch
;
1417 * @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)
1420 public Pager
<SearchResult
<TaxonBase
>> findByDescriptionElementFullText(
1421 Class
<?
extends DescriptionElementBase
> clazz
, String queryString
,
1422 Classification classification
, List
<Feature
> features
, List
<Language
> languages
,
1423 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1426 LuceneSearch luceneSearch
= prepareByDescriptionElementFullTextSearch(clazz
, queryString
, classification
, features
, languages
, highlightFragments
);
1428 // --- execute search
1429 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1431 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1432 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1434 // --- initialize taxa, highlight matches ....
1435 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1436 @SuppressWarnings("rawtypes")
1437 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1438 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1440 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupCount
: 0;
1441 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1447 public Pager
<SearchResult
<TaxonBase
>> findByEverythingFullText(String queryString
,
1448 Classification classification
, List
<Language
> languages
, boolean highlightFragments
,
1449 Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1451 LuceneSearch luceneSearchByDescriptionElement
= prepareByDescriptionElementFullTextSearch(null, queryString
, classification
, null, languages
, highlightFragments
);
1452 LuceneSearch luceneSearchByTaxonBase
= prepareFindByFullTextSearch(null, queryString
, classification
, languages
, highlightFragments
);
1454 LuceneMultiSearch multiSearch
= new LuceneMultiSearch(luceneSearchByDescriptionElement
, luceneSearchByTaxonBase
);
1456 // --- execute search
1457 TopGroupsWithMaxScore topDocsResultSet
= multiSearch
.executeSearch(pageSize
, pageNumber
);
1459 // --- initialize taxa, highlight matches ....
1460 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(multiSearch
, multiSearch
.getQuery());
1462 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1463 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1464 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1466 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1467 topDocsResultSet
, multiSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1469 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1470 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1477 * @param queryString
1478 * @param classification
1481 * @param highlightFragments
1482 * @param directorySelectClass
1485 protected LuceneSearch
prepareByDescriptionElementFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Feature
> features
,
1486 List
<Language
> languages
, boolean highlightFragments
) {
1487 BooleanQuery finalQuery
= new BooleanQuery();
1488 BooleanQuery textQuery
= new BooleanQuery();
1490 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), GroupByTaxonClassBridge
.GROUPBY_TAXON_FIELD
, DescriptionElementBase
.class);
1491 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1493 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("inDescription.taxon.titleCache__sort", SortField
.STRING
, false)};
1494 luceneSearch
.setSortFields(sortFields
);
1496 // ---- search criteria
1497 luceneSearch
.setClazz(clazz
);
1498 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1502 if(languages
== null || languages
.size() == 0){
1503 nameQuery
= queryFactory
.newTermQuery("name", queryString
);
1505 nameQuery
= new BooleanQuery();
1506 BooleanQuery languageSubQuery
= new BooleanQuery();
1507 for(Language lang
: languages
){
1508 languageSubQuery
.add(queryFactory
.newTermQuery("language.uuid", lang
.getUuid().toString(), false), Occur
.SHOULD
);
1510 ((BooleanQuery
) nameQuery
).add(queryFactory
.newTermQuery("name", queryString
), Occur
.MUST
);
1511 ((BooleanQuery
) nameQuery
).add(languageSubQuery
, Occur
.MUST
);
1513 textQuery
.add(nameQuery
, Occur
.SHOULD
);
1516 // text field from TextData
1517 textQuery
.add(queryFactory
.newMultilanguageTextQuery("text", queryString
, languages
), Occur
.SHOULD
);
1519 // --- TermBase fields - by representation ----
1520 // state field from CategoricalData
1521 textQuery
.add(queryFactory
.newDefinedTermQuery("stateData.state", queryString
, languages
), Occur
.SHOULD
);
1523 // state field from CategoricalData
1524 textQuery
.add(queryFactory
.newDefinedTermQuery("stateData.modifyingText", queryString
, languages
), Occur
.SHOULD
);
1526 // area field from Distribution
1527 textQuery
.add(queryFactory
.newDefinedTermQuery("area", queryString
, languages
), Occur
.SHOULD
);
1529 // status field from Distribution
1530 textQuery
.add(queryFactory
.newDefinedTermQuery("status", queryString
, languages
), Occur
.SHOULD
);
1532 finalQuery
.add(textQuery
, Occur
.MUST
);
1533 // --- classification ----
1535 if(classification
!= null){
1536 finalQuery
.add(queryFactory
.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification
), Occur
.MUST
);
1539 // --- IdentifieableEntity fields - by uuid
1540 if(features
!= null && features
.size() > 0 ){
1541 finalQuery
.add(queryFactory
.newEntityUuidQuery("feature.uuid", features
), Occur
.MUST
);
1544 // the description must be associated with a taxon
1545 finalQuery
.add(queryFactory
.newIsNotNullQuery("inDescription.taxon.id"), Occur
.MUST
);
1547 logger
.info("prepareByDescriptionElementFullTextSearch() query: " + finalQuery
.toString());
1548 luceneSearch
.setQuery(finalQuery
);
1550 if(highlightFragments
){
1551 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1553 return luceneSearch
;
1557 * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}
1558 * and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.
1559 * This method is a convenient means to retrieve a Lucene query string for such the fields.
1561 * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}
1562 * or {@link MultilanguageTextFieldBridge }
1563 * @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages
1564 * @param stringBuilder a StringBuilder to be reused, if <code>null</code> a new StringBuilder will be instantiated and is returned
1565 * @return the StringBuilder given a parameter or a new one if the stringBuilder parameter was null.
1567 * TODO move to utiliy class !!!!!!!!
1569 private StringBuilder
appendLocalizedFieldQuery(String name
, List
<Language
> languages
, StringBuilder stringBuilder
) {
1571 if(stringBuilder
== null){
1572 stringBuilder
= new StringBuilder();
1574 if(languages
== null || languages
.size() == 0){
1575 stringBuilder
.append(name
+ ".ALL:(%1$s) ");
1577 for(Language lang
: languages
){
1578 stringBuilder
.append(name
+ "." + lang
.getUuid().toString() + ":(%1$s) ");
1581 return stringBuilder
;
1585 public List
<Synonym
> createInferredSynonyms(Taxon taxon
, Classification classification
, SynonymRelationshipType type
, boolean doWithMisappliedNames
){
1586 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1587 List
<Synonym
> inferredSynonymsToBeRemoved
= new ArrayList
<Synonym
>();
1589 HashMap
<UUID
, ZoologicalName
> zooHashMap
= new HashMap
<UUID
, ZoologicalName
>();
1592 UUID nameUuid
= taxon
.getName().getUuid();
1593 ZoologicalName taxonName
= getZoologicalName(nameUuid
, zooHashMap
);
1594 String epithetOfTaxon
= null;
1595 String infragenericEpithetOfTaxon
= null;
1596 String infraspecificEpithetOfTaxon
= null;
1597 if (taxonName
.isSpecies()){
1598 epithetOfTaxon
= taxonName
.getSpecificEpithet();
1599 } else if (taxonName
.isInfraGeneric()){
1600 infragenericEpithetOfTaxon
= taxonName
.getInfraGenericEpithet();
1601 } else if (taxonName
.isInfraSpecific()){
1602 infraspecificEpithetOfTaxon
= taxonName
.getInfraSpecificEpithet();
1604 String genusOfTaxon
= taxonName
.getGenusOrUninomial();
1605 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1606 List
<String
> taxonNames
= new ArrayList
<String
>();
1608 for (TaxonNode node
: nodes
){
1609 // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName
1610 // List<String> synonymsEpithet = new ArrayList<String>();
1612 if (node
.getClassification().equals(classification
)){
1613 if (!node
.isTopmostNode()){
1614 TaxonNode parent
= node
.getParent();
1615 parent
= (TaxonNode
)HibernateProxyHelper
.deproxy(parent
);
1616 TaxonNameBase
<?
,?
> parentName
= parent
.getTaxon().getName();
1617 ZoologicalName zooParentName
= HibernateProxyHelper
.deproxy(parentName
, ZoologicalName
.class);
1618 Taxon parentTaxon
= (Taxon
)HibernateProxyHelper
.deproxy(parent
.getTaxon());
1619 Rank rankOfTaxon
= taxonName
.getRank();
1622 //create inferred synonyms for species, subspecies
1623 if ((parentName
.isGenus() || parentName
.isSpecies() || parentName
.getRank().equals(Rank
.SUBGENUS())) ){
1625 Synonym inferredEpithet
= null;
1626 Synonym inferredGenus
= null;
1627 Synonym potentialCombination
= null;
1629 List
<String
> propertyPaths
= new ArrayList
<String
>();
1630 propertyPaths
.add("synonym");
1631 propertyPaths
.add("synonym.name");
1632 List
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
1633 orderHints
.add(new OrderHint("relatedFrom.titleCache", SortOrder
.ASCENDING
));
1635 List
<SynonymRelationship
> synonymRelationshipsOfParent
= dao
.getSynonyms(parentTaxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1636 List
<SynonymRelationship
> synonymRelationshipsOfTaxon
= dao
.getSynonyms(taxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1638 List
<TaxonRelationship
> taxonRelListParent
= null;
1639 List
<TaxonRelationship
> taxonRelListTaxon
= null;
1640 if (doWithMisappliedNames
){
1641 taxonRelListParent
= dao
.getTaxonRelationships(parentTaxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1642 taxonRelListTaxon
= dao
.getTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1646 if (type
.equals(SynonymRelationshipType
.INFERRED_EPITHET_OF())){
1649 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1650 Synonym syn
= synonymRelationOfParent
.getSynonym();
1652 inferredEpithet
= createInferredEpithets(taxon
,
1653 zooHashMap
, taxonName
, epithetOfTaxon
,
1654 infragenericEpithetOfTaxon
,
1655 infraspecificEpithetOfTaxon
,
1656 taxonNames
, parentName
,
1660 inferredSynonyms
.add(inferredEpithet
);
1661 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1662 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1665 if (doWithMisappliedNames
){
1667 for (TaxonRelationship taxonRelationship
: taxonRelListParent
){
1668 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1670 inferredEpithet
= createInferredEpithets(taxon
,
1671 zooHashMap
, taxonName
, epithetOfTaxon
,
1672 infragenericEpithetOfTaxon
,
1673 infraspecificEpithetOfTaxon
,
1674 taxonNames
, parentName
,
1677 inferredSynonyms
.add(inferredEpithet
);
1678 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1679 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1683 if (!taxonNames
.isEmpty()){
1684 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1685 ZoologicalName name
;
1686 if (!synNotInCDM
.isEmpty()){
1687 inferredSynonymsToBeRemoved
.clear();
1689 for (Synonym syn
:inferredSynonyms
){
1690 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1691 if (!synNotInCDM
.contains(name
.getNameCache())){
1692 inferredSynonymsToBeRemoved
.add(syn
);
1696 // Remove identified Synonyms from inferredSynonyms
1697 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1698 inferredSynonyms
.remove(synonym
);
1703 }else if (type
.equals(SynonymRelationshipType
.INFERRED_GENUS_OF())){
1706 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1707 TaxonNameBase synName
;
1708 ZoologicalName inferredSynName
;
1710 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1711 inferredGenus
= createInferredGenus(taxon
,
1712 zooHashMap
, taxonName
, epithetOfTaxon
,
1713 genusOfTaxon
, taxonNames
, zooParentName
, syn
);
1715 inferredSynonyms
.add(inferredGenus
);
1716 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1717 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1722 if (doWithMisappliedNames
){
1724 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1725 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1726 inferredGenus
= createInferredGenus(taxon
, zooHashMap
, taxonName
, infraspecificEpithetOfTaxon
, genusOfTaxon
, taxonNames
, zooParentName
, misappliedName
);
1728 inferredSynonyms
.add(inferredGenus
);
1729 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1730 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1735 if (!taxonNames
.isEmpty()){
1736 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1737 ZoologicalName name
;
1738 if (!synNotInCDM
.isEmpty()){
1739 inferredSynonymsToBeRemoved
.clear();
1741 for (Synonym syn
:inferredSynonyms
){
1742 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1743 if (!synNotInCDM
.contains(name
.getNameCache())){
1744 inferredSynonymsToBeRemoved
.add(syn
);
1748 // Remove identified Synonyms from inferredSynonyms
1749 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1750 inferredSynonyms
.remove(synonym
);
1755 }else if (type
.equals(SynonymRelationshipType
.POTENTIAL_COMBINATION_OF())){
1757 Reference sourceReference
= null; // TODO: Determination of sourceReference is redundant
1758 ZoologicalName inferredSynName
;
1759 //for all synonyms of the parent...
1760 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1761 TaxonNameBase synName
;
1762 Synonym synParent
= synonymRelationOfParent
.getSynonym();
1763 synName
= synParent
.getName();
1765 HibernateProxyHelper
.deproxy(synParent
);
1767 // Set the sourceReference
1768 sourceReference
= synParent
.getSec();
1770 // Determine the idInSource
1771 String idInSourceParent
= getIdInSource(synParent
);
1773 ZoologicalName parentSynZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1774 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1775 String synParentInfragenericName
= null;
1776 String synParentSpecificEpithet
= null;
1778 if (parentSynZooName
.isInfraGeneric()){
1779 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1781 if (parentSynZooName
.isSpecies()){
1782 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1785 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1786 synonymsGenus.put(synGenusName, idInSource);
1789 //for all synonyms of the taxon
1791 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1793 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1794 ZoologicalName zooSynName
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1795 potentialCombination
= createPotentialCombination(idInSourceParent
, parentSynZooName
, zooSynName
,
1797 synParentInfragenericName
,
1798 synParentSpecificEpithet
, syn
, zooHashMap
);
1800 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1801 inferredSynonyms
.add(potentialCombination
);
1802 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1803 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1810 if (doWithMisappliedNames
){
1812 for (TaxonRelationship parentRelationship
: taxonRelListParent
){
1814 TaxonNameBase misappliedParentName
;
1816 Taxon misappliedParent
= parentRelationship
.getFromTaxon();
1817 misappliedParentName
= misappliedParent
.getName();
1819 HibernateProxyHelper
.deproxy(misappliedParent
);
1821 // Set the sourceReference
1822 sourceReference
= misappliedParent
.getSec();
1824 // Determine the idInSource
1825 String idInSourceParent
= getIdInSource(misappliedParent
);
1827 ZoologicalName parentSynZooName
= getZoologicalName(misappliedParentName
.getUuid(), zooHashMap
);
1828 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1829 String synParentInfragenericName
= null;
1830 String synParentSpecificEpithet
= null;
1832 if (parentSynZooName
.isInfraGeneric()){
1833 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1835 if (parentSynZooName
.isSpecies()){
1836 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1840 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1841 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1842 ZoologicalName zooMisappliedName
= getZoologicalName(misappliedName
.getName().getUuid(), zooHashMap
);
1843 potentialCombination
= createPotentialCombination(
1844 idInSourceParent
, parentSynZooName
, zooMisappliedName
,
1846 synParentInfragenericName
,
1847 synParentSpecificEpithet
, misappliedName
, zooHashMap
);
1850 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1851 inferredSynonyms
.add(potentialCombination
);
1852 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1853 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1858 if (!taxonNames
.isEmpty()){
1859 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1860 ZoologicalName name
;
1861 if (!synNotInCDM
.isEmpty()){
1862 inferredSynonymsToBeRemoved
.clear();
1863 for (Synonym syn
:inferredSynonyms
){
1865 name
= (ZoologicalName
) syn
.getName();
1866 }catch (ClassCastException e
){
1867 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1869 if (!synNotInCDM
.contains(name
.getNameCache())){
1870 inferredSynonymsToBeRemoved
.add(syn
);
1873 // Remove identified Synonyms from inferredSynonyms
1874 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1875 inferredSynonyms
.remove(synonym
);
1881 logger
.info("The synonymrelationship type is not defined.");
1882 return inferredSynonyms
;
1889 return inferredSynonyms
;
1892 private Synonym
createPotentialCombination(String idInSourceParent
,
1893 ZoologicalName parentSynZooName
, ZoologicalName zooSynName
, String synParentGenus
,
1894 String synParentInfragenericName
, String synParentSpecificEpithet
,
1895 TaxonBase syn
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1896 Synonym potentialCombination
;
1897 Reference sourceReference
;
1898 ZoologicalName inferredSynName
;
1899 HibernateProxyHelper
.deproxy(syn
);
1901 // Set sourceReference
1902 sourceReference
= syn
.getSec();
1903 if (sourceReference
== null){
1904 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
1906 if (!parentSynZooName
.getTaxa().isEmpty()){
1907 TaxonBase taxon
= parentSynZooName
.getTaxa().iterator().next();
1909 sourceReference
= taxon
.getSec();
1912 String synTaxonSpecificEpithet
= zooSynName
.getSpecificEpithet();
1914 String synTaxonInfraSpecificName
= null;
1916 if (parentSynZooName
.isSpecies()){
1917 synTaxonInfraSpecificName
= zooSynName
.getInfraSpecificEpithet();
1920 /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){
1921 synonymsEpithet.add(epithetName);
1924 //create potential combinations...
1925 inferredSynName
= ZoologicalName
.NewInstance(syn
.getName().getRank());
1927 inferredSynName
.setGenusOrUninomial(synParentGenus
);
1928 if (zooSynName
.isSpecies()){
1929 inferredSynName
.setSpecificEpithet(synTaxonSpecificEpithet
);
1930 if (parentSynZooName
.isInfraGeneric()){
1931 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1934 if (zooSynName
.isInfraSpecific()){
1935 inferredSynName
.setSpecificEpithet(synParentSpecificEpithet
);
1936 inferredSynName
.setInfraSpecificEpithet(synTaxonInfraSpecificName
);
1938 if (parentSynZooName
.isInfraGeneric()){
1939 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1943 potentialCombination
= Synonym
.NewInstance(inferredSynName
, null);
1945 // Set the sourceReference
1946 potentialCombination
.setSec(sourceReference
);
1949 // Determine the idInSource
1950 String idInSourceSyn
= getIdInSource(syn
);
1952 if (idInSourceParent
!= null && idInSourceSyn
!= null) {
1953 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
, idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1954 inferredSynName
.addSource(originalSource
);
1955 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
, idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1956 potentialCombination
.addSource(originalSource
);
1959 inferredSynName
.generateTitle();
1961 return potentialCombination
;
1964 private Synonym
createInferredGenus(Taxon taxon
,
1965 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1966 String epithetOfTaxon
, String genusOfTaxon
,
1967 List
<String
> taxonNames
, ZoologicalName zooParentName
,
1970 Synonym inferredGenus
;
1971 TaxonNameBase synName
;
1972 ZoologicalName inferredSynName
;
1973 synName
=syn
.getName();
1974 HibernateProxyHelper
.deproxy(syn
);
1976 // Determine the idInSource
1977 String idInSourceSyn
= getIdInSource(syn
);
1978 String idInSourceTaxon
= getIdInSource(taxon
);
1979 // Determine the sourceReference
1980 Reference sourceReference
= syn
.getSec();
1982 //logger.warn(sourceReference.getTitleCache());
1984 synName
= syn
.getName();
1985 ZoologicalName synZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1986 String synSpeciesEpithetName
= synZooName
.getSpecificEpithet();
1987 /* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){
1988 synonymsEpithet.add(synSpeciesEpithetName);
1991 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1992 //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...
1995 inferredSynName
.setGenusOrUninomial(genusOfTaxon
);
1996 if (zooParentName
.isInfraGeneric()){
1997 inferredSynName
.setInfraGenericEpithet(zooParentName
.getInfraGenericEpithet());
2000 if (taxonName
.isSpecies()){
2001 inferredSynName
.setSpecificEpithet(synSpeciesEpithetName
);
2003 if (taxonName
.isInfraSpecific()){
2004 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2005 inferredSynName
.setInfraSpecificEpithet(synZooName
.getInfraGenericEpithet());
2009 inferredGenus
= Synonym
.NewInstance(inferredSynName
, null);
2011 // Set the sourceReference
2012 inferredGenus
.setSec(sourceReference
);
2014 // Add the original source
2015 if (idInSourceSyn
!= null && idInSourceTaxon
!= null) {
2016 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2017 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2018 inferredGenus
.addSource(originalSource
);
2020 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2021 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2022 inferredSynName
.addSource(originalSource
);
2023 originalSource
= null;
2026 logger
.error("There is an idInSource missing: " + idInSourceSyn
+ " of Synonym or " + idInSourceTaxon
+ " of Taxon");
2027 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2028 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2029 inferredGenus
.addSource(originalSource
);
2031 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2032 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2033 inferredSynName
.addSource(originalSource
);
2034 originalSource
= null;
2037 taxon
.addSynonym(inferredGenus
, SynonymRelationshipType
.INFERRED_GENUS_OF());
2039 inferredSynName
.generateTitle();
2042 return inferredGenus
;
2045 private Synonym
createInferredEpithets(Taxon taxon
,
2046 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
2047 String epithetOfTaxon
, String infragenericEpithetOfTaxon
,
2048 String infraspecificEpithetOfTaxon
, List
<String
> taxonNames
,
2049 TaxonNameBase parentName
, TaxonBase syn
) {
2051 Synonym inferredEpithet
;
2052 TaxonNameBase
<?
,?
> synName
;
2053 ZoologicalName inferredSynName
;
2054 HibernateProxyHelper
.deproxy(syn
);
2056 // Determine the idInSource
2057 String idInSourceSyn
= getIdInSource(syn
);
2058 String idInSourceTaxon
= getIdInSource(taxon
);
2059 // Determine the sourceReference
2060 Reference
<?
> sourceReference
= syn
.getSec();
2062 if (sourceReference
== null){
2063 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
2065 System
.out
.println("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon
.getSec());
2066 sourceReference
= taxon
.getSec();
2069 synName
= syn
.getName();
2070 ZoologicalName zooSynName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
2071 String synGenusName
= zooSynName
.getGenusOrUninomial();
2072 String synInfraGenericEpithet
= null;
2073 String synSpecificEpithet
= null;
2075 if (zooSynName
.getInfraGenericEpithet() != null){
2076 synInfraGenericEpithet
= zooSynName
.getInfraGenericEpithet();
2079 if (zooSynName
.isInfraSpecific()){
2080 synSpecificEpithet
= zooSynName
.getSpecificEpithet();
2083 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
2084 synonymsGenus.put(synGenusName, idInSource);
2087 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
2089 // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!
2090 if (epithetOfTaxon
== null && infragenericEpithetOfTaxon
== null && infraspecificEpithetOfTaxon
== null) {
2091 logger
.error("This specificEpithet is NULL" + taxon
.getTitleCache());
2093 inferredSynName
.setGenusOrUninomial(synGenusName
);
2095 if (parentName
.isInfraGeneric()){
2096 inferredSynName
.setInfraGenericEpithet(synInfraGenericEpithet
);
2098 if (taxonName
.isSpecies()){
2099 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2100 }else if (taxonName
.isInfraSpecific()){
2101 inferredSynName
.setSpecificEpithet(synSpecificEpithet
);
2102 inferredSynName
.setInfraSpecificEpithet(infraspecificEpithetOfTaxon
);
2105 inferredEpithet
= Synonym
.NewInstance(inferredSynName
, null);
2107 // Set the sourceReference
2108 inferredEpithet
.setSec(sourceReference
);
2110 /* Add the original source
2111 if (idInSource != null) {
2112 IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);
2115 Reference citation = getCitation(syn);
2116 if (citation != null) {
2117 originalSource.setCitation(citation);
2118 inferredEpithet.addSource(originalSource);
2121 String taxonId
= idInSourceTaxon
+ "; " + idInSourceSyn
;
2124 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2125 taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2127 inferredEpithet
.addSource(originalSource
);
2129 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2130 taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2132 inferredSynName
.addSource(originalSource
);
2136 taxon
.addSynonym(inferredEpithet
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
2138 inferredSynName
.generateTitle();
2139 return inferredEpithet
;
2143 * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.
2144 * Very likely only useful for createInferredSynonyms().
2149 private ZoologicalName
getZoologicalName(UUID uuid
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
2150 ZoologicalName taxonName
=nameDao
.findZoologicalNameByUUID(uuid
);
2151 if (taxonName
== null) {
2152 taxonName
= zooHashMap
.get(uuid
);
2158 * Returns the idInSource for a given Synonym.
2161 private String
getIdInSource(TaxonBase taxonBase
) {
2162 String idInSource
= null;
2163 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
2164 if (sources
.size() == 1) {
2165 IdentifiableSource source
= sources
.iterator().next();
2166 if (source
!= null) {
2167 idInSource
= source
.getIdInSource();
2169 } else if (sources
.size() > 1) {
2172 for (IdentifiableSource source
: sources
) {
2173 idInSource
+= source
.getIdInSource();
2174 if (count
< sources
.size()) {
2179 } else if (sources
.size() == 0){
2180 logger
.warn("No idInSource for TaxonBase " + taxonBase
.getUuid() + " - " + taxonBase
.getTitleCache());
2189 * Returns the citation for a given Synonym.
2192 private Reference
getCitation(Synonym syn
) {
2193 Reference citation
= null;
2194 Set
<IdentifiableSource
> sources
= syn
.getSources();
2195 if (sources
.size() == 1) {
2196 IdentifiableSource source
= sources
.iterator().next();
2197 if (source
!= null) {
2198 citation
= source
.getCitation();
2200 } else if (sources
.size() > 1) {
2201 logger
.warn("This Synonym has more than one source: " + syn
.getUuid() + " (" + syn
.getTitleCache() +")");
2208 public List
<Synonym
> createAllInferredSynonyms(Taxon taxon
, Classification tree
, boolean doWithMisappliedNames
){
2209 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
2211 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_EPITHET_OF(), doWithMisappliedNames
));
2212 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_GENUS_OF(), doWithMisappliedNames
));
2213 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames
));
2215 return inferredSynonyms
;
2219 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)
2222 public List
<Classification
> listClassifications(TaxonBase taxonBase
, Integer limit
, Integer start
, List
<String
> propertyPaths
) {
2224 // TODO quickly implemented, create according dao !!!!
2225 Set
<TaxonNode
> nodes
= new HashSet
<TaxonNode
>();
2226 Set
<Classification
> classifications
= new HashSet
<Classification
>();
2227 List
<Classification
> list
= new ArrayList
<Classification
>();
2229 if (taxonBase
== null) {
2233 taxonBase
= load(taxonBase
.getUuid());
2235 if (taxonBase
instanceof Taxon
) {
2236 nodes
.addAll(((Taxon
)taxonBase
).getTaxonNodes());
2238 for (Taxon taxon
: ((Synonym
)taxonBase
).getAcceptedTaxa() ) {
2239 nodes
.addAll(taxon
.getTaxonNodes());
2242 for (TaxonNode node
: nodes
) {
2243 classifications
.add(node
.getClassification());
2245 list
.addAll(classifications
);