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
.DnaSample
;
78 import eu
.etaxonomy
.cdm
.model
.molecular
.Sequence
;
79 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
80 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
81 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
82 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
83 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnitBase
;
84 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
85 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
86 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
87 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
88 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
89 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
90 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
91 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
92 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
93 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
94 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
95 import eu
.etaxonomy
.cdm
.persistence
.dao
.AbstractBeanInitializer
;
96 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
97 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
98 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
99 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
100 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
101 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
102 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
103 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
104 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
.SortOrder
;
105 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
109 * @author a.kohlbecker
114 @Transactional(readOnly
= true)
115 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
116 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
118 public static final String POTENTIAL_COMBINATION_NAMESPACE
= "Potential combination";
120 public static final String INFERRED_EPITHET_NAMESPACE
= "Inferred epithet";
122 public static final String INFERRED_GENUS_NAMESPACE
= "Inferred genus";
126 private ITaxonNameDao nameDao
;
129 private INameService nameService
;
132 private ICdmGenericDao genericDao
;
135 private IDescriptionService descriptionService
;
138 private IOrderedTermVocabularyDao orderedVocabularyDao
;
141 private IOccurrenceDao occurrenceDao
;
144 private AbstractBeanInitializer beanInitializer
;
149 public TaxonServiceImpl(){
150 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
154 * FIXME Candidate for harmonization
155 * rename searchByName ?
158 public List
<TaxonBase
> searchTaxaByName(String name
, Reference sec
) {
159 return dao
.getTaxaByName(name
, sec
);
163 * FIXME Candidate for harmonization
164 * list(Synonym.class, ...)
166 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
169 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
170 return dao
.getAllSynonyms(limit
, start
);
174 * FIXME Candidate for harmonization
175 * list(Taxon.class, ...)
177 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
180 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
181 return dao
.getAllTaxa(limit
, start
);
185 * FIXME Candidate for harmonization
186 * merge with getRootTaxa(Reference sec, ..., ...)
188 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)
191 public List
<Taxon
> getRootTaxa(Reference sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
192 if (cdmFetch
== null){
193 cdmFetch
= CdmFetch
.NO_FETCH();
195 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
200 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
203 public List
<Taxon
> getRootTaxa(Rank rank
, Reference sec
, boolean onlyWithChildren
,boolean withMisapplications
, List
<String
> propertyPaths
) {
204 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
208 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)
211 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
212 return dao
.getAllRelationships(limit
, start
);
216 * FIXME Candidate for harmonization
217 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
221 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
223 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
224 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
225 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
226 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
227 return taxonRelTypeVocabulary
;
234 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
237 @Transactional(readOnly
= false)
238 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
240 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
241 synonymName
.removeTaxonBase(synonym
);
242 TaxonNameBase
<?
,?
> taxonName
= acceptedTaxon
.getName();
243 taxonName
.removeTaxonBase(acceptedTaxon
);
245 synonym
.setName(taxonName
);
246 acceptedTaxon
.setName(synonymName
);
248 // the accepted taxon needs a new uuid because the concept has changed
249 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
250 //acceptedTaxon.setUuid(UUID.randomUUID());
255 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
257 //TODO correct delete handling still needs to be implemented / checked
259 @Transactional(readOnly
= false)
260 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
, boolean deleteSynonym
, boolean copyCitationInfo
, Reference citation
, String microCitation
) throws HomotypicalGroupChangeException
{
262 TaxonNameBase
<?
,?
> acceptedName
= acceptedTaxon
.getName();
263 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
264 HomotypicalGroup synonymHomotypicGroup
= synonymName
.getHomotypicalGroup();
266 //check synonym is not homotypic
267 if (acceptedName
.getHomotypicalGroup().equals(synonymHomotypicGroup
)){
268 String message
= "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";
269 throw new HomotypicalGroupChangeException(message
);
272 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonymName
, acceptedTaxon
.getSec());
274 SynonymRelationshipType relTypeForGroup
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
275 List
<Synonym
> heteroSynonyms
= acceptedTaxon
.getSynonymsInGroup(synonymHomotypicGroup
);
277 for (Synonym heteroSynonym
: heteroSynonyms
){
278 if (synonym
.equals(heteroSynonym
)){
279 acceptedTaxon
.removeSynonym(heteroSynonym
, false);
281 //move synonyms in same homotypic group to new accepted taxon
282 heteroSynonym
.replaceAcceptedTaxon(newAcceptedTaxon
, relTypeForGroup
, copyCitationInfo
, citation
, microCitation
);
286 //synonym.getName().removeTaxonBase(synonym);
287 //TODO correct delete handling still needs to be implemented / checked
289 // deleteSynonym(synonym, taxon, false);
292 this.delete(synonym
);
294 } catch (Exception e
) {
295 logger
.info("Can't delete old synonym from database");
299 return newAcceptedTaxon
;
304 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, Reference citation
, String microcitation
){
306 // Get name from synonym
307 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
309 // remove synonym from taxon
310 toTaxon
.removeSynonym(synonym
);
312 // Create a taxon with synonym name
313 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
315 // Add taxon relation
316 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
318 // since we are swapping names, we have to detach the name from the synonym completely.
319 // Otherwise the synonym will still be in the list of typified names.
320 synonym
.getName().removeTaxonBase(synonym
);
327 * @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)
329 @Transactional(readOnly
= false)
331 public void changeHomotypicalGroupOfSynonym(Synonym synonym
, HomotypicalGroup newHomotypicalGroup
, Taxon targetTaxon
,
332 boolean removeFromOtherTaxa
, boolean setBasionymRelationIfApplicable
){
334 TaxonNameBase synonymName
= synonym
.getName();
335 HomotypicalGroup oldHomotypicalGroup
= synonymName
.getHomotypicalGroup();
339 oldHomotypicalGroup
.removeTypifiedName(synonymName
);
340 newHomotypicalGroup
.addTypifiedName(synonymName
);
342 //remove existing basionym relationships
343 synonymName
.removeBasionyms();
345 //add basionym relationship
346 if (setBasionymRelationIfApplicable
){
347 Set
<TaxonNameBase
> basionyms
= newHomotypicalGroup
.getBasionyms();
348 for (TaxonNameBase basionym
: basionyms
){
349 synonymName
.addBasionym(basionym
);
353 //set synonym relationship correctly
354 // SynonymRelationship relToTaxon = null;
355 boolean relToTargetTaxonExists
= false;
356 Set
<SynonymRelationship
> existingRelations
= synonym
.getSynonymRelations();
357 for (SynonymRelationship rel
: existingRelations
){
358 Taxon acceptedTaxon
= rel
.getAcceptedTaxon();
359 boolean isTargetTaxon
= acceptedTaxon
!= null && acceptedTaxon
.equals(targetTaxon
);
360 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
361 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
362 SynonymRelationshipType newRelationType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
363 rel
.setType(newRelationType
);
364 //TODO handle citation and microCitation
367 relToTargetTaxonExists
= true;
369 if (removeFromOtherTaxa
){
370 acceptedTaxon
.removeSynonym(synonym
, false);
376 if (targetTaxon
!= null && ! relToTargetTaxonExists
){
377 Taxon acceptedTaxon
= targetTaxon
;
378 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
379 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
380 SynonymRelationshipType relType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
381 //TODO handle citation and microCitation
382 Reference citation
= null;
383 String microCitation
= null;
384 acceptedTaxon
.addSynonym(synonym
, relType
, citation
, microCitation
);
391 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
394 @Transactional(readOnly
= false)
395 public void updateTitleCache(Class
<?
extends TaxonBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<TaxonBase
> cacheStrategy
, IProgressMonitor monitor
) {
397 clazz
= TaxonBase
.class;
399 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
404 protected void setDao(ITaxonDao dao
) {
409 * @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)
412 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
413 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
415 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
416 if(numberOfResults
> 0) { // no point checking again
417 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
420 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
424 * @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)
427 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
428 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
430 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
431 if(numberOfResults
> 0) { // no point checking again
432 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
439 * @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)
442 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
443 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
445 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
446 if(numberOfResults
> 0) { // no point checking again
447 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
453 * @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)
456 public Pager
<TaxonRelationship
> pageToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
457 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
459 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
460 if(numberOfResults
> 0) { // no point checking again
461 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
463 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
467 * @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)
470 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
471 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
473 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
474 if(numberOfResults
> 0) { // no point checking again
475 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
481 * @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)
484 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
485 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
487 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
488 if(numberOfResults
> 0) { // no point checking again
489 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
491 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
496 * @param includeRelationships
500 * @param propertyPaths
501 * @return an List which is not specifically ordered
504 public Set
<Taxon
> listRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Integer maxDepth
,
505 Integer limit
, Integer start
, List
<String
> propertyPaths
) {
507 Set
<Taxon
> relatedTaxa
= collectRelatedTaxa(taxon
, includeRelationships
, new HashSet
<Taxon
>(), maxDepth
);
508 relatedTaxa
.remove(taxon
);
509 beanInitializer
.initializeAll(relatedTaxa
, propertyPaths
);
515 * recursively collect related taxa for the given <code>taxon</code> . The returned list will also include the
516 * <code>taxon</code> supplied as parameter.
519 * @param includeRelationships
521 * @param maxDepth can be <code>null</code> for infinite depth
524 private Set
<Taxon
> collectRelatedTaxa(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, Set
<Taxon
> taxa
, Integer maxDepth
) {
530 if(maxDepth
!= null) {
533 if(logger
.isDebugEnabled()){
534 logger
.debug("collecting related taxa for " + taxon
+ " with maxDepth=" + maxDepth
);
536 List
<TaxonRelationship
> taxonRelationships
= dao
.getTaxonRelationships(taxon
, null, null, null, null, null, null);
537 for (TaxonRelationship taxRel
: taxonRelationships
) {
540 if (taxRel
.getToTaxon() == null || taxRel
.getFromTaxon() == null || taxRel
.getType() == null) {
543 // filter by includeRelationships
544 for (TaxonRelationshipEdge relationshipEdgeFilter
: includeRelationships
) {
545 if ( relationshipEdgeFilter
.getTaxonRelationshipType().equals(taxRel
.getType()) ) {
546 if (relationshipEdgeFilter
.getDirections().contains(Direction
.relatedTo
) && !taxa
.contains(taxRel
.getToTaxon())) {
547 if(logger
.isDebugEnabled()){
548 logger
.debug(maxDepth
+ ": " + taxon
.getTitleCache() + " --[" + taxRel
.getType().getLabel() + "]--> " + taxRel
.getToTaxon().getTitleCache());
550 taxa
.add(taxRel
.getToTaxon());
551 if(maxDepth
== null || maxDepth
> 0) {
552 taxa
.addAll(collectRelatedTaxa(taxRel
.getToTaxon(), includeRelationships
, taxa
, maxDepth
));
555 if(relationshipEdgeFilter
.getDirections().contains(Direction
.relatedFrom
) && !taxa
.contains(taxRel
.getFromTaxon())) {
556 taxa
.add(taxRel
.getFromTaxon());
557 if(logger
.isDebugEnabled()){
558 logger
.debug(maxDepth
+ ": " +taxRel
.getFromTaxon().getTitleCache() + " --[" + taxRel
.getType().getLabel() + "]--> " + taxon
.getTitleCache() );
560 if(maxDepth
== null || maxDepth
> 0) {
561 taxa
.addAll(collectRelatedTaxa(taxRel
.getFromTaxon(), includeRelationships
, taxa
, maxDepth
));
571 * @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)
574 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
575 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
577 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
578 if(numberOfResults
> 0) { // no point checking again
579 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
582 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
586 * @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)
589 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
590 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
592 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
593 if(numberOfResults
> 0) { // no point checking again
594 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
597 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
601 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
604 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
605 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
606 return t
.getHomotypicSynonymsByHomotypicGroup();
610 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
613 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
614 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
615 List
<HomotypicalGroup
> homotypicalGroups
= t
.getHeterotypicSynonymyGroups();
616 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(homotypicalGroups
.size());
617 for(HomotypicalGroup homotypicalGroup
: homotypicalGroups
){
618 heterotypicSynonymyGroups
.add(t
.getSynonymsInGroup(homotypicalGroup
));
620 return heterotypicSynonymyGroups
;
624 public List
<UuidAndTitleCache
<TaxonBase
>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator
){
626 List
<UuidAndTitleCache
<TaxonBase
>> result
= new ArrayList
<UuidAndTitleCache
<TaxonBase
>>();
627 // Class<? extends TaxonBase> clazz = null;
628 // if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
629 // clazz = TaxonBase.class;
630 // //propertyPath.addAll(configurator.getTaxonPropertyPath());
631 // //propertyPath.addAll(configurator.getSynonymPropertyPath());
632 // } else if(configurator.isDoTaxa()) {
633 // clazz = Taxon.class;
634 // //propertyPath = configurator.getTaxonPropertyPath();
635 // } else if (configurator.isDoSynonyms()) {
636 // clazz = Synonym.class;
637 // //propertyPath = configurator.getSynonymPropertyPath();
641 result
= dao
.getTaxaByNameForEditor(configurator
.isDoTaxa(), configurator
.isDoSynonyms(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
646 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
649 public Pager
<IdentifiableEntity
> findTaxaAndNames(IFindTaxaAndNamesConfigurator configurator
) {
651 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
652 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
653 List
<TaxonBase
> taxa
= null;
656 long numberTaxaResults
= 0L;
659 List
<String
> propertyPath
= new ArrayList
<String
>();
660 if(configurator
.getTaxonPropertyPath() != null){
661 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
665 if (configurator
.isDoMisappliedNames() || configurator
.isDoSynonyms() || configurator
.isDoTaxa()){
666 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
668 dao
.countTaxaByName(configurator
.isDoTaxa(),configurator
.isDoSynonyms(), configurator
.isDoMisappliedNames(),
669 configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(),
670 configurator
.getNamedAreas());
673 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
674 taxa
= dao
.getTaxaByName(configurator
.isDoTaxa(), configurator
.isDoSynonyms(),
675 configurator
.isDoMisappliedNames(), configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(),
676 configurator
.getMatchMode(), configurator
.getNamedAreas(),
677 configurator
.getPageSize(), configurator
.getPageNumber(), propertyPath
);
681 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
684 results
.addAll(taxa
);
687 numberOfResults
+= numberTaxaResults
;
689 // Names without taxa
690 if (configurator
.isDoNamesWithoutTaxa()) {
691 int numberNameResults
= 0;
693 List
<?
extends TaxonNameBase
<?
,?
>> names
=
694 nameDao
.findByName(configurator
.getTitleSearchStringSqlized(), configurator
.getMatchMode(),
695 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
696 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
697 if (names
.size() > 0) {
698 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
699 if (taxonName
.getTaxonBases().size() == 0) {
700 results
.add(taxonName
);
704 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
705 numberOfResults
+= numberNameResults
;
709 // Taxa from common names
711 if (configurator
.isDoTaxaByCommonNames()) {
712 taxa
= new ArrayList
<TaxonBase
>();
713 numberTaxaResults
= 0;
714 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
715 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
717 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
718 List
<Object
[]> commonNameResults
= dao
.getTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
719 for( Object
[] entry
: commonNameResults
) {
720 taxa
.add((TaxonBase
) entry
[0]);
724 results
.addAll(taxa
);
726 numberOfResults
+= numberTaxaResults
;
730 return new DefaultPagerImpl
<IdentifiableEntity
>
731 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
734 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
735 return dao
.getUuidAndTitleCache();
739 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])
742 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
743 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
744 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
745 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
746 for (TaxonDescription taxDesc
: descriptions
){
747 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
748 for (DescriptionElementBase descElem
: elements
){
749 for(Media media
: descElem
.getMedia()){
751 //find the best matching representation
752 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, null, size
, height
, widthOrDuration
, mimeTypes
));
761 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxonDescriptionMedia(eu.etaxonomy.cdm.model.taxon.Taxon, boolean)
764 public List
<Media
> listTaxonDescriptionMedia(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
, boolean limitToGalleries
, List
<String
> propertyPath
){
765 return listMedia(taxon
, includeRelationships
, limitToGalleries
, true, false, false, propertyPath
);
770 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listMedia(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, boolean, java.util.List)
773 public List
<Media
> listMedia(Taxon taxon
, Set
<TaxonRelationshipEdge
> includeRelationships
,
774 Boolean limitToGalleries
, Boolean includeTaxonDescriptions
, Boolean includeOccurrences
,
775 Boolean includeTaxonNameDescriptions
, List
<String
> propertyPath
) {
777 Set
<Taxon
> taxa
= new HashSet
<Taxon
>();
778 List
<Media
> taxonMedia
= new ArrayList
<Media
>();
780 if (limitToGalleries
== null) {
781 limitToGalleries
= false;
784 // --- resolve related taxa
785 if (includeRelationships
!= null) {
786 taxa
= listRelatedTaxa(taxon
, includeRelationships
, null, null, null, null);
789 taxa
.add((Taxon
) dao
.load(taxon
.getUuid()));
791 if(includeTaxonDescriptions
!= null && includeTaxonDescriptions
){
792 List
<TaxonDescription
> taxonDescriptions
= new ArrayList
<TaxonDescription
>();
793 // --- TaxonDescriptions
794 for (Taxon t
: taxa
) {
795 taxonDescriptions
.addAll(descriptionService
.listTaxonDescriptions(t
, null, null, null, null, propertyPath
));
797 for (TaxonDescription taxonDescription
: taxonDescriptions
) {
798 if (!limitToGalleries
|| taxonDescription
.isImageGallery()) {
799 for (DescriptionElementBase element
: taxonDescription
.getElements()) {
800 for (Media media
: element
.getMedia()) {
801 taxonMedia
.add(media
);
808 if(includeOccurrences
!= null && includeOccurrences
) {
809 Set
<SpecimenOrObservationBase
> specimensOrObservations
= new HashSet
<SpecimenOrObservationBase
>();
811 for (Taxon t
: taxa
) {
812 specimensOrObservations
.addAll(occurrenceDao
.listByAssociatedTaxon(null, t
, null, null, null, null));
814 for (SpecimenOrObservationBase occurrence
: specimensOrObservations
) {
816 taxonMedia
.addAll(occurrence
.getMedia());
818 // SpecimenDescriptions
819 Set
<SpecimenDescription
> specimenDescriptions
= occurrence
.getSpecimenDescriptions();
820 for (DescriptionBase specimenDescription
: specimenDescriptions
) {
821 if (!limitToGalleries
|| specimenDescription
.isImageGallery()) {
822 Set
<DescriptionElementBase
> elements
= specimenDescription
.getElements();
823 for (DescriptionElementBase element
: elements
) {
824 for (Media media
: element
.getMedia()) {
825 taxonMedia
.add(media
);
832 if (occurrence
instanceof DerivedUnitBase
) {
833 if (((DerivedUnitBase
) occurrence
).getCollection() != null){
834 taxonMedia
.addAll(((DerivedUnitBase
) occurrence
).getCollection().getMedia());
839 if (occurrence
instanceof DnaSample
) {
840 Set
<Sequence
> sequences
= ((DnaSample
) occurrence
).getSequences();
841 for (Sequence sequence
: sequences
) {
842 taxonMedia
.addAll(sequence
.getChromatograms());
849 if(includeTaxonNameDescriptions
!= null && includeTaxonNameDescriptions
) {
850 // --- TaxonNameDescription
851 Set
<TaxonNameDescription
> nameDescriptions
= new HashSet
<TaxonNameDescription
>();
852 for (Taxon t
: taxa
) {
853 nameDescriptions
.addAll(t
.getName().getDescriptions());
855 for(TaxonNameDescription nameDescription
: nameDescriptions
){
856 if (!limitToGalleries
|| nameDescription
.isImageGallery()) {
857 Set
<DescriptionElementBase
> elements
= nameDescription
.getElements();
858 for (DescriptionElementBase element
: elements
) {
859 for (Media media
: element
.getMedia()) {
860 taxonMedia
.add(media
);
867 beanInitializer
.initializeAll(taxonMedia
, propertyPath
);
872 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)
875 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
876 return this.dao
.listByIds(listOfIDs
, null, null, null, null);
880 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)
883 public TaxonBase
findTaxonByUuid(UUID uuid
, List
<String
> propertyPaths
){
884 return this.dao
.findByUuid(uuid
, null ,propertyPaths
);
888 * @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()
891 public int countAllRelationships() {
892 return this.dao
.countAllRelationships();
899 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)
902 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
903 return this.dao
.findIdenticalTaxonNames(propertyPath
);
908 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)
911 public void deleteTaxon(Taxon taxon
, TaxonDeletionConfigurator config
) throws ReferencedObjectUndeletableException
{
913 config
= new TaxonDeletionConfigurator();
917 if (! config
.isDeleteTaxonNodes()){
918 if (taxon
.getTaxonNodes().size() > 0){
919 String message
= "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";
920 throw new ReferencedObjectUndeletableException(message
);
925 // SynonymRelationShip
926 if (config
.isDeleteSynonymRelations()){
927 boolean removeSynonymNameFromHomotypicalGroup
= false;
928 for (SynonymRelationship synRel
: taxon
.getSynonymRelations()){
929 Synonym synonym
= synRel
.getSynonym();
930 taxon
.removeSynonymRelation(synRel
, removeSynonymNameFromHomotypicalGroup
);
931 if (config
.isDeleteSynonymsIfPossible()){
933 boolean newHomotypicGroupIfNeeded
= true;
934 deleteSynonym(synonym
, taxon
, config
.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded
);
936 deleteSynonymRelationships(synonym
, taxon
);
942 if (! config
.isDeleteTaxonRelationships()){
943 if (taxon
.getTaxonRelations().size() > 0){
944 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.";
945 throw new ReferencedObjectUndeletableException(message
);
951 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
953 for (TaxonDescription desc
: descriptions
){
954 if (config
.isDeleteDescriptions()){
955 //TODO use description delete configurator ?
956 //FIXME check if description is ALWAYS deletable
957 descriptionService
.delete(desc
);
959 if (desc
.getDescribedSpecimenOrObservations().size()>0){
960 String message
= "Taxon can't be deleted as it is used in a TaxonDescription" +
961 " which also describes specimens or abservations";
962 throw new ReferencedObjectUndeletableException(message
);
968 //check references with only reverse mapping
969 Set
<CdmBase
> referencingObjects
= genericDao
.getReferencingObjects(taxon
);
970 for (CdmBase referencingObject
: referencingObjects
){
971 //IIdentificationKeys (Media, Polytomous, MultiAccess)
972 if (HibernateProxyHelper
.isInstanceOf(referencingObject
, IIdentificationKey
.class)){
973 String message
= "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";
974 message
= String
.format(message
, CdmBase
.deproxy(referencingObject
, DerivedUnitBase
.class).getTitleCache());
975 throw new ReferencedObjectUndeletableException(message
);
980 if (referencingObject
.isInstanceOf(PolytomousKeyNode
.class)){
981 String message
= "Taxon can't be deleted as it is used in polytomous key node";
982 throw new ReferencedObjectUndeletableException(message
);
986 if (referencingObject
.isInstanceOf(TaxonInteraction
.class)){
987 String message
= "Taxon can't be deleted as it is used in taxonInteraction#taxon2";
988 throw new ReferencedObjectUndeletableException(message
);
994 if (config
.isDeleteNameIfPossible()){
996 nameService
.delete(taxon
.getName(), config
.getNameDeletionConfig());
997 } catch (ReferencedObjectUndeletableException e
) {
999 if (logger
.isDebugEnabled()){logger
.debug("Name could not be deleted");}
1006 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)
1008 @Transactional(readOnly
= false)
1010 public void deleteSynonym(Synonym synonym
, Taxon taxon
, boolean removeNameIfPossible
,boolean newHomotypicGroupIfNeeded
) {
1011 if (synonym
== null){
1014 synonym
= CdmBase
.deproxy(dao
.merge(synonym
), Synonym
.class);
1016 //remove synonymRelationship
1017 Set
<Taxon
> taxonSet
= new HashSet
<Taxon
>();
1019 taxonSet
.add(taxon
);
1021 taxonSet
.addAll(synonym
.getAcceptedTaxa());
1023 for (Taxon relatedTaxon
: taxonSet
){
1024 // dao.deleteSynonymRelationships(synonym, relatedTaxon);
1025 relatedTaxon
.removeSynonym(synonym
, newHomotypicGroupIfNeeded
);
1027 this.saveOrUpdate(synonym
);
1029 //TODO remove name from homotypical group?
1031 //remove synonym (if necessary)
1032 if (synonym
.getSynonymRelations().isEmpty()){
1033 TaxonNameBase
<?
,?
> name
= synonym
.getName();
1034 synonym
.setName(null);
1035 dao
.delete(synonym
);
1037 //remove name if possible (and required)
1038 if (name
!= null && removeNameIfPossible
){
1040 nameService
.delete(name
, new NameDeletionConfigurator());
1041 }catch (DataChangeNoRollbackException ex
){
1042 if (logger
.isDebugEnabled()) {
1043 logger
.debug("Name wasn't deleted as it is referenced");
1052 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)
1055 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
1057 return this.dao
.findIdenticalNamesNew(propertyPath
);
1061 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
1064 public String
getPhylumName(TaxonNameBase name
){
1065 return this.dao
.getPhylumName(name
);
1069 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
1072 public long deleteSynonymRelationships(Synonym syn
, Taxon taxon
) {
1073 return dao
.deleteSynonymRelationships(syn
, taxon
);
1077 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)
1080 public long deleteSynonymRelationships(Synonym syn
) {
1081 return dao
.deleteSynonymRelationships(syn
, null);
1086 * @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)
1089 public List
<SynonymRelationship
> listSynonymRelationships(
1090 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
1091 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
1092 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
1094 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
1095 if(numberOfResults
> 0) { // no point checking again
1096 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
1102 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingTaxon(java.lang.String)
1105 public Taxon
findBestMatchingTaxon(String taxonName
) {
1106 MatchingTaxonConfigurator config
= MatchingTaxonConfigurator
.NewInstance();
1107 config
.setTaxonNameTitle(taxonName
);
1108 return findBestMatchingTaxon(config
);
1114 public Taxon
findBestMatchingTaxon(MatchingTaxonConfigurator config
) {
1116 Taxon bestCandidate
= null;
1118 // 1. search for acceptet taxa
1119 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(true, false, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
1120 boolean bestCandidateMatchesSecUuid
= false;
1121 boolean bestCandidateIsInClassification
= false;
1122 int countEqualCandidates
= 0;
1123 for(TaxonBase taxonBaseCandidate
: taxonList
){
1124 if(taxonBaseCandidate
instanceof Taxon
){
1125 Taxon newCanditate
= CdmBase
.deproxy(taxonBaseCandidate
, Taxon
.class);
1126 boolean newCandidateMatchesSecUuid
= isMatchesSecUuid(newCanditate
, config
);
1127 if (! newCandidateMatchesSecUuid
&& config
.isOnlyMatchingSecUuid() ){
1129 }else if(newCandidateMatchesSecUuid
&& ! bestCandidateMatchesSecUuid
){
1130 bestCandidate
= newCanditate
;
1131 countEqualCandidates
= 1;
1132 bestCandidateMatchesSecUuid
= true;
1136 boolean newCandidateInClassification
= isInClassification(newCanditate
, config
);
1137 if (! newCandidateInClassification
&& config
.isOnlyMatchingClassificationUuid()){
1139 }else if (newCandidateInClassification
&& ! bestCandidateIsInClassification
){
1140 bestCandidate
= newCanditate
;
1141 countEqualCandidates
= 1;
1142 bestCandidateIsInClassification
= true;
1145 if (bestCandidate
== null){
1146 bestCandidate
= newCanditate
;
1147 countEqualCandidates
= 1;
1151 }else{ //not Taxon.class
1154 countEqualCandidates
++;
1157 if (bestCandidate
!= null){
1158 if(countEqualCandidates
> 1){
1159 logger
.info(countEqualCandidates
+ " equally matching TaxonBases found, using first accepted Taxon: " + bestCandidate
.getTitleCache());
1160 return bestCandidate
;
1162 logger
.info("using accepted Taxon: " + bestCandidate
.getTitleCache());
1163 return bestCandidate
;
1168 // 2. search for synonyms
1169 if (config
.isIncludeSynonyms()){
1170 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
1171 for(TaxonBase taxonBase
: synonymList
){
1172 if(taxonBase
instanceof Synonym
){
1173 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
1174 Set
<Taxon
> acceptetdCandidates
= synonym
.getAcceptedTaxa();
1175 if(!acceptetdCandidates
.isEmpty()){
1176 bestCandidate
= acceptetdCandidates
.iterator().next();
1177 if(acceptetdCandidates
.size() == 1){
1178 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + bestCandidate
.getTitleCache());
1179 return bestCandidate
;
1181 logger
.info("using accepted Taxon " + bestCandidate
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
1182 return bestCandidate
;
1184 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
1190 } catch (Exception e
){
1194 return bestCandidate
;
1197 private boolean isInClassification(Taxon taxon
, MatchingTaxonConfigurator config
) {
1198 UUID configClassificationUuid
= config
.getClassificationUuid();
1199 if (configClassificationUuid
== null){
1202 for (TaxonNode node
: taxon
.getTaxonNodes()){
1203 UUID classUuid
= node
.getClassification().getUuid();
1204 if (configClassificationUuid
.equals(classUuid
)){
1211 private boolean isMatchesSecUuid(Taxon taxon
, MatchingTaxonConfigurator config
) {
1212 UUID configSecUuid
= config
.getSecUuid();
1213 if (configSecUuid
== null){
1216 UUID taxonSecUuid
= (taxon
.getSec() == null)?
null : taxon
.getSec().getUuid();
1217 return configSecUuid
.equals(taxonSecUuid
);
1221 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
1224 public Synonym
findBestMatchingSynonym(String taxonName
) {
1225 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
1226 if(! synonymList
.isEmpty()){
1227 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
1228 if(synonymList
.size() == 1){
1229 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
1232 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());
1241 * @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)
1244 public SynonymRelationship
moveSynonymToAnotherTaxon(SynonymRelationship oldSynonymRelation
, Taxon newTaxon
, boolean moveHomotypicGroup
,
1245 SynonymRelationshipType newSynonymRelationshipType
, Reference reference
, String referenceDetail
, boolean keepReference
) throws HomotypicalGroupChangeException
{
1247 Synonym synonym
= oldSynonymRelation
.getSynonym();
1248 Taxon fromTaxon
= oldSynonymRelation
.getAcceptedTaxon();
1249 //TODO what if there is no name ?? Concepts may be cached (e.g. via TCS import)
1250 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
1251 TaxonNameBase
<?
,?
> fromTaxonName
= fromTaxon
.getName();
1252 //set default relationship type
1253 if (newSynonymRelationshipType
== null){
1254 newSynonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
1256 boolean newRelTypeIsHomotypic
= newSynonymRelationshipType
.equals(SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF());
1258 HomotypicalGroup homotypicGroup
= synonymName
.getHomotypicalGroup();
1259 int hgSize
= homotypicGroup
.getTypifiedNames().size();
1260 boolean isSingleInGroup
= !(hgSize
> 1);
1262 if (! isSingleInGroup
){
1263 boolean isHomotypicToAccepted
= synonymName
.isHomotypic(fromTaxonName
);
1264 boolean hasHomotypicSynonymRelatives
= isHomotypicToAccepted ? hgSize
> 2 : hgSize
> 1;
1265 if (isHomotypicToAccepted
){
1266 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.";
1267 String homotypicRelatives
= hasHomotypicSynonymRelatives ?
" and other synonym(s)":"";
1268 message
= String
.format(message
, homotypicRelatives
);
1269 throw new HomotypicalGroupChangeException(message
);
1271 if (! moveHomotypicGroup
){
1272 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.";
1273 throw new HomotypicalGroupChangeException(message
);
1276 moveHomotypicGroup
= true; //single synonym always allows to moveCompleteGroup
1278 // Assert.assertTrue("Synonym can only be moved with complete homotypic group", moveHomotypicGroup);
1280 SynonymRelationship result
= null;
1281 //move all synonyms to new taxon
1282 List
<Synonym
> homotypicSynonyms
= fromTaxon
.getSynonymsInGroup(homotypicGroup
);
1283 for (Synonym syn
: homotypicSynonyms
){
1284 Set
<SynonymRelationship
> synRelations
= syn
.getSynonymRelations();
1285 for (SynonymRelationship synRelation
: synRelations
){
1286 if (fromTaxon
.equals(synRelation
.getAcceptedTaxon())){
1287 Reference
<?
> newReference
= reference
;
1288 if (newReference
== null && keepReference
){
1289 newReference
= synRelation
.getCitation();
1291 String newRefDetail
= referenceDetail
;
1292 if (newRefDetail
== null && keepReference
){
1293 newRefDetail
= synRelation
.getCitationMicroReference();
1295 SynonymRelationship newSynRelation
= newTaxon
.addSynonym(syn
, newSynonymRelationshipType
, newReference
, newRefDetail
);
1296 fromTaxon
.removeSynonymRelation(synRelation
, false);
1298 //change homotypic group of synonym if relType is 'homotypic'
1299 // if (newRelTypeIsHomotypic){
1300 // newTaxon.getName().getHomotypicalGroup().addTypifiedName(syn.getName());
1303 if (synRelation
.equals(oldSynonymRelation
)){
1304 result
= newSynRelation
;
1310 saveOrUpdate(newTaxon
);
1311 //Assert that there is a result
1312 if (result
== null){
1313 String message
= "Old synonym relation could not be transformed into new relation. This should not happen.";
1314 throw new IllegalStateException(message
);
1320 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
1323 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheTaxon() {
1324 return dao
.getUuidAndTitleCacheTaxon();
1328 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
1331 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheSynonym() {
1332 return dao
.getUuidAndTitleCacheSynonym();
1336 * @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)
1339 public Pager
<SearchResult
<TaxonBase
>> findByFullText(
1340 Class
<?
extends TaxonBase
> clazz
, String queryString
,
1341 Classification classification
, List
<Language
> languages
,
1342 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1345 LuceneSearch luceneSearch
= prepareFindByFullTextSearch(clazz
, queryString
, classification
, languages
, highlightFragments
);
1347 // --- execute search
1348 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1350 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1351 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1353 // --- initialize taxa, thighlight matches ....
1354 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1355 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1356 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1358 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1359 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1364 * @param queryString
1365 * @param classification
1367 * @param highlightFragments
1368 * @param directorySelectClass
1371 protected LuceneSearch
prepareFindByFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Language
> languages
,
1372 boolean highlightFragments
) {
1373 BooleanQuery finalQuery
= new BooleanQuery();
1374 BooleanQuery textQuery
= new BooleanQuery();
1376 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), TaxonBase
.class);
1377 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1379 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("titleCache__sort", SortField
.STRING
, false)};
1380 luceneSearch
.setSortFields(sortFields
);
1382 // ---- search criteria
1383 luceneSearch
.setClazz(clazz
);
1385 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1386 textQuery
.add(queryFactory
.newDefinedTermQuery("name.rank", queryString
, languages
), Occur
.SHOULD
);
1388 finalQuery
.add(textQuery
, Occur
.MUST
);
1390 if(classification
!= null){
1391 finalQuery
.add(queryFactory
.newEntityIdQuery("taxonNodes.classification.id", classification
), Occur
.MUST
);
1393 luceneSearch
.setQuery(finalQuery
);
1395 if(highlightFragments
){
1396 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1398 return luceneSearch
;
1403 * @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)
1406 public Pager
<SearchResult
<TaxonBase
>> findByDescriptionElementFullText(
1407 Class
<?
extends DescriptionElementBase
> clazz
, String queryString
,
1408 Classification classification
, List
<Feature
> features
, List
<Language
> languages
,
1409 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1412 LuceneSearch luceneSearch
= prepareByDescriptionElementFullTextSearch(clazz
, queryString
, classification
, features
, languages
, highlightFragments
);
1414 // --- execute search
1415 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1417 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1418 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1420 // --- initialize taxa, highlight matches ....
1421 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1422 @SuppressWarnings("rawtypes")
1423 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1424 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1426 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupCount
: 0;
1427 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1433 public Pager
<SearchResult
<TaxonBase
>> findByEverythingFullText(String queryString
,
1434 Classification classification
, List
<Language
> languages
, boolean highlightFragments
,
1435 Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1437 LuceneSearch luceneSearchByDescriptionElement
= prepareByDescriptionElementFullTextSearch(null, queryString
, classification
, null, languages
, highlightFragments
);
1438 LuceneSearch luceneSearchByTaxonBase
= prepareFindByFullTextSearch(null, queryString
, classification
, languages
, highlightFragments
);
1440 LuceneMultiSearch multiSearch
= new LuceneMultiSearch(luceneSearchByDescriptionElement
, luceneSearchByTaxonBase
);
1442 // --- execute search
1443 TopGroupsWithMaxScore topDocsResultSet
= multiSearch
.executeSearch(pageSize
, pageNumber
);
1445 // --- initialize taxa, highlight matches ....
1446 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(multiSearch
, multiSearch
.getQuery());
1448 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1449 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1450 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1452 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1453 topDocsResultSet
, multiSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1455 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1456 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1463 * @param queryString
1464 * @param classification
1467 * @param highlightFragments
1468 * @param directorySelectClass
1471 protected LuceneSearch
prepareByDescriptionElementFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Feature
> features
,
1472 List
<Language
> languages
, boolean highlightFragments
) {
1473 BooleanQuery finalQuery
= new BooleanQuery();
1474 BooleanQuery textQuery
= new BooleanQuery();
1476 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), GroupByTaxonClassBridge
.GROUPBY_TAXON_FIELD
, DescriptionElementBase
.class);
1477 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1479 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("inDescription.taxon.titleCache__sort", SortField
.STRING
, false)};
1480 luceneSearch
.setSortFields(sortFields
);
1482 // ---- search criteria
1483 luceneSearch
.setClazz(clazz
);
1484 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1488 if(languages
== null || languages
.size() == 0){
1489 nameQuery
= queryFactory
.newTermQuery("name", queryString
);
1491 nameQuery
= new BooleanQuery();
1492 BooleanQuery languageSubQuery
= new BooleanQuery();
1493 for(Language lang
: languages
){
1494 languageSubQuery
.add(queryFactory
.newTermQuery("language.uuid", lang
.getUuid().toString(), false), Occur
.SHOULD
);
1496 ((BooleanQuery
) nameQuery
).add(queryFactory
.newTermQuery("name", queryString
), Occur
.MUST
);
1497 ((BooleanQuery
) nameQuery
).add(languageSubQuery
, Occur
.MUST
);
1499 textQuery
.add(nameQuery
, Occur
.SHOULD
);
1502 // text field from TextData
1503 textQuery
.add(queryFactory
.newMultilanguageTextQuery("text", queryString
, languages
), Occur
.SHOULD
);
1505 // --- TermBase fields - by representation ----
1506 // state field from CategoricalData
1507 textQuery
.add(queryFactory
.newDefinedTermQuery("states.state", queryString
, languages
), Occur
.SHOULD
);
1509 // state field from CategoricalData
1510 textQuery
.add(queryFactory
.newDefinedTermQuery("states.modifyingText", queryString
, languages
), Occur
.SHOULD
);
1512 // area field from Distribution
1513 textQuery
.add(queryFactory
.newDefinedTermQuery("area", queryString
, languages
), Occur
.SHOULD
);
1515 // status field from Distribution
1516 textQuery
.add(queryFactory
.newDefinedTermQuery("status", queryString
, languages
), Occur
.SHOULD
);
1518 finalQuery
.add(textQuery
, Occur
.MUST
);
1519 // --- classification ----
1521 if(classification
!= null){
1522 finalQuery
.add(queryFactory
.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification
), Occur
.MUST
);
1525 // --- IdentifieableEntity fields - by uuid
1526 if(features
!= null && features
.size() > 0 ){
1527 finalQuery
.add(queryFactory
.newEntityUuidQuery("feature.uuid", features
), Occur
.MUST
);
1530 // the description must be associated with a taxon
1531 finalQuery
.add(queryFactory
.newIsNotNullQuery("inDescription.taxon.id"), Occur
.MUST
);
1533 logger
.info("prepareByDescriptionElementFullTextSearch() query: " + finalQuery
.toString());
1534 luceneSearch
.setQuery(finalQuery
);
1536 if(highlightFragments
){
1537 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1539 return luceneSearch
;
1543 * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}
1544 * and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.
1545 * This method is a convenient means to retrieve a Lucene query string for such the fields.
1547 * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}
1548 * or {@link MultilanguageTextFieldBridge }
1549 * @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages
1550 * @param stringBuilder a StringBuilder to be reused, if <code>null</code> a new StringBuilder will be instantiated and is returned
1551 * @return the StringBuilder given a parameter or a new one if the stringBuilder parameter was null.
1553 * TODO move to utiliy class !!!!!!!!
1555 private StringBuilder
appendLocalizedFieldQuery(String name
, List
<Language
> languages
, StringBuilder stringBuilder
) {
1557 if(stringBuilder
== null){
1558 stringBuilder
= new StringBuilder();
1560 if(languages
== null || languages
.size() == 0){
1561 stringBuilder
.append(name
+ ".ALL:(%1$s) ");
1563 for(Language lang
: languages
){
1564 stringBuilder
.append(name
+ "." + lang
.getUuid().toString() + ":(%1$s) ");
1567 return stringBuilder
;
1571 public List
<Synonym
> createInferredSynonyms(Taxon taxon
, Classification classification
, SynonymRelationshipType type
, boolean doWithMisappliedNames
){
1572 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1573 List
<Synonym
> inferredSynonymsToBeRemoved
= new ArrayList
<Synonym
>();
1575 HashMap
<UUID
, ZoologicalName
> zooHashMap
= new HashMap
<UUID
, ZoologicalName
>();
1578 UUID nameUuid
= taxon
.getName().getUuid();
1579 ZoologicalName taxonName
= getZoologicalName(nameUuid
, zooHashMap
);
1580 String epithetOfTaxon
= null;
1581 String infragenericEpithetOfTaxon
= null;
1582 String infraspecificEpithetOfTaxon
= null;
1583 if (taxonName
.isSpecies()){
1584 epithetOfTaxon
= taxonName
.getSpecificEpithet();
1585 } else if (taxonName
.isInfraGeneric()){
1586 infragenericEpithetOfTaxon
= taxonName
.getInfraGenericEpithet();
1587 } else if (taxonName
.isInfraSpecific()){
1588 infraspecificEpithetOfTaxon
= taxonName
.getInfraSpecificEpithet();
1590 String genusOfTaxon
= taxonName
.getGenusOrUninomial();
1591 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1592 List
<String
> taxonNames
= new ArrayList
<String
>();
1594 for (TaxonNode node
: nodes
){
1595 // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName
1596 // List<String> synonymsEpithet = new ArrayList<String>();
1598 if (node
.getClassification().equals(classification
)){
1599 if (!node
.isTopmostNode()){
1600 TaxonNode parent
= node
.getParent();
1601 parent
= (TaxonNode
)HibernateProxyHelper
.deproxy(parent
);
1602 TaxonNameBase
<?
,?
> parentName
= parent
.getTaxon().getName();
1603 ZoologicalName zooParentName
= HibernateProxyHelper
.deproxy(parentName
, ZoologicalName
.class);
1604 Taxon parentTaxon
= (Taxon
)HibernateProxyHelper
.deproxy(parent
.getTaxon());
1605 Rank rankOfTaxon
= taxonName
.getRank();
1608 //create inferred synonyms for species, subspecies
1609 if ((parentName
.isGenus() || parentName
.isSpecies() || parentName
.getRank().equals(Rank
.SUBGENUS())) ){
1611 Synonym inferredEpithet
= null;
1612 Synonym inferredGenus
= null;
1613 Synonym potentialCombination
= null;
1615 List
<String
> propertyPaths
= new ArrayList
<String
>();
1616 propertyPaths
.add("synonym");
1617 propertyPaths
.add("synonym.name");
1618 List
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
1619 orderHints
.add(new OrderHint("relatedFrom.titleCache", SortOrder
.ASCENDING
));
1621 List
<SynonymRelationship
> synonymRelationshipsOfParent
= dao
.getSynonyms(parentTaxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1622 List
<SynonymRelationship
> synonymRelationshipsOfTaxon
= dao
.getSynonyms(taxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1624 List
<TaxonRelationship
> taxonRelListParent
= null;
1625 List
<TaxonRelationship
> taxonRelListTaxon
= null;
1626 if (doWithMisappliedNames
){
1627 taxonRelListParent
= dao
.getTaxonRelationships(parentTaxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1628 taxonRelListTaxon
= dao
.getTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1632 if (type
.equals(SynonymRelationshipType
.INFERRED_EPITHET_OF())){
1635 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1636 Synonym syn
= synonymRelationOfParent
.getSynonym();
1638 inferredEpithet
= createInferredEpithets(taxon
,
1639 zooHashMap
, taxonName
, epithetOfTaxon
,
1640 infragenericEpithetOfTaxon
,
1641 infraspecificEpithetOfTaxon
,
1642 taxonNames
, parentName
,
1646 inferredSynonyms
.add(inferredEpithet
);
1647 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1648 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1651 if (doWithMisappliedNames
){
1653 for (TaxonRelationship taxonRelationship
: taxonRelListParent
){
1654 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1656 inferredEpithet
= createInferredEpithets(taxon
,
1657 zooHashMap
, taxonName
, epithetOfTaxon
,
1658 infragenericEpithetOfTaxon
,
1659 infraspecificEpithetOfTaxon
,
1660 taxonNames
, parentName
,
1663 inferredSynonyms
.add(inferredEpithet
);
1664 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1665 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1669 if (!taxonNames
.isEmpty()){
1670 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1671 ZoologicalName name
;
1672 if (!synNotInCDM
.isEmpty()){
1673 inferredSynonymsToBeRemoved
.clear();
1675 for (Synonym syn
:inferredSynonyms
){
1676 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1677 if (!synNotInCDM
.contains(name
.getNameCache())){
1678 inferredSynonymsToBeRemoved
.add(syn
);
1682 // Remove identified Synonyms from inferredSynonyms
1683 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1684 inferredSynonyms
.remove(synonym
);
1689 }else if (type
.equals(SynonymRelationshipType
.INFERRED_GENUS_OF())){
1692 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1693 TaxonNameBase synName
;
1694 ZoologicalName inferredSynName
;
1696 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1697 inferredGenus
= createInferredGenus(taxon
,
1698 zooHashMap
, taxonName
, epithetOfTaxon
,
1699 genusOfTaxon
, taxonNames
, zooParentName
, syn
);
1701 inferredSynonyms
.add(inferredGenus
);
1702 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1703 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1708 if (doWithMisappliedNames
){
1710 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1711 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1712 inferredGenus
= createInferredGenus(taxon
, zooHashMap
, taxonName
, infraspecificEpithetOfTaxon
, genusOfTaxon
, taxonNames
, zooParentName
, misappliedName
);
1714 inferredSynonyms
.add(inferredGenus
);
1715 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1716 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1721 if (!taxonNames
.isEmpty()){
1722 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1723 ZoologicalName name
;
1724 if (!synNotInCDM
.isEmpty()){
1725 inferredSynonymsToBeRemoved
.clear();
1727 for (Synonym syn
:inferredSynonyms
){
1728 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1729 if (!synNotInCDM
.contains(name
.getNameCache())){
1730 inferredSynonymsToBeRemoved
.add(syn
);
1734 // Remove identified Synonyms from inferredSynonyms
1735 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1736 inferredSynonyms
.remove(synonym
);
1741 }else if (type
.equals(SynonymRelationshipType
.POTENTIAL_COMBINATION_OF())){
1743 Reference sourceReference
= null; // TODO: Determination of sourceReference is redundant
1744 ZoologicalName inferredSynName
;
1745 //for all synonyms of the parent...
1746 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1747 TaxonNameBase synName
;
1748 Synonym synParent
= synonymRelationOfParent
.getSynonym();
1749 synName
= synParent
.getName();
1751 HibernateProxyHelper
.deproxy(synParent
);
1753 // Set the sourceReference
1754 sourceReference
= synParent
.getSec();
1756 // Determine the idInSource
1757 String idInSourceParent
= getIdInSource(synParent
);
1759 ZoologicalName parentSynZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1760 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1761 String synParentInfragenericName
= null;
1762 String synParentSpecificEpithet
= null;
1764 if (parentSynZooName
.isInfraGeneric()){
1765 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1767 if (parentSynZooName
.isSpecies()){
1768 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1771 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1772 synonymsGenus.put(synGenusName, idInSource);
1775 //for all synonyms of the taxon
1777 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1779 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1780 ZoologicalName zooSynName
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1781 potentialCombination
= createPotentialCombination(idInSourceParent
, parentSynZooName
, zooSynName
,
1783 synParentInfragenericName
,
1784 synParentSpecificEpithet
, syn
, zooHashMap
);
1786 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1787 inferredSynonyms
.add(potentialCombination
);
1788 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1789 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1796 if (doWithMisappliedNames
){
1798 for (TaxonRelationship parentRelationship
: taxonRelListParent
){
1800 TaxonNameBase misappliedParentName
;
1802 Taxon misappliedParent
= parentRelationship
.getFromTaxon();
1803 misappliedParentName
= misappliedParent
.getName();
1805 HibernateProxyHelper
.deproxy(misappliedParent
);
1807 // Set the sourceReference
1808 sourceReference
= misappliedParent
.getSec();
1810 // Determine the idInSource
1811 String idInSourceParent
= getIdInSource(misappliedParent
);
1813 ZoologicalName parentSynZooName
= getZoologicalName(misappliedParentName
.getUuid(), zooHashMap
);
1814 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1815 String synParentInfragenericName
= null;
1816 String synParentSpecificEpithet
= null;
1818 if (parentSynZooName
.isInfraGeneric()){
1819 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1821 if (parentSynZooName
.isSpecies()){
1822 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1826 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1827 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1828 ZoologicalName zooMisappliedName
= getZoologicalName(misappliedName
.getName().getUuid(), zooHashMap
);
1829 potentialCombination
= createPotentialCombination(
1830 idInSourceParent
, parentSynZooName
, zooMisappliedName
,
1832 synParentInfragenericName
,
1833 synParentSpecificEpithet
, misappliedName
, zooHashMap
);
1836 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1837 inferredSynonyms
.add(potentialCombination
);
1838 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1839 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1844 if (!taxonNames
.isEmpty()){
1845 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1846 ZoologicalName name
;
1847 if (!synNotInCDM
.isEmpty()){
1848 inferredSynonymsToBeRemoved
.clear();
1849 for (Synonym syn
:inferredSynonyms
){
1851 name
= (ZoologicalName
) syn
.getName();
1852 }catch (ClassCastException e
){
1853 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1855 if (!synNotInCDM
.contains(name
.getNameCache())){
1856 inferredSynonymsToBeRemoved
.add(syn
);
1859 // Remove identified Synonyms from inferredSynonyms
1860 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1861 inferredSynonyms
.remove(synonym
);
1867 logger
.info("The synonymrelationship type is not defined.");
1868 return inferredSynonyms
;
1875 return inferredSynonyms
;
1878 private Synonym
createPotentialCombination(String idInSourceParent
,
1879 ZoologicalName parentSynZooName
, ZoologicalName zooSynName
, String synParentGenus
,
1880 String synParentInfragenericName
, String synParentSpecificEpithet
,
1881 TaxonBase syn
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1882 Synonym potentialCombination
;
1883 Reference sourceReference
;
1884 ZoologicalName inferredSynName
;
1885 HibernateProxyHelper
.deproxy(syn
);
1887 // Set sourceReference
1888 sourceReference
= syn
.getSec();
1889 if (sourceReference
== null){
1890 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
1892 if (!parentSynZooName
.getTaxa().isEmpty()){
1893 TaxonBase taxon
= parentSynZooName
.getTaxa().iterator().next();
1895 sourceReference
= taxon
.getSec();
1898 String synTaxonSpecificEpithet
= zooSynName
.getSpecificEpithet();
1900 String synTaxonInfraSpecificName
= null;
1902 if (parentSynZooName
.isSpecies()){
1903 synTaxonInfraSpecificName
= zooSynName
.getInfraSpecificEpithet();
1906 /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){
1907 synonymsEpithet.add(epithetName);
1910 //create potential combinations...
1911 inferredSynName
= ZoologicalName
.NewInstance(syn
.getName().getRank());
1913 inferredSynName
.setGenusOrUninomial(synParentGenus
);
1914 if (zooSynName
.isSpecies()){
1915 inferredSynName
.setSpecificEpithet(synTaxonSpecificEpithet
);
1916 if (parentSynZooName
.isInfraGeneric()){
1917 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1920 if (zooSynName
.isInfraSpecific()){
1921 inferredSynName
.setSpecificEpithet(synParentSpecificEpithet
);
1922 inferredSynName
.setInfraSpecificEpithet(synTaxonInfraSpecificName
);
1924 if (parentSynZooName
.isInfraGeneric()){
1925 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1929 potentialCombination
= Synonym
.NewInstance(inferredSynName
, null);
1931 // Set the sourceReference
1932 potentialCombination
.setSec(sourceReference
);
1935 // Determine the idInSource
1936 String idInSourceSyn
= getIdInSource(syn
);
1938 if (idInSourceParent
!= null && idInSourceSyn
!= null) {
1939 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
, idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1940 inferredSynName
.addSource(originalSource
);
1941 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
, idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1942 potentialCombination
.addSource(originalSource
);
1945 inferredSynName
.generateTitle();
1947 return potentialCombination
;
1950 private Synonym
createInferredGenus(Taxon taxon
,
1951 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1952 String epithetOfTaxon
, String genusOfTaxon
,
1953 List
<String
> taxonNames
, ZoologicalName zooParentName
,
1956 Synonym inferredGenus
;
1957 TaxonNameBase synName
;
1958 ZoologicalName inferredSynName
;
1959 synName
=syn
.getName();
1960 HibernateProxyHelper
.deproxy(syn
);
1962 // Determine the idInSource
1963 String idInSourceSyn
= getIdInSource(syn
);
1964 String idInSourceTaxon
= getIdInSource(taxon
);
1965 // Determine the sourceReference
1966 Reference sourceReference
= syn
.getSec();
1968 //logger.warn(sourceReference.getTitleCache());
1970 synName
= syn
.getName();
1971 ZoologicalName synZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1972 String synSpeciesEpithetName
= synZooName
.getSpecificEpithet();
1973 /* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){
1974 synonymsEpithet.add(synSpeciesEpithetName);
1977 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1978 //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...
1981 inferredSynName
.setGenusOrUninomial(genusOfTaxon
);
1982 if (zooParentName
.isInfraGeneric()){
1983 inferredSynName
.setInfraGenericEpithet(zooParentName
.getInfraGenericEpithet());
1986 if (taxonName
.isSpecies()){
1987 inferredSynName
.setSpecificEpithet(synSpeciesEpithetName
);
1989 if (taxonName
.isInfraSpecific()){
1990 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
1991 inferredSynName
.setInfraSpecificEpithet(synZooName
.getInfraGenericEpithet());
1995 inferredGenus
= Synonym
.NewInstance(inferredSynName
, null);
1997 // Set the sourceReference
1998 inferredGenus
.setSec(sourceReference
);
2000 // Add the original source
2001 if (idInSourceSyn
!= null && idInSourceTaxon
!= null) {
2002 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2003 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2004 inferredGenus
.addSource(originalSource
);
2006 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2007 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2008 inferredSynName
.addSource(originalSource
);
2009 originalSource
= null;
2012 logger
.error("There is an idInSource missing: " + idInSourceSyn
+ " of Synonym or " + idInSourceTaxon
+ " of Taxon");
2013 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2014 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2015 inferredGenus
.addSource(originalSource
);
2017 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2018 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2019 inferredSynName
.addSource(originalSource
);
2020 originalSource
= null;
2023 taxon
.addSynonym(inferredGenus
, SynonymRelationshipType
.INFERRED_GENUS_OF());
2025 inferredSynName
.generateTitle();
2028 return inferredGenus
;
2031 private Synonym
createInferredEpithets(Taxon taxon
,
2032 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
2033 String epithetOfTaxon
, String infragenericEpithetOfTaxon
,
2034 String infraspecificEpithetOfTaxon
, List
<String
> taxonNames
,
2035 TaxonNameBase parentName
, TaxonBase syn
) {
2037 Synonym inferredEpithet
;
2038 TaxonNameBase
<?
,?
> synName
;
2039 ZoologicalName inferredSynName
;
2040 HibernateProxyHelper
.deproxy(syn
);
2042 // Determine the idInSource
2043 String idInSourceSyn
= getIdInSource(syn
);
2044 String idInSourceTaxon
= getIdInSource(taxon
);
2045 // Determine the sourceReference
2046 Reference
<?
> sourceReference
= syn
.getSec();
2048 if (sourceReference
== null){
2049 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
2051 System
.out
.println("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon
.getSec());
2052 sourceReference
= taxon
.getSec();
2055 synName
= syn
.getName();
2056 ZoologicalName zooSynName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
2057 String synGenusName
= zooSynName
.getGenusOrUninomial();
2058 String synInfraGenericEpithet
= null;
2059 String synSpecificEpithet
= null;
2061 if (zooSynName
.getInfraGenericEpithet() != null){
2062 synInfraGenericEpithet
= zooSynName
.getInfraGenericEpithet();
2065 if (zooSynName
.isInfraSpecific()){
2066 synSpecificEpithet
= zooSynName
.getSpecificEpithet();
2069 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
2070 synonymsGenus.put(synGenusName, idInSource);
2073 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
2075 // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!
2076 if (epithetOfTaxon
== null && infragenericEpithetOfTaxon
== null && infraspecificEpithetOfTaxon
== null) {
2077 logger
.error("This specificEpithet is NULL" + taxon
.getTitleCache());
2079 inferredSynName
.setGenusOrUninomial(synGenusName
);
2081 if (parentName
.isInfraGeneric()){
2082 inferredSynName
.setInfraGenericEpithet(synInfraGenericEpithet
);
2084 if (taxonName
.isSpecies()){
2085 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2086 }else if (taxonName
.isInfraSpecific()){
2087 inferredSynName
.setSpecificEpithet(synSpecificEpithet
);
2088 inferredSynName
.setInfraSpecificEpithet(infraspecificEpithetOfTaxon
);
2091 inferredEpithet
= Synonym
.NewInstance(inferredSynName
, null);
2093 // Set the sourceReference
2094 inferredEpithet
.setSec(sourceReference
);
2096 /* Add the original source
2097 if (idInSource != null) {
2098 IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);
2101 Reference citation = getCitation(syn);
2102 if (citation != null) {
2103 originalSource.setCitation(citation);
2104 inferredEpithet.addSource(originalSource);
2107 String taxonId
= idInSourceTaxon
+ "; " + idInSourceSyn
;
2110 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2111 taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2113 inferredEpithet
.addSource(originalSource
);
2115 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2116 taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2118 inferredSynName
.addSource(originalSource
);
2122 taxon
.addSynonym(inferredEpithet
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
2124 inferredSynName
.generateTitle();
2125 return inferredEpithet
;
2129 * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.
2130 * Very likely only useful for createInferredSynonyms().
2135 private ZoologicalName
getZoologicalName(UUID uuid
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
2136 ZoologicalName taxonName
=nameDao
.findZoologicalNameByUUID(uuid
);
2137 if (taxonName
== null) {
2138 taxonName
= zooHashMap
.get(uuid
);
2144 * Returns the idInSource for a given Synonym.
2147 private String
getIdInSource(TaxonBase taxonBase
) {
2148 String idInSource
= null;
2149 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
2150 if (sources
.size() == 1) {
2151 IdentifiableSource source
= sources
.iterator().next();
2152 if (source
!= null) {
2153 idInSource
= source
.getIdInSource();
2155 } else if (sources
.size() > 1) {
2158 for (IdentifiableSource source
: sources
) {
2159 idInSource
+= source
.getIdInSource();
2160 if (count
< sources
.size()) {
2165 } else if (sources
.size() == 0){
2166 logger
.warn("No idInSource for TaxonBase " + taxonBase
.getUuid() + " - " + taxonBase
.getTitleCache());
2175 * Returns the citation for a given Synonym.
2178 private Reference
getCitation(Synonym syn
) {
2179 Reference citation
= null;
2180 Set
<IdentifiableSource
> sources
= syn
.getSources();
2181 if (sources
.size() == 1) {
2182 IdentifiableSource source
= sources
.iterator().next();
2183 if (source
!= null) {
2184 citation
= source
.getCitation();
2186 } else if (sources
.size() > 1) {
2187 logger
.warn("This Synonym has more than one source: " + syn
.getUuid() + " (" + syn
.getTitleCache() +")");
2194 public List
<Synonym
> createAllInferredSynonyms(Taxon taxon
, Classification tree
, boolean doWithMisappliedNames
){
2195 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
2197 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_EPITHET_OF(), doWithMisappliedNames
));
2198 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_GENUS_OF(), doWithMisappliedNames
));
2199 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames
));
2201 return inferredSynonyms
;
2205 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)
2208 public List
<Classification
> listClassifications(TaxonBase taxonBase
, Integer limit
, Integer start
, List
<String
> propertyPaths
) {
2210 // TODO quickly implemented, create according dao !!!!
2211 Set
<TaxonNode
> nodes
= new HashSet
<TaxonNode
>();
2212 Set
<Classification
> classifications
= new HashSet
<Classification
>();
2213 List
<Classification
> list
= new ArrayList
<Classification
>();
2215 if (taxonBase
== null) {
2219 taxonBase
= load(taxonBase
.getUuid());
2221 if (taxonBase
instanceof Taxon
) {
2222 nodes
.addAll(((Taxon
)taxonBase
).getTaxonNodes());
2224 for (Taxon taxon
: ((Synonym
)taxonBase
).getAcceptedTaxa() ) {
2225 nodes
.addAll(taxon
.getTaxonNodes());
2228 for (TaxonNode node
: nodes
) {
2229 classifications
.add(node
.getClassification());
2231 list
.addAll(classifications
);