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
.pager
.Pager
;
28 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
29 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
30 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
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
.UuidAndTitleCache
;
35 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
36 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
37 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
38 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
39 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
40 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
41 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
42 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
43 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
44 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
45 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
46 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
47 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
48 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
49 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonomicTree
;
54 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IOrderedTermVocabularyDao
;
55 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionDao
;
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
;
64 * @author a.kohlbecker
69 @Transactional(propagation
= Propagation
.SUPPORTS
, readOnly
= true)
70 public class TaxonServiceImpl
extends IdentifiableServiceBase
<TaxonBase
,ITaxonDao
> implements ITaxonService
{
71 private static final Logger logger
= Logger
.getLogger(TaxonServiceImpl
.class);
74 private ITaxonNameDao nameDao
;
77 private IDescriptionDao descriptionDao
;
80 private IOrderedTermVocabularyDao orderedVocabularyDao
;
85 public TaxonServiceImpl(){
86 if (logger
.isDebugEnabled()) { logger
.debug("Load TaxonService Bean"); }
90 * FIXME Candidate for harmonization
91 * rename searchByName ?
93 public List
<TaxonBase
> searchTaxaByName(String name
, ReferenceBase sec
) {
94 return dao
.getTaxaByName(name
, sec
);
98 * FIXME Candidate for harmonization
99 * list(Synonym.class, ...)
101 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
103 public List
<Synonym
> getAllSynonyms(int limit
, int start
) {
104 return dao
.getAllSynonyms(limit
, start
);
108 * FIXME Candidate for harmonization
109 * list(Taxon.class, ...)
111 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
113 public List
<Taxon
> getAllTaxa(int limit
, int start
) {
114 return dao
.getAllTaxa(limit
, start
);
119 * FIXME Candidate for harmonization
120 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
122 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
124 public List
<Taxon
> getRootTaxa(ReferenceBase sec
){
125 return getRootTaxa(sec
, CdmFetch
.FETCH_CHILDTAXA(), true);
129 * FIXME Candidate for harmonization
130 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
132 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean)
134 public List
<Taxon
> getRootTaxa(ReferenceBase sec
, CdmFetch cdmFetch
, boolean onlyWithChildren
) {
135 if (cdmFetch
== null){
136 cdmFetch
= CdmFetch
.NO_FETCH();
138 return dao
.getRootTaxa(sec
, cdmFetch
, onlyWithChildren
, false);
142 * FIXME Candidate for harmonization
143 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
145 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
147 public List
<Taxon
> getRootTaxa(ReferenceBase sec
, boolean onlyWithChildren
,
148 boolean withMisapplications
) {
149 return dao
.getRootTaxa(sec
, null, onlyWithChildren
, withMisapplications
);
153 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
155 public List
<Taxon
> getRootTaxa(Rank rank
, ReferenceBase sec
, boolean onlyWithChildren
,
156 boolean withMisapplications
, List
<String
> propertyPaths
) {
157 return dao
.getRootTaxa(rank
, sec
, null, onlyWithChildren
, withMisapplications
, propertyPaths
);
160 public List
<RelationshipBase
> getAllRelationships(int limit
, int start
){
161 return dao
.getAllRelationships(limit
, start
);
165 * FIXME Candidate for harmonization
166 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
169 public OrderedTermVocabulary
<TaxonRelationshipType
> getTaxonRelationshipTypeVocabulary() {
171 String taxonRelTypeVocabularyId
= "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
172 UUID uuid
= UUID
.fromString(taxonRelTypeVocabularyId
);
173 OrderedTermVocabulary
<TaxonRelationshipType
> taxonRelTypeVocabulary
=
174 (OrderedTermVocabulary
)orderedVocabularyDao
.findByUuid(uuid
);
175 return taxonRelTypeVocabulary
;
179 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeTaxonSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Taxon)
181 @Transactional(readOnly
= false)
182 public Synonym
changeAcceptedTaxonToSynonym(TaxonNode oldTaxonNode
, TaxonNode newAcceptedTaxonNode
, SynonymRelationshipType synonymRelationshipType
, ReferenceBase citation
, String citationMicroReference
) {
184 // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
185 // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
186 if (oldTaxonNode
== null || newAcceptedTaxonNode
== null || oldTaxonNode
.getTaxon().getName() == null){
187 throw new IllegalArgumentException("A mandatory parameter was null.");
190 if(oldTaxonNode
.equals(newAcceptedTaxonNode
)){
191 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
194 Taxon oldTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(oldTaxonNode
.getTaxon());
195 Taxon newAcceptedTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(newAcceptedTaxonNode
.getTaxon());
197 // Move oldTaxon to newTaxon
198 TaxonNameBase
<?
,?
> synonymName
= oldTaxon
.getName();
199 if (synonymRelationshipType
== null){
200 if (synonymName
.isHomotypic(newAcceptedTaxon
.getName())){
201 synonymRelationshipType
= SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF();
203 synonymRelationshipType
= SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF();
206 SynonymRelationship synonmyRelationship
= newAcceptedTaxon
.addSynonymName(synonymName
, synonymRelationshipType
, citation
, citationMicroReference
);
208 //Move Synonym Relations to new Taxon
209 for(SynonymRelationship synRelation
: oldTaxon
.getSynonymRelations()){
210 newAcceptedTaxon
.addSynonym(synRelation
.getSynonym(), synRelation
.getType(),
211 synRelation
.getCitation(), synRelation
.getCitationMicroReference());
216 if(oldTaxonNode
.getChildNodes() != null && oldTaxonNode
.getChildNodes().size() != 0){
217 for(TaxonNode childNode
: oldTaxonNode
.getChildNodes()){
218 newAcceptedTaxonNode
.addChildNode(childNode
, childNode
.getReference(), childNode
.getMicroReference(), childNode
.getSynonymToBeUsed());
222 //Move Taxon RelationShips to new Taxon
223 Set
<TaxonRelationship
> obsoleteTaxonRelationships
= new HashSet
<TaxonRelationship
>();
224 for(TaxonRelationship taxonRelationship
: oldTaxon
.getTaxonRelations()){
225 Taxon fromTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(taxonRelationship
.getFromTaxon());
226 Taxon toTaxon
= (Taxon
) HibernateProxyHelper
.deproxy(taxonRelationship
.getToTaxon());
227 if (fromTaxon
== oldTaxon
){
228 newAcceptedTaxon
.addTaxonRelation(taxonRelationship
.getToTaxon(), taxonRelationship
.getType(),
229 taxonRelationship
.getCitation(), taxonRelationship
.getCitationMicroReference());
231 }else if(toTaxon
== oldTaxon
){
232 taxonRelationship
.getFromTaxon().addTaxonRelation(newAcceptedTaxon
, taxonRelationship
.getType(),
233 taxonRelationship
.getCitation(), taxonRelationship
.getCitationMicroReference());
236 logger
.warn("Taxon is not part of its own Taxonrelationship");
238 // Remove old relationships
239 taxonRelationship
.setToTaxon(null);
240 taxonRelationship
.setFromTaxon(null);
243 //Move descriptions to new taxon
244 for(TaxonDescription description
: oldTaxon
.getDescriptions()){
245 description
.setTitleCache("Description copied from former accepted taxon: " + oldTaxon
.getTitleCache() + "(Old title: " + description
.getTitleCache() + ")");
246 newAcceptedTaxon
.addDescription(description
);
249 oldTaxonNode
.delete();
251 return synonmyRelationship
.getSynonym();
256 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
258 @Transactional(readOnly
= false)
259 public void swapSynonymAndAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
261 TaxonNameBase synonymName
= synonym
.getName();
262 synonymName
.removeTaxonBase(synonym
);
263 TaxonNameBase taxonName
= acceptedTaxon
.getName();
264 taxonName
.removeTaxonBase(acceptedTaxon
);
266 synonym
.setName(taxonName
);
267 acceptedTaxon
.setName(synonymName
);
269 // the accepted taxon needs a new uuid because the concept has changed
270 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
271 //acceptedTaxon.setUuid(UUID.randomUUID());
277 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeSynonymAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
279 public Taxon
changeSynonymToAcceptedTaxon(Synonym synonym
, Taxon acceptedTaxon
){
281 Taxon newAcceptedTaxon
= Taxon
.NewInstance(synonym
.getName(), acceptedTaxon
.getSec());
283 acceptedTaxon
.removeSynonym(synonym
);
285 // since we are swapping names, we have to detach the name from the synonym completely.
286 // Otherwise the synonym will still be in the list of typified names.
287 synonym
.getName().removeTaxonBase(synonym
);
289 return newAcceptedTaxon
;
292 public Taxon
changeSynonymToRelatedTaxon(Synonym synonym
, Taxon toTaxon
, TaxonRelationshipType taxonRelationshipType
, ReferenceBase citation
, String microcitation
){
294 // Get name from synonym
295 TaxonNameBase
<?
, ?
> synonymName
= synonym
.getName();
297 // remove synonym from taxon
298 toTaxon
.removeSynonym(synonym
);
300 // Create a taxon with synonym name
301 Taxon fromTaxon
= Taxon
.NewInstance(synonymName
, null);
303 // Add taxon relation
304 fromTaxon
.addTaxonRelation(toTaxon
, taxonRelationshipType
, citation
, microcitation
);
306 // since we are swapping names, we have to detach the name from the synonym completely.
307 // Otherwise the synonym will still be in the list of typified names.
308 synonym
.getName().removeTaxonBase(synonym
);
314 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache()
317 @Transactional(readOnly
= false)
318 public void updateTitleCache() {
319 Class
<TaxonBase
> clazz
= TaxonBase
.class;
320 super.updateTitleCache(clazz
, null, null);
324 protected void setDao(ITaxonDao dao
) {
328 public Pager
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
329 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
331 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
332 if(numberOfResults
> 0) { // no point checking again
333 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
336 return new DefaultPagerImpl
<TaxonBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
339 public List
<TaxonBase
> listTaxaByName(Class
<?
extends TaxonBase
> clazz
, String uninomial
, String infragenericEpithet
, String specificEpithet
, String infraspecificEpithet
, Rank rank
, Integer pageSize
,Integer pageNumber
) {
340 Integer numberOfResults
= dao
.countTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
);
342 List
<TaxonBase
> results
= new ArrayList
<TaxonBase
>();
343 if(numberOfResults
> 0) { // no point checking again
344 results
= dao
.findTaxaByName(clazz
, uninomial
, infragenericEpithet
, specificEpithet
, infraspecificEpithet
, rank
, pageSize
, pageNumber
);
350 public List
<TaxonRelationship
> listToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
351 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
353 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
354 if(numberOfResults
> 0) { // no point checking again
355 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
360 public Pager
<TaxonRelationship
> pageToTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
361 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedTo
);
363 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
364 if(numberOfResults
> 0) { // no point checking again
365 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedTo
);
367 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
370 public List
<TaxonRelationship
> listFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
371 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
373 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
374 if(numberOfResults
> 0) { // no point checking again
375 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
380 public Pager
<TaxonRelationship
> pageFromTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
381 Integer numberOfResults
= dao
.countTaxonRelationships(taxon
, type
, TaxonRelationship
.Direction
.relatedFrom
);
383 List
<TaxonRelationship
> results
= new ArrayList
<TaxonRelationship
>();
384 if(numberOfResults
> 0) { // no point checking again
385 results
= dao
.getTaxonRelationships(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, TaxonRelationship
.Direction
.relatedFrom
);
387 return new DefaultPagerImpl
<TaxonRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
390 public Pager
<SynonymRelationship
> getSynonyms(Taxon taxon
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
391 Integer numberOfResults
= dao
.countSynonyms(taxon
, type
);
393 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
394 if(numberOfResults
> 0) { // no point checking again
395 results
= dao
.getSynonyms(taxon
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
398 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
401 public Pager
<SynonymRelationship
> getSynonyms(Synonym synonym
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
402 Integer numberOfResults
= dao
.countSynonyms(synonym
, type
);
404 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
405 if(numberOfResults
> 0) { // no point checking again
406 results
= dao
.getSynonyms(synonym
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
409 return new DefaultPagerImpl
<SynonymRelationship
>(pageNumber
, numberOfResults
, pageSize
, results
);
412 public List
<Synonym
> getHomotypicSynonymsByHomotypicGroup(Taxon taxon
, List
<String
> propertyPaths
){
413 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
414 return t
.getHomotypicSynonymsByHomotypicGroup();
417 public List
<List
<Synonym
>> getHeterotypicSynonymyGroups(Taxon taxon
, List
<String
> propertyPaths
){
418 Taxon t
= (Taxon
)dao
.load(taxon
.getUuid(), propertyPaths
);
419 List
<HomotypicalGroup
> hsgl
= t
.getHeterotypicSynonymyGroups();
420 List
<List
<Synonym
>> heterotypicSynonymyGroups
= new ArrayList
<List
<Synonym
>>(hsgl
.size());
421 for(HomotypicalGroup hsg
: hsgl
){
422 heterotypicSynonymyGroups
.add(hsg
.getSynonymsInGroup(t
.getSec()));
424 return heterotypicSynonymyGroups
;
428 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
430 public Pager
<IdentifiableEntity
> findTaxaAndNames(ITaxonServiceConfigurator configurator
) {
432 List
<IdentifiableEntity
> results
= new ArrayList
<IdentifiableEntity
>();
433 int numberOfResults
= 0; // overall number of results (as opposed to number of results per page)
434 List
<TaxonBase
> taxa
= null;
437 long numberTaxaResults
= 0L;
439 Class
<?
extends TaxonBase
> clazz
= null;
440 List
<String
> propertyPath
= new ArrayList
<String
>();
441 if(configurator
.getTaxonPropertyPath() != null){
442 propertyPath
.addAll(configurator
.getTaxonPropertyPath());
444 if ((configurator
.isDoTaxa() && configurator
.isDoSynonyms())) {
445 clazz
= TaxonBase
.class;
446 //propertyPath.addAll(configurator.getTaxonPropertyPath());
447 //propertyPath.addAll(configurator.getSynonymPropertyPath());
448 } else if(configurator
.isDoTaxa()) {
450 //propertyPath = configurator.getTaxonPropertyPath();
451 } else if (configurator
.isDoSynonyms()) {
452 clazz
= Synonym
.class;
453 //propertyPath = configurator.getSynonymPropertyPath();
457 if(configurator
.getPageSize() != null){ // no point counting if we need all anyway
459 dao
.countTaxaByName(clazz
,
460 configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(),
461 configurator
.getNamedAreas());
463 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){ // no point checking again if less results
464 taxa
= dao
.getTaxaByName(clazz
,
465 configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(),
466 configurator
.getNamedAreas(), configurator
.getPageSize(),
467 configurator
.getPageNumber(), propertyPath
);
471 if (logger
.isDebugEnabled()) { logger
.debug(numberTaxaResults
+ " matching taxa counted"); }
474 results
.addAll(taxa
);
477 numberOfResults
+= numberTaxaResults
;
479 // Names without taxa
480 if (configurator
.isDoNamesWithoutTaxa()) {
481 int numberNameResults
= 0;
483 List
<?
extends TaxonNameBase
<?
,?
>> names
=
484 nameDao
.findByName(configurator
.getSearchString(), configurator
.getMatchMode(),
485 configurator
.getPageSize(), configurator
.getPageNumber(), null, configurator
.getTaxonNamePropertyPath());
486 if (logger
.isDebugEnabled()) { logger
.debug(names
.size() + " matching name(s) found"); }
487 if (names
.size() > 0) {
488 for (TaxonNameBase
<?
,?
> taxonName
: names
) {
489 if (taxonName
.getTaxonBases().size() == 0) {
490 results
.add(taxonName
);
494 if (logger
.isDebugEnabled()) { logger
.debug(numberNameResults
+ " matching name(s) without taxa found"); }
495 numberOfResults
+= numberNameResults
;
499 // Taxa from common names
501 if (configurator
.isDoTaxaByCommonNames()) {
503 numberTaxaResults
= 0;
504 if(configurator
.getPageSize() != null){// no point counting if we need all anyway
505 numberTaxaResults
= dao
.countTaxaByCommonName(configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(), configurator
.getNamedAreas());
507 if(configurator
.getPageSize() == null || numberTaxaResults
> configurator
.getPageSize() * configurator
.getPageNumber()){
508 taxa
= dao
.getTaxaByCommonName(configurator
.getSearchString(), configurator
.getTaxonomicTree(), configurator
.getMatchMode(), configurator
.getNamedAreas(), configurator
.getPageSize(), configurator
.getPageNumber(), configurator
.getTaxonPropertyPath());
511 results
.addAll(taxa
);
513 numberOfResults
+= numberTaxaResults
;
517 return new DefaultPagerImpl
<IdentifiableEntity
>
518 (configurator
.getPageNumber(), numberOfResults
, configurator
.getPageSize(), results
);
521 public List
<UuidAndTitleCache
<TaxonBase
>> getTaxonUuidAndTitleCache(){
522 return dao
.getUuidAndTitleCache();
525 public List
<MediaRepresentation
> getAllMedia(Taxon taxon
, int size
, int height
, int widthOrDuration
, String
[] mimeTypes
){
526 List
<MediaRepresentation
> medRep
= new ArrayList
<MediaRepresentation
>();
527 taxon
= (Taxon
)dao
.load(taxon
.getUuid());
528 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
529 for (TaxonDescription taxDesc
: descriptions
){
530 Set
<DescriptionElementBase
> elements
= taxDesc
.getElements();
531 for (DescriptionElementBase descElem
: elements
){
532 for(Media media
: descElem
.getMedia()){
534 //find the best matching representation
535 medRep
.add(MediaUtils
.findBestMatchingRepresentation(media
, size
, height
, widthOrDuration
, mimeTypes
));
543 public List
<TaxonBase
> findTaxaByID(Set
<Integer
> listOfIDs
) {
544 return this.dao
.findById(listOfIDs
);
547 public int countAllRelationships() {
548 return this.dao
.countAllRelationships();
551 public List
<Synonym
> createAllInferredSynonyms(TaxonomicTree tree
,
554 return this.dao
.createAllInferredSynonyms(taxon
, tree
);
557 public List
<Synonym
> createInferredSynonyms(TaxonomicTree tree
, Taxon taxon
, SynonymRelationshipType type
) {
559 return this.dao
.createInferredSynonyms(taxon
, tree
, type
);
562 public List
<TaxonNameBase
> findIdenticalTaxonNames(List
<String
> propertyPath
) {
564 return this.dao
.findIdenticalTaxonNames(propertyPath
);
567 public List
<TaxonNameBase
> findIdenticalTaxonNameIds(List
<String
> propertyPath
) {
569 return this.dao
.findIdenticalNamesNew(propertyPath
);
572 public String
getPhylumName(TaxonNameBase name
){
573 return this.dao
.getPhylumName(name
);
576 private class TaxonAndNameComparator
implements Comparator
{
578 public int compare(Object arg0
, Object arg1
) {
579 IdentifiableEntity castArg0
= (IdentifiableEntity
) arg0
;
580 IdentifiableEntity castArg1
= (IdentifiableEntity
) arg1
;
581 return castArg0
.compareTo(castArg1
);
586 public long deleteSynonymRelationships(Synonym syn
) {
588 return dao
.deleteSynonymRelationships(syn
);
592 public List
<SynonymRelationship
> listSynonymRelationships(
593 TaxonBase taxonBase
, SynonymRelationshipType type
, Integer pageSize
, Integer pageNumber
,
594 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
, Direction direction
) {
595 Integer numberOfResults
= dao
.countSynonymRelationships(taxonBase
, type
, direction
);
597 List
<SynonymRelationship
> results
= new ArrayList
<SynonymRelationship
>();
598 if(numberOfResults
> 0) { // no point checking again
599 results
= dao
.getSynonymRelationships(taxonBase
, type
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
605 * @see eu.etaxonomy.cdm.api.service.ITaxonService#matchToTaxon(eu.etaxonomy.cdm.model.name.NonViralName)
608 public Taxon
findBestMatchingTaxon(String taxonName
) {
610 Taxon matchedTaxon
= null;
612 // 1. search for acceptet taxa
613 List
<TaxonBase
> taxonList
= dao
.findByNameTitleCache(Taxon
.class, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
614 for(IdentifiableEntity taxonBaseCandidate
: taxonList
){
615 if(taxonBaseCandidate
instanceof Taxon
){
616 matchedTaxon
= (Taxon
)taxonBaseCandidate
;
617 if(taxonList
.size() > 1){
618 logger
.info(taxonList
.size() + " TaxonBases found, using first accepted Taxon: " + matchedTaxon
.getTitleCache());
621 logger
.info("using accepted Taxon: " + matchedTaxon
.getTitleCache());
624 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
628 // 2. search for synonyms
629 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(Synonym
.class, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
630 for(TaxonBase taxonBase
: synonymList
){
631 if(taxonBase
instanceof Synonym
){
632 Set
<Taxon
> acceptetdCandidates
= ((Synonym
)taxonBase
).getAcceptedTaxa();
633 if(!acceptetdCandidates
.isEmpty()){
634 matchedTaxon
= acceptetdCandidates
.iterator().next();
635 if(acceptetdCandidates
.size() == 1){
636 logger
.info(acceptetdCandidates
.size() + " Accepted taxa found for synonym " + taxonBase
.getTitleCache() + ", using first one: " + matchedTaxon
.getTitleCache());
639 logger
.info("using accepted Taxon " + matchedTaxon
.getTitleCache() + "for synonym " + taxonBase
.getTitleCache());
642 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
647 } catch (Exception e
){
655 public Synonym
findBestMatchingSynonym(String taxonName
) {
656 List
<TaxonBase
> synonymList
= dao
.findByNameTitleCache(Synonym
.class, taxonName
, null, MatchMode
.EXACT
, null, 0, null, null);
657 if(! synonymList
.isEmpty()){
658 Synonym result
= CdmBase
.deproxy(synonymList
.iterator().next(), Synonym
.class);
659 if(synonymList
.size() == 1){
660 logger
.info(synonymList
.size() + " Synonym found " + result
.getTitleCache() );
663 logger
.info("Several matching synonyms found. Using first: " + result
.getTitleCache());