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
.impl
.TaxonServiceConfiguratorImpl
;
28 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
29 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
30 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
31 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
32 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
33 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
34 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
35 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
36 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
37 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
38 import eu
.etaxonomy
.cdm
.model
.description
.FeatureNode
;
39 import eu
.etaxonomy
.cdm
.model
.description
.FeatureTree
;
40 import eu
.etaxonomy
.cdm
.model
.description
.Scope
;
41 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
42 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
43 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
44 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
45 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
46 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
47 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
48 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
49 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
57 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
58 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonomicTree
;
59 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
60 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionDao
;
61 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
62 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
63 import eu
.etaxonomy
.cdm
.persistence
.fetch
.CdmFetch
;
64 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
65 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
69 * @author a.kohlbecker
74 @Transactional(propagation
= Propagation
.SUPPORTS
, readOnly
= true)
75 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
76 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
79 private ITaxonNameDao nameDao
;
82 private IDescriptionDao descriptionDao
;
85 private IOrderedTermVocabularyDao orderedVocabularyDao
;
90 public TaxonServiceImpl(){
91 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
95 * FIXME Candidate for harmonization
96 * rename searchByName ?
98 public List
<TaxonBase
> searchTaxaByName(String name
, ReferenceBase sec
) {
99 return dao
.getTaxaByName(name
, sec
);
103 * FIXME Candidate for harmonization
104 * list(Synonym.class, ...)
106 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
108 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
109 return dao
.getAllSynonyms(limit
, start
);
113 * FIXME Candidate for harmonization
114 * list(Taxon.class, ...)
116 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
118 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
119 return dao
.getAllTaxa(limit
, start
);
124 * FIXME Candidate for harmonization
125 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
127 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
129 public List
<Taxon
> getRootTaxa(ReferenceBase sec
){
130 return getRootTaxa(sec
, CdmFetch
.FETCH_CHILDTAXA(), true);
134 * FIXME Candidate for harmonization
135 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
137 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean)
139 public List
<Taxon
> getRootTaxa(ReferenceBase sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
140 if (cdmFetch
== null){
141 cdmFetch
= CdmFetch
.NO_FETCH();
143 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
147 * FIXME Candidate for harmonization
148 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
150 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
152 public List
<Taxon
> getRootTaxa(ReferenceBase sec
, boolean onlyWithChildren
,
153 boolean withMisapplications
) {
154 return dao
.getRootTaxa(sec
, null, onlyWithChildren
, withMisapplications
);
158 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
160 public List
<Taxon
> getRootTaxa(Rank rank
, ReferenceBase sec
, boolean onlyWithChildren
,
161 boolean withMisapplications
, List
<String
> propertyPaths
) {
162 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
165 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
166 return dao
.getAllRelationships(limit
, start
);
170 * FIXME Candidate for harmonization
171 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
174 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
176 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
177 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
178 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
179 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
180 return taxonRelTypeVocabulary
;
184 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeTaxonSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Taxon)
186 @Transactional(readOnly
= false)
187 public Synonym
changeAcceptedTaxonToSynonym(TaxonNode oldTaxonNode
, TaxonNode newAcceptedTaxonNode
, SynonymRelationshipType synonymRelationshipType
, ReferenceBase citation
, String citationMicroReference
) {
189 // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
190 // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
191 if (oldTaxonNode
== null || newAcceptedTaxonNode
== null || oldTaxonNode
.getTaxon().getName() == null){
192 throw new IllegalArgumentException("A mandatory parameter was null.");
195 if(oldTaxonNode
.equals(newAcceptedTaxonNode
)){
196 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
199 Taxon oldTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(oldTaxonNode
.getTaxon());
200 Taxon newAcceptedTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(newAcceptedTaxonNode
.getTaxon());
202 // Move oldTaxon to newTaxon
203 TaxonNameBase
<?
,?
> synonymName
= oldTaxon
.getName();
204 if (synonymRelationshipType
== null){
205 if (synonymName
.isHomotypic(newAcceptedTaxon
.getName())){
206 synonymRelationshipType
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
208 synonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
211 SynonymRelationship synonmyRelationship
= newAcceptedTaxon
.addSynonymName(synonymName
, synonymRelationshipType
, citation
, citationMicroReference
);
213 //Move Synonym Relations to new Taxon
214 for(SynonymRelationship synRelation
: oldTaxon
.getSynonymRelations()){
215 newAcceptedTaxon
.addSynonym(synRelation
.getSynonym(), synRelation
.getType(),
216 synRelation
.getCitation(), synRelation
.getCitationMicroReference());
221 if(oldTaxonNode
.getChildNodes() != null && oldTaxonNode
.getChildNodes().size() != 0){
222 for(TaxonNode childNode
: oldTaxonNode
.getChildNodes()){
223 newAcceptedTaxonNode
.addChildNode(childNode
, childNode
.getReference(), childNode
.getMicroReference(), childNode
.getSynonymToBeUsed());
227 //Move Taxon RelationShips to new Taxon
228 Set
<TaxonRelationship
> obsoleteTaxonRelationships
= new HashSet
<TaxonRelationship
>();
229 for(TaxonRelationship taxonRelationship
: oldTaxon
.getTaxonRelations()){
230 Taxon fromTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(taxonRelationship
.getFromTaxon());
231 Taxon toTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(taxonRelationship
.getToTaxon());
232 if (fromTaxon
== oldTaxon
){
233 newAcceptedTaxon
.addTaxonRelation(taxonRelationship
.getToTaxon(), taxonRelationship
.getType(),
234 taxonRelationship
.getCitation(), taxonRelationship
.getCitationMicroReference());
236 }else if(toTaxon
== oldTaxon
){
237 taxonRelationship
.getFromTaxon().addTaxonRelation(newAcceptedTaxon
, taxonRelationship
.getType(),
238 taxonRelationship
.getCitation(), taxonRelationship
.getCitationMicroReference());
241 logger
.warn("Taxon is not part of its own Taxonrelationship");
243 // Remove old relationships
244 taxonRelationship
.setToTaxon(null);
245 taxonRelationship
.setFromTaxon(null);
248 //Move descriptions to new taxon
249 for(TaxonDescription description
: oldTaxon
.getDescriptions()){
250 description
.setTitleCache("Description copied from former accepted taxon: " + oldTaxon
.getTitleCache() + "(Old title: " + description
.getTitleCache() + ")");
251 newAcceptedTaxon
.addDescription(description
);
254 oldTaxonNode
.delete();
256 return synonmyRelationship
.getSynonym();
261 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
263 @Transactional(readOnly
= false)
264 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
266 TaxonNameBase synonymName
= synonym
.getName();
267 synonymName
.removeTaxonBase(synonym
);
268 TaxonNameBase taxonName
= acceptedTaxon
.getName();
269 taxonName
.removeTaxonBase(acceptedTaxon
);
271 synonym
.setName(taxonName
);
272 acceptedTaxon
.setName(synonymName
);
274 // the accepted taxon needs a new uuid because the concept has changed
275 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
276 //acceptedTaxon.setUuid(UUID.randomUUID());
282 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeSynonymAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
284 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
286 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonym
.getName(), acceptedTaxon
.getSec());
288 acceptedTaxon
.removeSynonym(synonym
);
290 // since we are swapping names, we have to detach the name from the synonym completely.
291 // Otherwise the synonym will still be in the list of typified names.
292 synonym
.getName().removeTaxonBase(synonym
);
294 return newAcceptedTaxon
;
297 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, ReferenceBase citation
, String microcitation
){
299 // Get name from synonym
300 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
302 // remove synonym from taxon
303 toTaxon
.removeSynonym(synonym
);
305 // Create a taxon with synonym name
306 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
308 // Add taxon relation
309 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
311 // since we are swapping names, we have to detach the name from the synonym completely.
312 // Otherwise the synonym will still be in the list of typified names.
313 synonym
.getName().removeTaxonBase(synonym
);
319 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache()
322 @Transactional(readOnly
= false)
323 public void updateTitleCache() {
324 Class
<TaxonBase
> clazz
= TaxonBase
.class;
325 super.updateTitleCache(clazz
, null, null);
329 protected void setDao(ITaxonDao dao
) {
333 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
334 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
336 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
337 if(numberOfResults
> 0) { // no point checking again
338 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
341 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
344 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
345 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
347 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
348 if(numberOfResults
> 0) { // no point checking again
349 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
355 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
356 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
358 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
359 if(numberOfResults
> 0) { // no point checking again
360 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
365 public Pager
<TaxonRelationship
> pageToTaxonRelationships(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
);
372 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
375 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
376 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
378 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
379 if(numberOfResults
> 0) { // no point checking again
380 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
385 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
386 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
388 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
389 if(numberOfResults
> 0) { // no point checking again
390 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
392 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
395 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
396 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
398 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
399 if(numberOfResults
> 0) { // no point checking again
400 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
403 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
406 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
407 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
409 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
410 if(numberOfResults
> 0) { // no point checking again
411 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
414 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
417 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
418 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
419 return t
.getHomotypicSynonymsByHomotypicGroup();
422 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
423 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
424 List
<HomotypicalGroup
> hsgl
= t
.getHeterotypicSynonymyGroups();
425 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(hsgl
.size());
426 for(HomotypicalGroup hsg
: hsgl
){
427 heterotypicSynonymyGroups
.add(hsg
.getSynonymsInGroup(t
.getSec()));
429 return heterotypicSynonymyGroups
;
433 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
435 public Pager
<IdentifiableEntity
> findTaxaAndNames(ITaxonServiceConfigurator configurator
) {
437 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
438 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
439 List
<TaxonBase
> taxa
= null;
442 long numberTaxaResults
= 0L;
444 Class
<?
extends TaxonBase
> clazz
= null;
445 List
<String
> propertyPath
= new ArrayList
<String
>();
446 if(configurator
.getTaxonPropertyPath() != null){
447 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
449 if ((configurator
.isDoTaxa() && configurator
.isDoSynonyms())) {
450 clazz
= TaxonBase
.class;
451 //propertyPath.addAll(configurator.getTaxonPropertyPath());
452 //propertyPath.addAll(configurator.getSynonymPropertyPath());
453 } else if(configurator
.isDoTaxa()) {
455 //propertyPath = configurator.getTaxonPropertyPath();
456 } else if (configurator
.isDoSynonyms()) {
457 clazz
= Synonym
.class;
458 //propertyPath = configurator.getSynonymPropertyPath();
462 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
464 dao
.countTaxaByName(clazz
,
465 configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(),
466 configurator
.getNamedAreas());
468 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
469 taxa
= dao
.getTaxaByName(clazz
,
470 configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(),
471 configurator
.getNamedAreas(), configurator
.getPageSize(),
472 configurator
.getPageNumber(), propertyPath
);
476 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
479 results
.addAll(taxa
);
482 numberOfResults
+= numberTaxaResults
;
484 // Names without taxa
485 if (configurator
.isDoNamesWithoutTaxa()) {
486 int numberNameResults
= 0;
488 List
<?
extends TaxonNameBase
<?
,?
>> names
=
489 nameDao
.findByName(configurator
.getSearchString(), configurator
.getMatchMode(),
490 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
491 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
492 if (names
.size() > 0) {
493 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
494 if (taxonName
.getTaxonBases().size() == 0) {
495 results
.add(taxonName
);
499 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
500 numberOfResults
+= numberNameResults
;
504 // Taxa from common names
506 if (configurator
.isDoTaxaByCommonNames()) {
508 numberTaxaResults
= 0;
509 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
510 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(), configurator
.getNamedAreas());
512 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
513 taxa
= dao
.getTaxaByCommonName(configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
516 results
.addAll(taxa
);
518 numberOfResults
+= numberTaxaResults
;
522 return new DefaultPagerImpl
<IdentifiableEntity
>
523 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
526 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
527 return dao
.getUuidAndTitleCache();
530 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
531 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
532 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
533 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
534 for (TaxonDescription taxDesc
: descriptions
){
535 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
536 for (DescriptionElementBase descElem
: elements
){
537 for(Media media
: descElem
.getMedia()){
539 //find the best matching representation
540 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, size
, height
, widthOrDuration
, mimeTypes
));
548 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
549 return this.dao
.findById(listOfIDs
);
552 public int countAllRelationships() {
553 return this.dao
.countAllRelationships();
556 public List
<Synonym
> createAllInferredSynonyms(TaxonomicTree tree
,
559 return this.dao
.createAllInferredSynonyms(taxon
, tree
);
562 public List
<Synonym
> createInferredSynonyms(TaxonomicTree tree
, Taxon taxon
, SynonymRelationshipType type
) {
564 return this.dao
.createInferredSynonyms(taxon
, tree
, type
);
567 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
569 return this.dao
.findIdenticalTaxonNames(propertyPath
);
572 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
574 return this.dao
.findIdenticalNamesNew(propertyPath
);
577 public String
getPhylumName(TaxonNameBase name
){
578 return this.dao
.getPhylumName(name
);
581 private class TaxonAndNameComparator
implements Comparator
{
583 public int compare(Object arg0
, Object arg1
) {
584 IdentifiableEntity castArg0
= (IdentifiableEntity
) arg0
;
585 IdentifiableEntity castArg1
= (IdentifiableEntity
) arg1
;
586 return castArg0
.compareTo(castArg1
);
591 public long deleteSynonymRelationships(Synonym syn
) {
593 return dao
.deleteSynonymRelationships(syn
);
597 public List
<SynonymRelationship
> listSynonymRelationships(
598 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
599 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
600 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
602 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
603 if(numberOfResults
> 0) { // no point checking again
604 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
610 * @see eu.etaxonomy.cdm.api.service.ITaxonService#matchToTaxon(eu.etaxonomy.cdm.model.name.NonViralName)
613 public Taxon
findBestMatchingTaxon(String taxonName
) {
615 Taxon matchedTaxon
= null;
617 // 1. search for acceptet taxa
618 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(Taxon
.class, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
619 for(IdentifiableEntity taxonBaseCandidate
: taxonList
){
620 if(taxonBaseCandidate
instanceof Taxon
){
621 matchedTaxon
= (Taxon
)taxonBaseCandidate
;
622 if(taxonList
.size() > 1){
623 logger
.info(taxonList
.size() + " TaxonBases found, using first accepted Taxon: " + matchedTaxon
.getTitleCache());
626 logger
.info("using accepted Taxon: " + matchedTaxon
.getTitleCache());
629 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
633 // 2. search for synonyms
634 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(Synonym
.class, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
635 for(IdentifiableEntity taxonBase
: synonymList
){
636 if(taxonBase
instanceof Synonym
){
637 Set
<Taxon
> acceptetdCandidates
= ((Synonym
)taxonBase
).getAcceptedTaxa();
638 if(!acceptetdCandidates
.isEmpty()){
639 matchedTaxon
= acceptetdCandidates
.iterator().next();
640 if(acceptetdCandidates
.size() == 1){
641 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + matchedTaxon
.getTitleCache());
644 logger
.info("using accepted Taxon " + matchedTaxon
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
647 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
652 } catch (Exception e
){