include trunk
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TaxonServiceImpl.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
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.
9 */
10
11 package eu.etaxonomy.cdm.api.service;
12
13 import java.util.ArrayList;
14 import java.util.Comparator;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.UUID;
19
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;
25
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;
66
67
68 /**
69 * @author a.kohlbecker
70 * @date 10.09.2010
71 *
72 */
73 @Service
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);
77
78 @Autowired
79 private ITaxonNameDao nameDao;
80
81 @Autowired
82 private IDescriptionDao descriptionDao;
83
84 @Autowired
85 private IOrderedTermVocabularyDao orderedVocabularyDao;
86
87 /**
88 * Constructor
89 */
90 public TaxonServiceImpl(){
91 if (logger.isDebugEnabled()) { logger.debug("Load TaxonService Bean"); }
92 }
93
94 /**
95 * FIXME Candidate for harmonization
96 * rename searchByName ?
97 */
98 public List<TaxonBase> searchTaxaByName(String name, ReferenceBase sec) {
99 return dao.getTaxaByName(name, sec);
100 }
101
102 /**
103 * FIXME Candidate for harmonization
104 * list(Synonym.class, ...)
105 * (non-Javadoc)
106 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
107 */
108 public List<Synonym> getAllSynonyms(int limit, int start) {
109 return dao.getAllSynonyms(limit, start);
110 }
111
112 /**
113 * FIXME Candidate for harmonization
114 * list(Taxon.class, ...)
115 * (non-Javadoc)
116 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
117 */
118 public List<Taxon> getAllTaxa(int limit, int start) {
119 return dao.getAllTaxa(limit, start);
120 }
121
122
123 /**
124 * FIXME Candidate for harmonization
125 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
126 * (non-Javadoc)
127 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
128 */
129 public List<Taxon> getRootTaxa(ReferenceBase sec){
130 return getRootTaxa(sec, CdmFetch.FETCH_CHILDTAXA(), true);
131 }
132
133 /**
134 * FIXME Candidate for harmonization
135 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
136 * (non-Javadoc)
137 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean)
138 */
139 public List<Taxon> getRootTaxa(ReferenceBase sec, CdmFetch cdmFetch, boolean onlyWithChildren) {
140 if (cdmFetch == null){
141 cdmFetch = CdmFetch.NO_FETCH();
142 }
143 return dao.getRootTaxa(sec, cdmFetch, onlyWithChildren, false);
144 }
145
146 /**
147 * FIXME Candidate for harmonization
148 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
149 * (non-Javadoc)
150 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
151 */
152 public List<Taxon> getRootTaxa(ReferenceBase sec, boolean onlyWithChildren,
153 boolean withMisapplications) {
154 return dao.getRootTaxa(sec, null, onlyWithChildren, withMisapplications);
155 }
156
157 /* (non-Javadoc)
158 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
159 */
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);
163 }
164
165 public List<RelationshipBase> getAllRelationships(int limit, int start){
166 return dao.getAllRelationships(limit, start);
167 }
168
169 /**
170 * FIXME Candidate for harmonization
171 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
172 */
173 @Deprecated
174 public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypeVocabulary() {
175
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;
181 }
182
183 /* (non-Javadoc)
184 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeTaxonSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Taxon)
185 */
186 @Transactional(readOnly = false)
187 public Synonym changeAcceptedTaxonToSynonym(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, ReferenceBase citation, String citationMicroReference) {
188
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.");
193 }
194
195 if(oldTaxonNode.equals(newAcceptedTaxonNode)){
196 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
197 }
198
199 Taxon oldTaxon = (Taxon) HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
200 Taxon newAcceptedTaxon = (Taxon) HibernateProxyHelper.deproxy(newAcceptedTaxonNode.getTaxon());
201
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();
207 }else{
208 synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
209 }
210 }
211 SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName, synonymRelationshipType, citation, citationMicroReference);
212
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());
217 }
218
219
220 // CHILD NODES
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());
224 }
225 }
226
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());
235
236 }else if(toTaxon == oldTaxon){
237 taxonRelationship.getFromTaxon().addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
238 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
239
240 }else{
241 logger.warn("Taxon is not part of its own Taxonrelationship");
242 }
243 // Remove old relationships
244 taxonRelationship.setToTaxon(null);
245 taxonRelationship.setFromTaxon(null);
246 }
247
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);
252 }
253
254 oldTaxonNode.delete();
255
256 return synonmyRelationship.getSynonym();
257 }
258
259 /*
260 * (non-Javadoc)
261 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
262 */
263 @Transactional(readOnly = false)
264 public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){
265
266 TaxonNameBase synonymName = synonym.getName();
267 synonymName.removeTaxonBase(synonym);
268 TaxonNameBase taxonName = acceptedTaxon.getName();
269 taxonName.removeTaxonBase(acceptedTaxon);
270
271 synonym.setName(taxonName);
272 acceptedTaxon.setName(synonymName);
273
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());
277 }
278
279
280 /*
281 * (non-Javadoc)
282 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeSynonymAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
283 */
284 public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){
285
286 Taxon newAcceptedTaxon = Taxon.NewInstance(synonym.getName(), acceptedTaxon.getSec());
287
288 acceptedTaxon.removeSynonym(synonym);
289
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);
293
294 return newAcceptedTaxon;
295 }
296
297 public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, ReferenceBase citation, String microcitation){
298
299 // Get name from synonym
300 TaxonNameBase<?, ?> synonymName = synonym.getName();
301
302 // remove synonym from taxon
303 toTaxon.removeSynonym(synonym);
304
305 // Create a taxon with synonym name
306 Taxon fromTaxon = Taxon.NewInstance(synonymName, null);
307
308 // Add taxon relation
309 fromTaxon.addTaxonRelation(toTaxon, taxonRelationshipType, citation, microcitation);
310
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);
314
315 return fromTaxon;
316 }
317
318 /* (non-Javadoc)
319 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache()
320 */
321 @Override
322 @Transactional(readOnly = false)
323 public void updateTitleCache() {
324 Class<TaxonBase> clazz = TaxonBase.class;
325 super.updateTitleCache(clazz, null, null);
326 }
327
328 @Autowired
329 protected void setDao(ITaxonDao dao) {
330 this.dao = dao;
331 }
332
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);
335
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);
339 }
340
341 return new DefaultPagerImpl<TaxonBase>(pageNumber, numberOfResults, pageSize, results);
342 }
343
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);
346
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);
350 }
351
352 return results;
353 }
354
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);
357
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);
361 }
362 return results;
363 }
364
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);
367
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);
371 }
372 return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
373 }
374
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);
377
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);
381 }
382 return results;
383 }
384
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);
387
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);
391 }
392 return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
393 }
394
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);
397
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);
401 }
402
403 return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
404 }
405
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);
408
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);
412 }
413
414 return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
415 }
416
417 public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){
418 Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);
419 return t.getHomotypicSynonymsByHomotypicGroup();
420 }
421
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()));
428 }
429 return heterotypicSynonymyGroups;
430 }
431
432 /* (non-Javadoc)
433 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
434 */
435 public Pager<IdentifiableEntity> findTaxaAndNames(ITaxonServiceConfigurator configurator) {
436
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;
440
441 // Taxa and synonyms
442 long numberTaxaResults = 0L;
443
444 Class<? extends TaxonBase> clazz = null;
445 List<String> propertyPath = new ArrayList<String>();
446 if(configurator.getTaxonPropertyPath() != null){
447 propertyPath.addAll(configurator.getTaxonPropertyPath());
448 }
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()) {
454 clazz = Taxon.class;
455 //propertyPath = configurator.getTaxonPropertyPath();
456 } else if (configurator.isDoSynonyms()) {
457 clazz = Synonym.class;
458 //propertyPath = configurator.getSynonymPropertyPath();
459 }
460
461 if(clazz != null){
462 if(configurator.getPageSize() != null){ // no point counting if we need all anyway
463 numberTaxaResults =
464 dao.countTaxaByName(clazz,
465 configurator.getSearchString(), configurator.getTaxonomicTree(), configurator.getMatchMode(),
466 configurator.getNamedAreas());
467 }
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);
473 }
474 }
475
476 if (logger.isDebugEnabled()) { logger.debug(numberTaxaResults + " matching taxa counted"); }
477
478 if(taxa != null){
479 results.addAll(taxa);
480 }
481
482 numberOfResults += numberTaxaResults;
483
484 // Names without taxa
485 if (configurator.isDoNamesWithoutTaxa()) {
486 int numberNameResults = 0;
487
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);
496 numberNameResults++;
497 }
498 }
499 if (logger.isDebugEnabled()) { logger.debug(numberNameResults + " matching name(s) without taxa found"); }
500 numberOfResults += numberNameResults;
501 }
502 }
503
504 // Taxa from common names
505
506 if (configurator.isDoTaxaByCommonNames()) {
507 taxa = null;
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());
511 }
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());
514 }
515 if(taxa != null){
516 results.addAll(taxa);
517 }
518 numberOfResults += numberTaxaResults;
519
520 }
521
522 return new DefaultPagerImpl<IdentifiableEntity>
523 (configurator.getPageNumber(), numberOfResults, configurator.getPageSize(), results);
524 }
525
526 public List<UuidAndTitleCache<TaxonBase>> getTaxonUuidAndTitleCache(){
527 return dao.getUuidAndTitleCache();
528 }
529
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()){
538
539 //find the best matching representation
540 medRep.add(MediaUtils.findBestMatchingRepresentation(media, size, height, widthOrDuration, mimeTypes));
541
542 }
543 }
544 }
545 return medRep;
546 }
547
548 public List<TaxonBase> findTaxaByID(Set<Integer> listOfIDs) {
549 return this.dao.findById(listOfIDs);
550 }
551
552 public int countAllRelationships() {
553 return this.dao.countAllRelationships();
554 }
555
556 public List<Synonym> createAllInferredSynonyms(TaxonomicTree tree,
557 Taxon taxon) {
558
559 return this.dao.createAllInferredSynonyms(taxon, tree);
560 }
561
562 public List<Synonym> createInferredSynonyms(TaxonomicTree tree, Taxon taxon, SynonymRelationshipType type) {
563
564 return this.dao.createInferredSynonyms(taxon, tree, type);
565 }
566
567 public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {
568
569 return this.dao.findIdenticalTaxonNames(propertyPath);
570 }
571
572 public List<TaxonNameBase> findIdenticalTaxonNameIds(List<String> propertyPath) {
573
574 return this.dao.findIdenticalNamesNew(propertyPath);
575 }
576
577 public String getPhylumName(TaxonNameBase name){
578 return this.dao.getPhylumName(name);
579 }
580
581 private class TaxonAndNameComparator implements Comparator{
582
583 public int compare(Object arg0, Object arg1) {
584 IdentifiableEntity castArg0 = (IdentifiableEntity) arg0;
585 IdentifiableEntity castArg1 = (IdentifiableEntity) arg1;
586 return castArg0.compareTo(castArg1);
587 }
588
589 }
590
591 public long deleteSynonymRelationships(Synonym syn) {
592
593 return dao.deleteSynonymRelationships(syn);
594 }
595
596
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);
601
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);
605 }
606 return results;
607 }
608
609 /* (non-Javadoc)
610 * @see eu.etaxonomy.cdm.api.service.ITaxonService#matchToTaxon(eu.etaxonomy.cdm.model.name.NonViralName)
611 */
612 @Override
613 public Taxon findBestMatchingTaxon(String taxonName) {
614
615 Taxon matchedTaxon = null;
616 try{
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());
624 return matchedTaxon;
625 } else {
626 logger.info("using accepted Taxon: " + matchedTaxon.getTitleCache());
627 return matchedTaxon;
628 }
629 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
630 }
631 }
632
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());
642 return matchedTaxon;
643 } else {
644 logger.info("using accepted Taxon " + matchedTaxon.getTitleCache() + "for synonym " + taxonBase.getTitleCache());
645 return matchedTaxon;
646 }
647 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
648 }
649 }
650 }
651
652 } catch (Exception e){
653 logger.error(e);
654 }
655
656 return matchedTaxon;
657 }
658 }