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
.SingleRead
;
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 (SingleRead singleRead
: sequence
.getSingleReads()){
851 Amplification amplification
= singleRead
.getAmplification();
852 dnaRelatedMedia
.add(amplification
.getGelPhoto());
853 dnaRelatedMedia
.add(singleRead
.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
){
1206 e
.printStackTrace();
1209 return bestCandidate
;
1212 private boolean isInClassification(Taxon taxon
, MatchingTaxonConfigurator config
) {
1213 UUID configClassificationUuid
= config
.getClassificationUuid();
1214 if (configClassificationUuid
== null){
1217 for (TaxonNode node
: taxon
.getTaxonNodes()){
1218 UUID classUuid
= node
.getClassification().getUuid();
1219 if (configClassificationUuid
.equals(classUuid
)){
1226 private boolean isMatchesSecUuid(Taxon taxon
, MatchingTaxonConfigurator config
) {
1227 UUID configSecUuid
= config
.getSecUuid();
1228 if (configSecUuid
== null){
1231 UUID taxonSecUuid
= (taxon
.getSec() == null)?
null : taxon
.getSec().getUuid();
1232 return configSecUuid
.equals(taxonSecUuid
);
1236 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
1239 public Synonym
findBestMatchingSynonym(String taxonName
) {
1240 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(false, true, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
1241 if(! synonymList
.isEmpty()){
1242 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
1243 if(synonymList
.size() == 1){
1244 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
1247 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());
1256 * @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)
1259 public SynonymRelationship
moveSynonymToAnotherTaxon(SynonymRelationship oldSynonymRelation
, Taxon newTaxon
, boolean moveHomotypicGroup
,
1260 SynonymRelationshipType newSynonymRelationshipType
, Reference reference
, String referenceDetail
, boolean keepReference
) throws HomotypicalGroupChangeException
{
1262 Synonym synonym
= oldSynonymRelation
.getSynonym();
1263 Taxon fromTaxon
= oldSynonymRelation
.getAcceptedTaxon();
1264 //TODO what if there is no name ?? Concepts may be cached (e.g. via TCS import)
1265 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
1266 TaxonNameBase
<?
,?
> fromTaxonName
= fromTaxon
.getName();
1267 //set default relationship type
1268 if (newSynonymRelationshipType
== null){
1269 newSynonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
1271 boolean newRelTypeIsHomotypic
= newSynonymRelationshipType
.equals(SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF());
1273 HomotypicalGroup homotypicGroup
= synonymName
.getHomotypicalGroup();
1274 int hgSize
= homotypicGroup
.getTypifiedNames().size();
1275 boolean isSingleInGroup
= !(hgSize
> 1);
1277 if (! isSingleInGroup
){
1278 boolean isHomotypicToAccepted
= synonymName
.isHomotypic(fromTaxonName
);
1279 boolean hasHomotypicSynonymRelatives
= isHomotypicToAccepted ? hgSize
> 2 : hgSize
> 1;
1280 if (isHomotypicToAccepted
){
1281 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.";
1282 String homotypicRelatives
= hasHomotypicSynonymRelatives ?
" and other synonym(s)":"";
1283 message
= String
.format(message
, homotypicRelatives
);
1284 throw new HomotypicalGroupChangeException(message
);
1286 if (! moveHomotypicGroup
){
1287 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.";
1288 throw new HomotypicalGroupChangeException(message
);
1291 moveHomotypicGroup
= true; //single synonym always allows to moveCompleteGroup
1293 // Assert.assertTrue("Synonym can only be moved with complete homotypic group", moveHomotypicGroup);
1295 SynonymRelationship result
= null;
1296 //move all synonyms to new taxon
1297 List
<Synonym
> homotypicSynonyms
= fromTaxon
.getSynonymsInGroup(homotypicGroup
);
1298 for (Synonym syn
: homotypicSynonyms
){
1299 Set
<SynonymRelationship
> synRelations
= syn
.getSynonymRelations();
1300 for (SynonymRelationship synRelation
: synRelations
){
1301 if (fromTaxon
.equals(synRelation
.getAcceptedTaxon())){
1302 Reference
<?
> newReference
= reference
;
1303 if (newReference
== null && keepReference
){
1304 newReference
= synRelation
.getCitation();
1306 String newRefDetail
= referenceDetail
;
1307 if (newRefDetail
== null && keepReference
){
1308 newRefDetail
= synRelation
.getCitationMicroReference();
1310 SynonymRelationship newSynRelation
= newTaxon
.addSynonym(syn
, newSynonymRelationshipType
, newReference
, newRefDetail
);
1311 fromTaxon
.removeSynonymRelation(synRelation
, false);
1313 //change homotypic group of synonym if relType is 'homotypic'
1314 // if (newRelTypeIsHomotypic){
1315 // newTaxon.getName().getHomotypicalGroup().addTypifiedName(syn.getName());
1318 if (synRelation
.equals(oldSynonymRelation
)){
1319 result
= newSynRelation
;
1325 saveOrUpdate(newTaxon
);
1326 //Assert that there is a result
1327 if (result
== null){
1328 String message
= "Old synonym relation could not be transformed into new relation. This should not happen.";
1329 throw new IllegalStateException(message
);
1335 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
1338 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheTaxon() {
1339 return dao
.getUuidAndTitleCacheTaxon();
1343 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
1346 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheSynonym() {
1347 return dao
.getUuidAndTitleCacheSynonym();
1351 * @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)
1354 public Pager
<SearchResult
<TaxonBase
>> findByFullText(
1355 Class
<?
extends TaxonBase
> clazz
, String queryString
,
1356 Classification classification
, List
<Language
> languages
,
1357 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1360 LuceneSearch luceneSearch
= prepareFindByFullTextSearch(clazz
, queryString
, classification
, languages
, highlightFragments
);
1362 // --- execute search
1363 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1365 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1366 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1368 // --- initialize taxa, thighlight matches ....
1369 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1370 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1371 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1373 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1374 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1379 * @param queryString
1380 * @param classification
1382 * @param highlightFragments
1383 * @param directorySelectClass
1386 protected LuceneSearch
prepareFindByFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Language
> languages
,
1387 boolean highlightFragments
) {
1388 BooleanQuery finalQuery
= new BooleanQuery();
1389 BooleanQuery textQuery
= new BooleanQuery();
1391 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), TaxonBase
.class);
1392 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1394 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("titleCache__sort", SortField
.STRING
, false)};
1395 luceneSearch
.setSortFields(sortFields
);
1397 // ---- search criteria
1398 luceneSearch
.setClazz(clazz
);
1400 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1401 textQuery
.add(queryFactory
.newDefinedTermQuery("name.rank", queryString
, languages
), Occur
.SHOULD
);
1403 finalQuery
.add(textQuery
, Occur
.MUST
);
1405 if(classification
!= null){
1406 finalQuery
.add(queryFactory
.newEntityIdQuery("taxonNodes.classification.id", classification
), Occur
.MUST
);
1408 luceneSearch
.setQuery(finalQuery
);
1410 if(highlightFragments
){
1411 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1413 return luceneSearch
;
1418 * @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)
1421 public Pager
<SearchResult
<TaxonBase
>> findByDescriptionElementFullText(
1422 Class
<?
extends DescriptionElementBase
> clazz
, String queryString
,
1423 Classification classification
, List
<Feature
> features
, List
<Language
> languages
,
1424 boolean highlightFragments
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1427 LuceneSearch luceneSearch
= prepareByDescriptionElementFullTextSearch(clazz
, queryString
, classification
, features
, languages
, highlightFragments
);
1429 // --- execute search
1430 TopGroupsWithMaxScore topDocsResultSet
= luceneSearch
.executeSearch(pageSize
, pageNumber
);
1432 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1433 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1435 // --- initialize taxa, highlight matches ....
1436 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(luceneSearch
, luceneSearch
.getQuery());
1437 @SuppressWarnings("rawtypes")
1438 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1439 topDocsResultSet
, luceneSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1441 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupCount
: 0;
1442 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1448 public Pager
<SearchResult
<TaxonBase
>> findByEverythingFullText(String queryString
,
1449 Classification classification
, List
<Language
> languages
, boolean highlightFragments
,
1450 Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws CorruptIndexException
, IOException
, ParseException
{
1452 LuceneSearch luceneSearchByDescriptionElement
= prepareByDescriptionElementFullTextSearch(null, queryString
, classification
, null, languages
, highlightFragments
);
1453 LuceneSearch luceneSearchByTaxonBase
= prepareFindByFullTextSearch(null, queryString
, classification
, languages
, highlightFragments
);
1455 LuceneMultiSearch multiSearch
= new LuceneMultiSearch(luceneSearchByDescriptionElement
, luceneSearchByTaxonBase
);
1457 // --- execute search
1458 TopGroupsWithMaxScore topDocsResultSet
= multiSearch
.executeSearch(pageSize
, pageNumber
);
1460 // --- initialize taxa, highlight matches ....
1461 ISearchResultBuilder searchResultBuilder
= new SearchResultBuilder(multiSearch
, multiSearch
.getQuery());
1463 Map
<CdmBaseType
, String
> idFieldMap
= new HashMap
<CdmBaseType
, String
>();
1464 idFieldMap
.put(CdmBaseType
.TAXON
, "id");
1465 idFieldMap
.put(CdmBaseType
.DESCRIPTION_ELEMENT
, "inDescription.taxon.id");
1467 List
<SearchResult
<TaxonBase
>> searchResults
= searchResultBuilder
.createResultSet(
1468 topDocsResultSet
, multiSearch
.getHighlightFields(), dao
, idFieldMap
, propertyPaths
);
1470 int totalHits
= topDocsResultSet
!= null ? topDocsResultSet
.topGroups
.totalGroupedHitCount
: 0;
1471 return new DefaultPagerImpl
<SearchResult
<TaxonBase
>>(pageNumber
, totalHits
, pageSize
, searchResults
);
1478 * @param queryString
1479 * @param classification
1482 * @param highlightFragments
1483 * @param directorySelectClass
1486 protected LuceneSearch
prepareByDescriptionElementFullTextSearch(Class
<?
extends CdmBase
> clazz
, String queryString
, Classification classification
, List
<Feature
> features
,
1487 List
<Language
> languages
, boolean highlightFragments
) {
1488 BooleanQuery finalQuery
= new BooleanQuery();
1489 BooleanQuery textQuery
= new BooleanQuery();
1491 LuceneSearch luceneSearch
= new LuceneSearch(getSession(), GroupByTaxonClassBridge
.GROUPBY_TAXON_FIELD
, DescriptionElementBase
.class);
1492 QueryFactory queryFactory
= new QueryFactory(luceneSearch
);
1494 SortField
[] sortFields
= new SortField
[]{SortField
.FIELD_SCORE
, new SortField("inDescription.taxon.titleCache__sort", SortField
.STRING
, false)};
1495 luceneSearch
.setSortFields(sortFields
);
1497 // ---- search criteria
1498 luceneSearch
.setClazz(clazz
);
1499 textQuery
.add(queryFactory
.newTermQuery("titleCache", queryString
), Occur
.SHOULD
);
1503 if(languages
== null || languages
.size() == 0){
1504 nameQuery
= queryFactory
.newTermQuery("name", queryString
);
1506 nameQuery
= new BooleanQuery();
1507 BooleanQuery languageSubQuery
= new BooleanQuery();
1508 for(Language lang
: languages
){
1509 languageSubQuery
.add(queryFactory
.newTermQuery("language.uuid", lang
.getUuid().toString(), false), Occur
.SHOULD
);
1511 ((BooleanQuery
) nameQuery
).add(queryFactory
.newTermQuery("name", queryString
), Occur
.MUST
);
1512 ((BooleanQuery
) nameQuery
).add(languageSubQuery
, Occur
.MUST
);
1514 textQuery
.add(nameQuery
, Occur
.SHOULD
);
1517 // text field from TextData
1518 textQuery
.add(queryFactory
.newMultilanguageTextQuery("text", queryString
, languages
), Occur
.SHOULD
);
1520 // --- TermBase fields - by representation ----
1521 // state field from CategoricalData
1522 textQuery
.add(queryFactory
.newDefinedTermQuery("stateData.state", queryString
, languages
), Occur
.SHOULD
);
1524 // state field from CategoricalData
1525 textQuery
.add(queryFactory
.newDefinedTermQuery("stateData.modifyingText", queryString
, languages
), Occur
.SHOULD
);
1527 // area field from Distribution
1528 textQuery
.add(queryFactory
.newDefinedTermQuery("area", queryString
, languages
), Occur
.SHOULD
);
1530 // status field from Distribution
1531 textQuery
.add(queryFactory
.newDefinedTermQuery("status", queryString
, languages
), Occur
.SHOULD
);
1533 finalQuery
.add(textQuery
, Occur
.MUST
);
1534 // --- classification ----
1536 if(classification
!= null){
1537 finalQuery
.add(queryFactory
.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification
), Occur
.MUST
);
1540 // --- IdentifieableEntity fields - by uuid
1541 if(features
!= null && features
.size() > 0 ){
1542 finalQuery
.add(queryFactory
.newEntityUuidQuery("feature.uuid", features
), Occur
.MUST
);
1545 // the description must be associated with a taxon
1546 finalQuery
.add(queryFactory
.newIsNotNullQuery("inDescription.taxon.id"), Occur
.MUST
);
1548 logger
.info("prepareByDescriptionElementFullTextSearch() query: " + finalQuery
.toString());
1549 luceneSearch
.setQuery(finalQuery
);
1551 if(highlightFragments
){
1552 luceneSearch
.setHighlightFields(queryFactory
.getTextFieldNamesAsArray());
1554 return luceneSearch
;
1558 * DefinedTerm representations and MultilanguageString maps are stored in the Lucene index by the {@link DefinedTermBaseClassBridge}
1559 * and {@link MultilanguageTextFieldBridge } in a consistent way. One field per language and also in one additional field for all languages.
1560 * This method is a convenient means to retrieve a Lucene query string for such the fields.
1562 * @param name name of the term field as in the Lucene index. Must be field created by {@link DefinedTermBaseClassBridge}
1563 * or {@link MultilanguageTextFieldBridge }
1564 * @param languages the languages to search for exclusively. Can be <code>null</code> to search in all languages
1565 * @param stringBuilder a StringBuilder to be reused, if <code>null</code> a new StringBuilder will be instantiated and is returned
1566 * @return the StringBuilder given a parameter or a new one if the stringBuilder parameter was null.
1568 * TODO move to utiliy class !!!!!!!!
1570 private StringBuilder
appendLocalizedFieldQuery(String name
, List
<Language
> languages
, StringBuilder stringBuilder
) {
1572 if(stringBuilder
== null){
1573 stringBuilder
= new StringBuilder();
1575 if(languages
== null || languages
.size() == 0){
1576 stringBuilder
.append(name
+ ".ALL:(%1$s) ");
1578 for(Language lang
: languages
){
1579 stringBuilder
.append(name
+ "." + lang
.getUuid().toString() + ":(%1$s) ");
1582 return stringBuilder
;
1586 public List
<Synonym
> createInferredSynonyms(Taxon taxon
, Classification classification
, SynonymRelationshipType type
, boolean doWithMisappliedNames
){
1587 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
1588 List
<Synonym
> inferredSynonymsToBeRemoved
= new ArrayList
<Synonym
>();
1590 HashMap
<UUID
, ZoologicalName
> zooHashMap
= new HashMap
<UUID
, ZoologicalName
>();
1593 UUID nameUuid
= taxon
.getName().getUuid();
1594 ZoologicalName taxonName
= getZoologicalName(nameUuid
, zooHashMap
);
1595 String epithetOfTaxon
= null;
1596 String infragenericEpithetOfTaxon
= null;
1597 String infraspecificEpithetOfTaxon
= null;
1598 if (taxonName
.isSpecies()){
1599 epithetOfTaxon
= taxonName
.getSpecificEpithet();
1600 } else if (taxonName
.isInfraGeneric()){
1601 infragenericEpithetOfTaxon
= taxonName
.getInfraGenericEpithet();
1602 } else if (taxonName
.isInfraSpecific()){
1603 infraspecificEpithetOfTaxon
= taxonName
.getInfraSpecificEpithet();
1605 String genusOfTaxon
= taxonName
.getGenusOrUninomial();
1606 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
1607 List
<String
> taxonNames
= new ArrayList
<String
>();
1609 for (TaxonNode node
: nodes
){
1610 // HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName
1611 // List<String> synonymsEpithet = new ArrayList<String>();
1613 if (node
.getClassification().equals(classification
)){
1614 if (!node
.isTopmostNode()){
1615 TaxonNode parent
= node
.getParent();
1616 parent
= (TaxonNode
)HibernateProxyHelper
.deproxy(parent
);
1617 TaxonNameBase
<?
,?
> parentName
= parent
.getTaxon().getName();
1618 ZoologicalName zooParentName
= HibernateProxyHelper
.deproxy(parentName
, ZoologicalName
.class);
1619 Taxon parentTaxon
= (Taxon
)HibernateProxyHelper
.deproxy(parent
.getTaxon());
1620 Rank rankOfTaxon
= taxonName
.getRank();
1623 //create inferred synonyms for species, subspecies
1624 if ((parentName
.isGenus() || parentName
.isSpecies() || parentName
.getRank().equals(Rank
.SUBGENUS())) ){
1626 Synonym inferredEpithet
= null;
1627 Synonym inferredGenus
= null;
1628 Synonym potentialCombination
= null;
1630 List
<String
> propertyPaths
= new ArrayList
<String
>();
1631 propertyPaths
.add("synonym");
1632 propertyPaths
.add("synonym.name");
1633 List
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
1634 orderHints
.add(new OrderHint("relatedFrom.titleCache", SortOrder
.ASCENDING
));
1636 List
<SynonymRelationship
> synonymRelationshipsOfParent
= dao
.getSynonyms(parentTaxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1637 List
<SynonymRelationship
> synonymRelationshipsOfTaxon
= dao
.getSynonyms(taxon
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), null, null,orderHints
,propertyPaths
);
1639 List
<TaxonRelationship
> taxonRelListParent
= null;
1640 List
<TaxonRelationship
> taxonRelListTaxon
= null;
1641 if (doWithMisappliedNames
){
1642 taxonRelListParent
= dao
.getTaxonRelationships(parentTaxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1643 taxonRelListTaxon
= dao
.getTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, orderHints
, propertyPaths
, Direction
.relatedTo
);
1647 if (type
.equals(SynonymRelationshipType
.INFERRED_EPITHET_OF())){
1650 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1651 Synonym syn
= synonymRelationOfParent
.getSynonym();
1653 inferredEpithet
= createInferredEpithets(taxon
,
1654 zooHashMap
, taxonName
, epithetOfTaxon
,
1655 infragenericEpithetOfTaxon
,
1656 infraspecificEpithetOfTaxon
,
1657 taxonNames
, parentName
,
1661 inferredSynonyms
.add(inferredEpithet
);
1662 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1663 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1666 if (doWithMisappliedNames
){
1668 for (TaxonRelationship taxonRelationship
: taxonRelListParent
){
1669 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1671 inferredEpithet
= createInferredEpithets(taxon
,
1672 zooHashMap
, taxonName
, epithetOfTaxon
,
1673 infragenericEpithetOfTaxon
,
1674 infraspecificEpithetOfTaxon
,
1675 taxonNames
, parentName
,
1678 inferredSynonyms
.add(inferredEpithet
);
1679 zooHashMap
.put(inferredEpithet
.getName().getUuid(), (ZoologicalName
)inferredEpithet
.getName());
1680 taxonNames
.add(((ZoologicalName
)inferredEpithet
.getName()).getNameCache());
1684 if (!taxonNames
.isEmpty()){
1685 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1686 ZoologicalName name
;
1687 if (!synNotInCDM
.isEmpty()){
1688 inferredSynonymsToBeRemoved
.clear();
1690 for (Synonym syn
:inferredSynonyms
){
1691 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1692 if (!synNotInCDM
.contains(name
.getNameCache())){
1693 inferredSynonymsToBeRemoved
.add(syn
);
1697 // Remove identified Synonyms from inferredSynonyms
1698 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1699 inferredSynonyms
.remove(synonym
);
1704 }else if (type
.equals(SynonymRelationshipType
.INFERRED_GENUS_OF())){
1707 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1708 TaxonNameBase synName
;
1709 ZoologicalName inferredSynName
;
1711 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1712 inferredGenus
= createInferredGenus(taxon
,
1713 zooHashMap
, taxonName
, epithetOfTaxon
,
1714 genusOfTaxon
, taxonNames
, zooParentName
, syn
);
1716 inferredSynonyms
.add(inferredGenus
);
1717 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1718 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1723 if (doWithMisappliedNames
){
1725 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1726 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1727 inferredGenus
= createInferredGenus(taxon
, zooHashMap
, taxonName
, infraspecificEpithetOfTaxon
, genusOfTaxon
, taxonNames
, zooParentName
, misappliedName
);
1729 inferredSynonyms
.add(inferredGenus
);
1730 zooHashMap
.put(inferredGenus
.getName().getUuid(), (ZoologicalName
)inferredGenus
.getName());
1731 taxonNames
.add(( (ZoologicalName
)inferredGenus
.getName()).getNameCache());
1736 if (!taxonNames
.isEmpty()){
1737 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1738 ZoologicalName name
;
1739 if (!synNotInCDM
.isEmpty()){
1740 inferredSynonymsToBeRemoved
.clear();
1742 for (Synonym syn
:inferredSynonyms
){
1743 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1744 if (!synNotInCDM
.contains(name
.getNameCache())){
1745 inferredSynonymsToBeRemoved
.add(syn
);
1749 // Remove identified Synonyms from inferredSynonyms
1750 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1751 inferredSynonyms
.remove(synonym
);
1756 }else if (type
.equals(SynonymRelationshipType
.POTENTIAL_COMBINATION_OF())){
1758 Reference sourceReference
= null; // TODO: Determination of sourceReference is redundant
1759 ZoologicalName inferredSynName
;
1760 //for all synonyms of the parent...
1761 for (SynonymRelationship synonymRelationOfParent
:synonymRelationshipsOfParent
){
1762 TaxonNameBase synName
;
1763 Synonym synParent
= synonymRelationOfParent
.getSynonym();
1764 synName
= synParent
.getName();
1766 HibernateProxyHelper
.deproxy(synParent
);
1768 // Set the sourceReference
1769 sourceReference
= synParent
.getSec();
1771 // Determine the idInSource
1772 String idInSourceParent
= getIdInSource(synParent
);
1774 ZoologicalName parentSynZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1775 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1776 String synParentInfragenericName
= null;
1777 String synParentSpecificEpithet
= null;
1779 if (parentSynZooName
.isInfraGeneric()){
1780 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1782 if (parentSynZooName
.isSpecies()){
1783 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1786 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
1787 synonymsGenus.put(synGenusName, idInSource);
1790 //for all synonyms of the taxon
1792 for (SynonymRelationship synonymRelationOfTaxon
:synonymRelationshipsOfTaxon
){
1794 Synonym syn
= synonymRelationOfTaxon
.getSynonym();
1795 ZoologicalName zooSynName
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1796 potentialCombination
= createPotentialCombination(idInSourceParent
, parentSynZooName
, zooSynName
,
1798 synParentInfragenericName
,
1799 synParentSpecificEpithet
, syn
, zooHashMap
);
1801 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1802 inferredSynonyms
.add(potentialCombination
);
1803 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1804 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1811 if (doWithMisappliedNames
){
1813 for (TaxonRelationship parentRelationship
: taxonRelListParent
){
1815 TaxonNameBase misappliedParentName
;
1817 Taxon misappliedParent
= parentRelationship
.getFromTaxon();
1818 misappliedParentName
= misappliedParent
.getName();
1820 HibernateProxyHelper
.deproxy(misappliedParent
);
1822 // Set the sourceReference
1823 sourceReference
= misappliedParent
.getSec();
1825 // Determine the idInSource
1826 String idInSourceParent
= getIdInSource(misappliedParent
);
1828 ZoologicalName parentSynZooName
= getZoologicalName(misappliedParentName
.getUuid(), zooHashMap
);
1829 String synParentGenus
= parentSynZooName
.getGenusOrUninomial();
1830 String synParentInfragenericName
= null;
1831 String synParentSpecificEpithet
= null;
1833 if (parentSynZooName
.isInfraGeneric()){
1834 synParentInfragenericName
= parentSynZooName
.getInfraGenericEpithet();
1836 if (parentSynZooName
.isSpecies()){
1837 synParentSpecificEpithet
= parentSynZooName
.getSpecificEpithet();
1841 for (TaxonRelationship taxonRelationship
: taxonRelListTaxon
){
1842 Taxon misappliedName
= taxonRelationship
.getFromTaxon();
1843 ZoologicalName zooMisappliedName
= getZoologicalName(misappliedName
.getName().getUuid(), zooHashMap
);
1844 potentialCombination
= createPotentialCombination(
1845 idInSourceParent
, parentSynZooName
, zooMisappliedName
,
1847 synParentInfragenericName
,
1848 synParentSpecificEpithet
, misappliedName
, zooHashMap
);
1851 taxon
.addSynonym(potentialCombination
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF());
1852 inferredSynonyms
.add(potentialCombination
);
1853 zooHashMap
.put(potentialCombination
.getName().getUuid(), (ZoologicalName
)potentialCombination
.getName());
1854 taxonNames
.add(( (ZoologicalName
)potentialCombination
.getName()).getNameCache());
1859 if (!taxonNames
.isEmpty()){
1860 List
<String
> synNotInCDM
= dao
.taxaByNameNotInDB(taxonNames
);
1861 ZoologicalName name
;
1862 if (!synNotInCDM
.isEmpty()){
1863 inferredSynonymsToBeRemoved
.clear();
1864 for (Synonym syn
:inferredSynonyms
){
1866 name
= (ZoologicalName
) syn
.getName();
1867 }catch (ClassCastException e
){
1868 name
= getZoologicalName(syn
.getName().getUuid(), zooHashMap
);
1870 if (!synNotInCDM
.contains(name
.getNameCache())){
1871 inferredSynonymsToBeRemoved
.add(syn
);
1874 // Remove identified Synonyms from inferredSynonyms
1875 for (Synonym synonym
: inferredSynonymsToBeRemoved
) {
1876 inferredSynonyms
.remove(synonym
);
1882 logger
.info("The synonymrelationship type is not defined.");
1883 return inferredSynonyms
;
1890 return inferredSynonyms
;
1893 private Synonym
createPotentialCombination(String idInSourceParent
,
1894 ZoologicalName parentSynZooName
, ZoologicalName zooSynName
, String synParentGenus
,
1895 String synParentInfragenericName
, String synParentSpecificEpithet
,
1896 TaxonBase syn
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
1897 Synonym potentialCombination
;
1898 Reference sourceReference
;
1899 ZoologicalName inferredSynName
;
1900 HibernateProxyHelper
.deproxy(syn
);
1902 // Set sourceReference
1903 sourceReference
= syn
.getSec();
1904 if (sourceReference
== null){
1905 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
1907 if (!parentSynZooName
.getTaxa().isEmpty()){
1908 TaxonBase taxon
= parentSynZooName
.getTaxa().iterator().next();
1910 sourceReference
= taxon
.getSec();
1913 String synTaxonSpecificEpithet
= zooSynName
.getSpecificEpithet();
1915 String synTaxonInfraSpecificName
= null;
1917 if (parentSynZooName
.isSpecies()){
1918 synTaxonInfraSpecificName
= zooSynName
.getInfraSpecificEpithet();
1921 /*if (epithetName != null && !synonymsEpithet.contains(epithetName)){
1922 synonymsEpithet.add(epithetName);
1925 //create potential combinations...
1926 inferredSynName
= ZoologicalName
.NewInstance(syn
.getName().getRank());
1928 inferredSynName
.setGenusOrUninomial(synParentGenus
);
1929 if (zooSynName
.isSpecies()){
1930 inferredSynName
.setSpecificEpithet(synTaxonSpecificEpithet
);
1931 if (parentSynZooName
.isInfraGeneric()){
1932 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1935 if (zooSynName
.isInfraSpecific()){
1936 inferredSynName
.setSpecificEpithet(synParentSpecificEpithet
);
1937 inferredSynName
.setInfraSpecificEpithet(synTaxonInfraSpecificName
);
1939 if (parentSynZooName
.isInfraGeneric()){
1940 inferredSynName
.setInfraGenericEpithet(synParentInfragenericName
);
1944 potentialCombination
= Synonym
.NewInstance(inferredSynName
, null);
1946 // Set the sourceReference
1947 potentialCombination
.setSec(sourceReference
);
1950 // Determine the idInSource
1951 String idInSourceSyn
= getIdInSource(syn
);
1953 if (idInSourceParent
!= null && idInSourceSyn
!= null) {
1954 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
, idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1955 inferredSynName
.addSource(originalSource
);
1956 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
, idInSourceSyn
+ "; " + idInSourceParent
, POTENTIAL_COMBINATION_NAMESPACE
, sourceReference
, null);
1957 potentialCombination
.addSource(originalSource
);
1960 inferredSynName
.generateTitle();
1962 return potentialCombination
;
1965 private Synonym
createInferredGenus(Taxon taxon
,
1966 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
1967 String epithetOfTaxon
, String genusOfTaxon
,
1968 List
<String
> taxonNames
, ZoologicalName zooParentName
,
1971 Synonym inferredGenus
;
1972 TaxonNameBase synName
;
1973 ZoologicalName inferredSynName
;
1974 synName
=syn
.getName();
1975 HibernateProxyHelper
.deproxy(syn
);
1977 // Determine the idInSource
1978 String idInSourceSyn
= getIdInSource(syn
);
1979 String idInSourceTaxon
= getIdInSource(taxon
);
1980 // Determine the sourceReference
1981 Reference sourceReference
= syn
.getSec();
1983 //logger.warn(sourceReference.getTitleCache());
1985 synName
= syn
.getName();
1986 ZoologicalName synZooName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
1987 String synSpeciesEpithetName
= synZooName
.getSpecificEpithet();
1988 /* if (synonymsEpithet != null && !synonymsEpithet.contains(synSpeciesEpithetName)){
1989 synonymsEpithet.add(synSpeciesEpithetName);
1992 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
1993 //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...
1996 inferredSynName
.setGenusOrUninomial(genusOfTaxon
);
1997 if (zooParentName
.isInfraGeneric()){
1998 inferredSynName
.setInfraGenericEpithet(zooParentName
.getInfraGenericEpithet());
2001 if (taxonName
.isSpecies()){
2002 inferredSynName
.setSpecificEpithet(synSpeciesEpithetName
);
2004 if (taxonName
.isInfraSpecific()){
2005 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2006 inferredSynName
.setInfraSpecificEpithet(synZooName
.getInfraGenericEpithet());
2010 inferredGenus
= Synonym
.NewInstance(inferredSynName
, null);
2012 // Set the sourceReference
2013 inferredGenus
.setSec(sourceReference
);
2015 // Add the original source
2016 if (idInSourceSyn
!= null && idInSourceTaxon
!= null) {
2017 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2018 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2019 inferredGenus
.addSource(originalSource
);
2021 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2022 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2023 inferredSynName
.addSource(originalSource
);
2024 originalSource
= null;
2027 logger
.error("There is an idInSource missing: " + idInSourceSyn
+ " of Synonym or " + idInSourceTaxon
+ " of Taxon");
2028 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2029 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2030 inferredGenus
.addSource(originalSource
);
2032 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2033 idInSourceSyn
+ "; " + idInSourceTaxon
, INFERRED_GENUS_NAMESPACE
, sourceReference
, null);
2034 inferredSynName
.addSource(originalSource
);
2035 originalSource
= null;
2038 taxon
.addSynonym(inferredGenus
, SynonymRelationshipType
.INFERRED_GENUS_OF());
2040 inferredSynName
.generateTitle();
2043 return inferredGenus
;
2046 private Synonym
createInferredEpithets(Taxon taxon
,
2047 HashMap
<UUID
, ZoologicalName
> zooHashMap
, ZoologicalName taxonName
,
2048 String epithetOfTaxon
, String infragenericEpithetOfTaxon
,
2049 String infraspecificEpithetOfTaxon
, List
<String
> taxonNames
,
2050 TaxonNameBase parentName
, TaxonBase syn
) {
2052 Synonym inferredEpithet
;
2053 TaxonNameBase
<?
,?
> synName
;
2054 ZoologicalName inferredSynName
;
2055 HibernateProxyHelper
.deproxy(syn
);
2057 // Determine the idInSource
2058 String idInSourceSyn
= getIdInSource(syn
);
2059 String idInSourceTaxon
= getIdInSource(taxon
);
2060 // Determine the sourceReference
2061 Reference
<?
> sourceReference
= syn
.getSec();
2063 if (sourceReference
== null){
2064 logger
.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon");
2066 System
.out
.println("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon
.getSec());
2067 sourceReference
= taxon
.getSec();
2070 synName
= syn
.getName();
2071 ZoologicalName zooSynName
= getZoologicalName(synName
.getUuid(), zooHashMap
);
2072 String synGenusName
= zooSynName
.getGenusOrUninomial();
2073 String synInfraGenericEpithet
= null;
2074 String synSpecificEpithet
= null;
2076 if (zooSynName
.getInfraGenericEpithet() != null){
2077 synInfraGenericEpithet
= zooSynName
.getInfraGenericEpithet();
2080 if (zooSynName
.isInfraSpecific()){
2081 synSpecificEpithet
= zooSynName
.getSpecificEpithet();
2084 /* if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){
2085 synonymsGenus.put(synGenusName, idInSource);
2088 inferredSynName
= ZoologicalName
.NewInstance(taxon
.getName().getRank());
2090 // DEBUG TODO: for subgenus or subspecies the infrageneric or infraspecific epithet should be used!!!
2091 if (epithetOfTaxon
== null && infragenericEpithetOfTaxon
== null && infraspecificEpithetOfTaxon
== null) {
2092 logger
.error("This specificEpithet is NULL" + taxon
.getTitleCache());
2094 inferredSynName
.setGenusOrUninomial(synGenusName
);
2096 if (parentName
.isInfraGeneric()){
2097 inferredSynName
.setInfraGenericEpithet(synInfraGenericEpithet
);
2099 if (taxonName
.isSpecies()){
2100 inferredSynName
.setSpecificEpithet(epithetOfTaxon
);
2101 }else if (taxonName
.isInfraSpecific()){
2102 inferredSynName
.setSpecificEpithet(synSpecificEpithet
);
2103 inferredSynName
.setInfraSpecificEpithet(infraspecificEpithetOfTaxon
);
2106 inferredEpithet
= Synonym
.NewInstance(inferredSynName
, null);
2108 // Set the sourceReference
2109 inferredEpithet
.setSec(sourceReference
);
2111 /* Add the original source
2112 if (idInSource != null) {
2113 IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);
2116 Reference citation = getCitation(syn);
2117 if (citation != null) {
2118 originalSource.setCitation(citation);
2119 inferredEpithet.addSource(originalSource);
2122 String taxonId
= idInSourceTaxon
+ "; " + idInSourceSyn
;
2125 IdentifiableSource originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2126 taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2128 inferredEpithet
.addSource(originalSource
);
2130 originalSource
= IdentifiableSource
.NewInstance(OriginalSourceType
.Transformation
,
2131 taxonId
, INFERRED_EPITHET_NAMESPACE
, sourceReference
, null);
2133 inferredSynName
.addSource(originalSource
);
2137 taxon
.addSynonym(inferredEpithet
, SynonymRelationshipType
.INFERRED_EPITHET_OF());
2139 inferredSynName
.generateTitle();
2140 return inferredEpithet
;
2144 * Returns an existing ZoologicalName or extends an internal hashmap if it does not exist.
2145 * Very likely only useful for createInferredSynonyms().
2150 private ZoologicalName
getZoologicalName(UUID uuid
, HashMap
<UUID
, ZoologicalName
> zooHashMap
) {
2151 ZoologicalName taxonName
=nameDao
.findZoologicalNameByUUID(uuid
);
2152 if (taxonName
== null) {
2153 taxonName
= zooHashMap
.get(uuid
);
2159 * Returns the idInSource for a given Synonym.
2162 private String
getIdInSource(TaxonBase taxonBase
) {
2163 String idInSource
= null;
2164 Set
<IdentifiableSource
> sources
= taxonBase
.getSources();
2165 if (sources
.size() == 1) {
2166 IdentifiableSource source
= sources
.iterator().next();
2167 if (source
!= null) {
2168 idInSource
= source
.getIdInSource();
2170 } else if (sources
.size() > 1) {
2173 for (IdentifiableSource source
: sources
) {
2174 idInSource
+= source
.getIdInSource();
2175 if (count
< sources
.size()) {
2180 } else if (sources
.size() == 0){
2181 logger
.warn("No idInSource for TaxonBase " + taxonBase
.getUuid() + " - " + taxonBase
.getTitleCache());
2190 * Returns the citation for a given Synonym.
2193 private Reference
getCitation(Synonym syn
) {
2194 Reference citation
= null;
2195 Set
<IdentifiableSource
> sources
= syn
.getSources();
2196 if (sources
.size() == 1) {
2197 IdentifiableSource source
= sources
.iterator().next();
2198 if (source
!= null) {
2199 citation
= source
.getCitation();
2201 } else if (sources
.size() > 1) {
2202 logger
.warn("This Synonym has more than one source: " + syn
.getUuid() + " (" + syn
.getTitleCache() +")");
2209 public List
<Synonym
> createAllInferredSynonyms(Taxon taxon
, Classification tree
, boolean doWithMisappliedNames
){
2210 List
<Synonym
> inferredSynonyms
= new ArrayList
<Synonym
>();
2212 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_EPITHET_OF(), doWithMisappliedNames
));
2213 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.INFERRED_GENUS_OF(), doWithMisappliedNames
));
2214 inferredSynonyms
.addAll(createInferredSynonyms(taxon
, tree
, SynonymRelationshipType
.POTENTIAL_COMBINATION_OF(), doWithMisappliedNames
));
2216 return inferredSynonyms
;
2220 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)
2223 public List
<Classification
> listClassifications(TaxonBase taxonBase
, Integer limit
, Integer start
, List
<String
> propertyPaths
) {
2225 // TODO quickly implemented, create according dao !!!!
2226 Set
<TaxonNode
> nodes
= new HashSet
<TaxonNode
>();
2227 Set
<Classification
> classifications
= new HashSet
<Classification
>();
2228 List
<Classification
> list
= new ArrayList
<Classification
>();
2230 if (taxonBase
== null) {
2234 taxonBase
= load(taxonBase
.getUuid());
2236 if (taxonBase
instanceof Taxon
) {
2237 nodes
.addAll(((Taxon
)taxonBase
).getTaxonNodes());
2239 for (Taxon taxon
: ((Synonym
)taxonBase
).getAcceptedTaxa() ) {
2240 nodes
.addAll(taxon
.getTaxonNodes());
2243 for (TaxonNode node
: nodes
) {
2244 classifications
.add(node
.getClassification());
2246 list
.addAll(classifications
);