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
.util
.ArrayList
;
14 import java
.util
.Comparator
;
15 import java
.util
.HashSet
;
16 import java
.util
.List
;
18 import java
.util
.UUID
;
20 import org
.apache
.log4j
.Logger
;
21 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
22 import org
.springframework
.stereotype
.Service
;
23 import org
.springframework
.transaction
.annotation
.Propagation
;
24 import org
.springframework
.transaction
.annotation
.Transactional
;
26 import eu
.etaxonomy
.cdm
.api
.service
.config
.ITaxonServiceConfigurator
;
27 import eu
.etaxonomy
.cdm
.api
.service
.config
.MatchingTaxonConfigurator
;
28 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
29 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
30 import eu
.etaxonomy
.cdm
.common
.IProgressMonitor
;
31 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
32 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
33 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
34 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
35 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
36 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
37 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
38 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
39 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
40 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
41 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
42 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
43 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
44 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
45 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
46 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
47 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
48 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
49 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
55 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
56 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
57 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
58 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
59 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
60 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
61 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
65 * @author a.kohlbecker
70 @Transactional(propagation
= Propagation
.SUPPORTS
, readOnly
= true)
71 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
72 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
75 private ITaxonNameDao nameDao
;
78 private IOrderedTermVocabularyDao orderedVocabularyDao
;
81 private INameService nameService
;
86 public TaxonServiceImpl(){
87 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
91 * FIXME Candidate for harmonization
92 * rename searchByName ?
94 public List
<TaxonBase
> searchTaxaByName(String name
, Reference sec
) {
95 return dao
.getTaxaByName(name
, sec
);
99 * FIXME Candidate for harmonization
100 * list(Synonym.class, ...)
102 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
104 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
105 return dao
.getAllSynonyms(limit
, start
);
109 * FIXME Candidate for harmonization
110 * list(Taxon.class, ...)
112 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
114 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
115 return dao
.getAllTaxa(limit
, start
);
119 * FIXME Candidate for harmonization
120 * merge with getRootTaxa(Reference sec, ..., ...)
122 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)
124 public List
<Taxon
> getRootTaxa(Reference sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
125 if (cdmFetch
== null){
126 cdmFetch
= CdmFetch
.NO_FETCH();
128 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
133 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
135 public List
<Taxon
> getRootTaxa(Rank rank
, Reference sec
, boolean onlyWithChildren
,boolean withMisapplications
, List
<String
> propertyPaths
) {
136 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
140 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)
142 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
143 return dao
.getAllRelationships(limit
, start
);
147 * FIXME Candidate for harmonization
148 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
151 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
153 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
154 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
155 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
156 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
157 return taxonRelTypeVocabulary
;
164 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
166 @Transactional(readOnly
= false)
167 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
169 TaxonNameBase synonymName
= synonym
.getName();
170 synonymName
.removeTaxonBase(synonym
);
171 TaxonNameBase taxonName
= acceptedTaxon
.getName();
172 taxonName
.removeTaxonBase(acceptedTaxon
);
174 synonym
.setName(taxonName
);
175 acceptedTaxon
.setName(synonymName
);
177 // the accepted taxon needs a new uuid because the concept has changed
178 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
179 //acceptedTaxon.setUuid(UUID.randomUUID());
184 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
186 //TODO correct delete handling still needs to be implemented / checked
188 @Transactional(readOnly
= false)
189 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
, boolean deleteSynonym
, boolean copyCitationInfo
, Reference citation
, String microCitation
) throws IllegalArgumentException
{
191 TaxonNameBase
<?
,?
> acceptedName
= acceptedTaxon
.getName();
192 TaxonNameBase
<?
,?
> synonymName
= synonym
.getName();
193 HomotypicalGroup synonymHomotypicGroup
= synonymName
.getHomotypicalGroup();
195 //check synonym is not homotypic
196 if (acceptedName
.getHomotypicalGroup().equals(synonymHomotypicGroup
)){
197 String message
= "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";
198 throw new IllegalArgumentException(message
);
201 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonymName
, acceptedTaxon
.getSec());
203 SynonymRelationshipType relTypeForGroup
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
204 List
<Synonym
> heteroSynonyms
= acceptedTaxon
.getSynonymsInGroup(synonymHomotypicGroup
);
206 for (Synonym heteroSynonym
: heteroSynonyms
){
207 if (synonym
.equals(heteroSynonym
)){
208 acceptedTaxon
.removeSynonym(heteroSynonym
, false);
210 //move synonyms in same homotypic group to new accepted taxon
211 heteroSynonym
.replaceAcceptedTaxon(newAcceptedTaxon
, relTypeForGroup
, copyCitationInfo
, citation
, microCitation
);
215 //synonym.getName().removeTaxonBase(synonym);
216 //TODO correct delete handling still needs to be implemented / checked
218 // deleteSynonym(synonym, taxon, false);
221 this.delete(synonym
);
223 } catch (Exception e
) {
224 logger
.info("Can't delete old synonym from database");
228 return newAcceptedTaxon
;
232 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, Reference citation
, String microcitation
){
234 // Get name from synonym
235 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
237 // remove synonym from taxon
238 toTaxon
.removeSynonym(synonym
);
240 // Create a taxon with synonym name
241 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
243 // Add taxon relation
244 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
246 // since we are swapping names, we have to detach the name from the synonym completely.
247 // Otherwise the synonym will still be in the list of typified names.
248 synonym
.getName().removeTaxonBase(synonym
);
255 * @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)
257 @Transactional(readOnly
= false)
259 public void changeHomotypicalGroupOfSynonym(Synonym synonym
, HomotypicalGroup newHomotypicalGroup
, Taxon targetTaxon
,
260 boolean removeFromOtherTaxa
, boolean setBasionymRelationIfApplicable
){
262 TaxonNameBase synonymName
= synonym
.getName();
263 HomotypicalGroup oldHomotypicalGroup
= synonymName
.getHomotypicalGroup();
267 oldHomotypicalGroup
.removeTypifiedName(synonymName
);
268 newHomotypicalGroup
.addTypifiedName(synonymName
);
270 //remove existing basionym relationships
271 synonymName
.removeBasionyms();
273 //add basionym relationship
274 if (setBasionymRelationIfApplicable
){
275 Set
<TaxonNameBase
> basionyms
= newHomotypicalGroup
.getBasionyms();
276 for (TaxonNameBase basionym
: basionyms
){
277 synonymName
.addBasionym(basionym
);
281 //set synonym relationship correctly
282 // SynonymRelationship relToTaxon = null;
283 boolean relToTargetTaxonExists
= false;
284 Set
<SynonymRelationship
> existingRelations
= synonym
.getSynonymRelations();
285 for (SynonymRelationship rel
: existingRelations
){
286 Taxon acceptedTaxon
= rel
.getAcceptedTaxon();
287 boolean isTargetTaxon
= acceptedTaxon
!= null && acceptedTaxon
.equals(targetTaxon
);
288 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
289 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
290 SynonymRelationshipType newRelationType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
291 rel
.setType(newRelationType
);
292 //TODO handle citation and microCitation
295 relToTargetTaxonExists
= true;
297 if (removeFromOtherTaxa
){
298 acceptedTaxon
.removeSynonym(synonym
, false);
304 if (targetTaxon
!= null && ! relToTargetTaxonExists
){
305 Taxon acceptedTaxon
= targetTaxon
;
306 HomotypicalGroup acceptedGroup
= acceptedTaxon
.getHomotypicGroup();
307 boolean isHomotypicToTaxon
= acceptedGroup
.equals(newHomotypicalGroup
);
308 SynonymRelationshipType relType
= isHomotypicToTaxon? SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
309 //TODO handle citation and microCitation
310 Reference citation
= null;
311 String microCitation
= null;
312 acceptedTaxon
.addSynonym(synonym
, relType
, citation
, microCitation
);
319 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
322 public void updateTitleCache(Class
<?
extends TaxonBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<TaxonBase
> cacheStrategy
, IProgressMonitor monitor
) {
324 clazz
= TaxonBase
.class;
326 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
330 protected void setDao(ITaxonDao dao
) {
335 * @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)
337 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
338 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
340 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
341 if(numberOfResults
> 0) { // no point checking again
342 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
345 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
349 * @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)
351 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
352 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
354 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
355 if(numberOfResults
> 0) { // no point checking again
356 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
363 * @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)
365 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
366 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
368 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
369 if(numberOfResults
> 0) { // no point checking again
370 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
376 * @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)
378 public Pager
<TaxonRelationship
> pageToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
379 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
381 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
382 if(numberOfResults
> 0) { // no point checking again
383 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
385 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
389 * @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)
391 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
392 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
394 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
395 if(numberOfResults
> 0) { // no point checking again
396 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
402 * @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)
404 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
405 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
407 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
408 if(numberOfResults
> 0) { // no point checking again
409 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
411 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
415 * @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)
417 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
418 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
420 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
421 if(numberOfResults
> 0) { // no point checking again
422 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
425 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
429 * @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)
431 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
432 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
434 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
435 if(numberOfResults
> 0) { // no point checking again
436 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
439 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
443 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
445 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
446 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
447 return t
.getHomotypicSynonymsByHomotypicGroup();
451 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
453 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
454 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
455 List
<HomotypicalGroup
> homotypicalGroups
= t
.getHeterotypicSynonymyGroups();
456 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(homotypicalGroups
.size());
457 for(HomotypicalGroup homotypicalGroup
: homotypicalGroups
){
458 heterotypicSynonymyGroups
.add(t
.getSynonymsInGroup(homotypicalGroup
));
460 return heterotypicSynonymyGroups
;
463 public List
<UuidAndTitleCache
<TaxonBase
>> findTaxaAndNamesForEditor(ITaxonServiceConfigurator configurator
){
465 List
<UuidAndTitleCache
<TaxonBase
>> result
= new ArrayList
<UuidAndTitleCache
<TaxonBase
>>();
466 Class
<?
extends TaxonBase
> clazz
= null;
467 if ((configurator
.isDoTaxa() && configurator
.isDoSynonyms())) {
468 clazz
= TaxonBase
.class;
469 //propertyPath.addAll(configurator.getTaxonPropertyPath());
470 //propertyPath.addAll(configurator.getSynonymPropertyPath());
471 } else if(configurator
.isDoTaxa()) {
473 //propertyPath = configurator.getTaxonPropertyPath();
474 } else if (configurator
.isDoSynonyms()) {
475 clazz
= Synonym
.class;
476 //propertyPath = configurator.getSynonymPropertyPath();
480 result
= dao
.getTaxaByNameForEditor(clazz
, configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
485 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
487 public Pager
<IdentifiableEntity
> findTaxaAndNames(ITaxonServiceConfigurator configurator
) {
489 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
490 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
491 List
<TaxonBase
> taxa
= null;
494 long numberTaxaResults
= 0L;
496 Class
<?
extends TaxonBase
> clazz
= null;
497 List
<String
> propertyPath
= new ArrayList
<String
>();
498 if(configurator
.getTaxonPropertyPath() != null){
499 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
501 if ((configurator
.isDoTaxa() && configurator
.isDoSynonyms())) {
502 clazz
= TaxonBase
.class;
503 //propertyPath.addAll(configurator.getTaxonPropertyPath());
504 //propertyPath.addAll(configurator.getSynonymPropertyPath());
505 } else if(configurator
.isDoTaxa()) {
507 //propertyPath = configurator.getTaxonPropertyPath();
508 } else if (configurator
.isDoSynonyms()) {
509 clazz
= Synonym
.class;
510 //propertyPath = configurator.getSynonymPropertyPath();
514 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
516 dao
.countTaxaByName(clazz
,
517 configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(),
518 configurator
.getNamedAreas());
521 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
522 taxa
= dao
.getTaxaByName(clazz
,
523 configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(),
524 configurator
.getNamedAreas(), configurator
.getPageSize(),
525 configurator
.getPageNumber(), propertyPath
);
529 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
532 results
.addAll(taxa
);
535 numberOfResults
+= numberTaxaResults
;
537 // Names without taxa
538 if (configurator
.isDoNamesWithoutTaxa()) {
539 int numberNameResults
= 0;
541 List
<?
extends TaxonNameBase
<?
,?
>> names
=
542 nameDao
.findByName(configurator
.getTitleSearchStringSqlized(), configurator
.getMatchMode(),
543 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
544 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
545 if (names
.size() > 0) {
546 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
547 if (taxonName
.getTaxonBases().size() == 0) {
548 results
.add(taxonName
);
552 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
553 numberOfResults
+= numberNameResults
;
557 // Taxa from common names
559 if (configurator
.isDoTaxaByCommonNames()) {
561 numberTaxaResults
= 0;
562 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
563 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas());
565 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
566 taxa
= dao
.getTaxaByCommonName(configurator
.getTitleSearchStringSqlized(), configurator
.getClassification(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
569 results
.addAll(taxa
);
571 numberOfResults
+= numberTaxaResults
;
575 return new DefaultPagerImpl
<IdentifiableEntity
>
576 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
579 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
580 return dao
.getUuidAndTitleCache();
584 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])
586 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
587 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
588 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
589 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
590 for (TaxonDescription taxDesc
: descriptions
){
591 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
592 for (DescriptionElementBase descElem
: elements
){
593 for(Media media
: descElem
.getMedia()){
595 //find the best matching representation
596 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, null, size
, height
, widthOrDuration
, mimeTypes
));
605 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)
607 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
608 return this.dao
.findById(listOfIDs
);
612 * @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()
614 public int countAllRelationships() {
615 return this.dao
.countAllRelationships();
619 * @see eu.etaxonomy.cdm.api.service.ITaxonService#createAllInferredSynonyms(eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.model.taxon.Taxon)
621 public List
<Synonym
> createAllInferredSynonyms(Classification tree
,
624 return this.dao
.createAllInferredSynonyms(taxon
, tree
);
628 * @see eu.etaxonomy.cdm.api.service.ITaxonService#createInferredSynonyms(eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType)
630 public List
<Synonym
> createInferredSynonyms(Classification tree
, Taxon taxon
, SynonymRelationshipType type
) {
632 return this.dao
.createInferredSynonyms(taxon
, tree
, type
);
636 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)
638 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
640 return this.dao
.findIdenticalTaxonNames(propertyPath
);
645 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Synonym, boolean)
648 @Transactional(readOnly
= false)
650 public void deleteSynonym(Synonym synonym
, Taxon taxon
, boolean removeNameIfPossible
) {
651 //remove synonymRelationship
652 Set
<Taxon
> taxonSet
= new HashSet
<Taxon
>();
656 taxonSet
.addAll(synonym
.getAcceptedTaxa());
658 Set
<SynonymRelationship
> synRels
= synonym
.getSynonymRelations();
659 for (Taxon taxon2
: taxonSet
){
660 dao
.deleteSynonymRelationships(synonym
, taxon2
);
663 //TODO remove name from homotypical group?
665 //remove synonym (if necessary)
666 if (synonym
.getSynonymRelations().isEmpty()){
670 if (removeNameIfPossible
){
671 TaxonNameBase name
= synonym
.getName();
672 nameService
.delete(name
);
676 //descriptionElementSource
683 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)
685 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
687 return this.dao
.findIdenticalNamesNew(propertyPath
);
691 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
693 public String
getPhylumName(TaxonNameBase name
){
694 return this.dao
.getPhylumName(name
);
698 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)
700 public long deleteSynonymRelationships(Synonym syn
) {
701 return dao
.deleteSynonymRelationships(syn
, null);
706 * @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)
708 public List
<SynonymRelationship
> listSynonymRelationships(
709 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
710 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
711 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
713 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
714 if(numberOfResults
> 0) { // no point checking again
715 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
721 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingTaxon(java.lang.String)
724 public Taxon
findBestMatchingTaxon(String taxonName
) {
725 MatchingTaxonConfigurator config
= MatchingTaxonConfigurator
.NewInstance();
726 config
.setTaxonNameTitle(taxonName
);
727 return findBestMatchingTaxon(config
);
733 public Taxon
findBestMatchingTaxon(MatchingTaxonConfigurator config
) {
735 Taxon bestCandidate
= null;
737 // 1. search for acceptet taxa
738 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(Taxon
.class, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
739 boolean bestCandidateMatchesSecUuid
= false;
740 boolean bestCandidateIsInClassification
= false;
741 int countEqualCandidates
= 0;
742 for(TaxonBase taxonBaseCandidate
: taxonList
){
743 if(taxonBaseCandidate
instanceof Taxon
){
744 Taxon newCanditate
= CdmBase
.deproxy(taxonBaseCandidate
, Taxon
.class);
745 boolean newCandidateMatchesSecUuid
= isMatchesSecUuid(newCanditate
, config
);
746 if (! newCandidateMatchesSecUuid
&& config
.isOnlyMatchingSecUuid() ){
748 }else if(newCandidateMatchesSecUuid
&& ! bestCandidateMatchesSecUuid
){
749 bestCandidate
= newCanditate
;
750 countEqualCandidates
= 1;
751 bestCandidateMatchesSecUuid
= true;
755 boolean newCandidateInClassification
= isInClassification(newCanditate
, config
);
756 if (! newCandidateInClassification
&& config
.isOnlyMatchingClassificationUuid()){
758 }else if (newCandidateInClassification
&& ! bestCandidateIsInClassification
){
759 bestCandidate
= newCanditate
;
760 countEqualCandidates
= 1;
761 bestCandidateIsInClassification
= true;
764 if (bestCandidate
== null){
765 bestCandidate
= newCanditate
;
766 countEqualCandidates
= 1;
770 }else{ //not Taxon.class
773 countEqualCandidates
++;
776 if (bestCandidate
!= null){
777 if(countEqualCandidates
> 1){
778 logger
.info(countEqualCandidates
+ " equally matching TaxonBases found, using first accepted Taxon: " + bestCandidate
.getTitleCache());
779 return bestCandidate
;
781 logger
.info("using accepted Taxon: " + bestCandidate
.getTitleCache());
782 return bestCandidate
;
787 // 2. search for synonyms
788 if (config
.isIncludeSynonyms()){
789 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(Synonym
.class, config
.getTaxonNameTitle(), null, MatchMode
.EXACT
, null, 0, null, null);
790 for(TaxonBase taxonBase
: synonymList
){
791 if(taxonBase
instanceof Synonym
){
792 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
793 Set
<Taxon
> acceptetdCandidates
= synonym
.getAcceptedTaxa();
794 if(!acceptetdCandidates
.isEmpty()){
795 bestCandidate
= acceptetdCandidates
.iterator().next();
796 if(acceptetdCandidates
.size() == 1){
797 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + bestCandidate
.getTitleCache());
798 return bestCandidate
;
800 logger
.info("using accepted Taxon " + bestCandidate
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
801 return bestCandidate
;
803 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
809 } catch (Exception e
){
813 return bestCandidate
;
816 private boolean isInClassification(Taxon taxon
, MatchingTaxonConfigurator config
) {
817 UUID configClassificationUuid
= config
.getClassificationUuid();
818 if (configClassificationUuid
== null){
821 for (TaxonNode node
: taxon
.getTaxonNodes()){
822 UUID classUuid
= node
.getClassification().getUuid();
823 if (configClassificationUuid
.equals(classUuid
)){
830 private boolean isMatchesSecUuid(Taxon taxon
, MatchingTaxonConfigurator config
) {
831 UUID configSecUuid
= config
.getSecUuid();
832 if (configSecUuid
== null){
835 UUID taxonSecUuid
= (taxon
.getSec() == null)?
null : taxon
.getSec().getUuid();
836 return configSecUuid
.equals(taxonSecUuid
);
840 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
843 public Synonym
findBestMatchingSynonym(String taxonName
) {
844 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(Synonym
.class, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
845 if(! synonymList
.isEmpty()){
846 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
847 if(synonymList
.size() == 1){
848 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
851 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());
859 * @see eu.etaxonomy.cdm.api.service.ITaxonService#moveSynonymToAnotherTaxon(eu.etaxonomy.cdm.model.taxon.SynonymRelationship, eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.reference.Reference, java.lang.String)
862 public Taxon
moveSynonymToAnotherTaxon(SynonymRelationship synonymRelation
,
863 Taxon toTaxon
, SynonymRelationshipType synonymRelationshipType
, Reference reference
, String referenceDetail
) {
864 Taxon fromTaxon
= synonymRelation
.getAcceptedTaxon();
866 toTaxon
.addSynonym(synonymRelation
.getSynonym(), synonymRelationshipType
, reference
, referenceDetail
);
868 fromTaxon
.removeSynonymRelation(synonymRelation
);
874 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
877 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheTaxon() {
878 return dao
.getUuidAndTitleCacheTaxon();
882 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
885 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCacheSynonym() {
886 return dao
.getUuidAndTitleCacheSynonym();