Some commenting and cleaning code
[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.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;
61
62
63 /**
64 * @author a.kohlbecker
65 * @date 10.09.2010
66 *
67 */
68 @Service
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);
72
73 @Autowired
74 private ITaxonNameDao nameDao;
75
76 @Autowired
77 private IDescriptionDao descriptionDao;
78
79 @Autowired
80 private IOrderedTermVocabularyDao orderedVocabularyDao;
81
82 /**
83 * Constructor
84 */
85 public TaxonServiceImpl(){
86 if (logger.isDebugEnabled()) { logger.debug("Load TaxonService Bean"); }
87 }
88
89 /**
90 * FIXME Candidate for harmonization
91 * rename searchByName ?
92 */
93 public List<TaxonBase> searchTaxaByName(String name, ReferenceBase sec) {
94 return dao.getTaxaByName(name, sec);
95 }
96
97 /**
98 * FIXME Candidate for harmonization
99 * list(Synonym.class, ...)
100 * (non-Javadoc)
101 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
102 */
103 public List<Synonym> getAllSynonyms(int limit, int start) {
104 return dao.getAllSynonyms(limit, start);
105 }
106
107 /**
108 * FIXME Candidate for harmonization
109 * list(Taxon.class, ...)
110 * (non-Javadoc)
111 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
112 */
113 public List<Taxon> getAllTaxa(int limit, int start) {
114 return dao.getAllTaxa(limit, start);
115 }
116
117
118 /**
119 * FIXME Candidate for harmonization
120 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
121 * (non-Javadoc)
122 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
123 */
124 public List<Taxon> getRootTaxa(ReferenceBase sec){
125 return getRootTaxa(sec, CdmFetch.FETCH_CHILDTAXA(), true);
126 }
127
128 /**
129 * FIXME Candidate for harmonization
130 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
131 * (non-Javadoc)
132 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean)
133 */
134 public List<Taxon> getRootTaxa(ReferenceBase sec, CdmFetch cdmFetch, boolean onlyWithChildren) {
135 if (cdmFetch == null){
136 cdmFetch = CdmFetch.NO_FETCH();
137 }
138 return dao.getRootTaxa(sec, cdmFetch, onlyWithChildren, false);
139 }
140
141 /**
142 * FIXME Candidate for harmonization
143 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
144 * (non-Javadoc)
145 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
146 */
147 public List<Taxon> getRootTaxa(ReferenceBase sec, boolean onlyWithChildren,
148 boolean withMisapplications) {
149 return dao.getRootTaxa(sec, null, onlyWithChildren, withMisapplications);
150 }
151
152 /* (non-Javadoc)
153 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
154 */
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);
158 }
159
160 public List<RelationshipBase> getAllRelationships(int limit, int start){
161 return dao.getAllRelationships(limit, start);
162 }
163
164 /**
165 * FIXME Candidate for harmonization
166 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
167 */
168 @Deprecated
169 public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypeVocabulary() {
170
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;
176 }
177
178 /* (non-Javadoc)
179 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeTaxonSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Taxon)
180 */
181 @Transactional(readOnly = false)
182 public Synonym changeAcceptedTaxonToSynonym(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, ReferenceBase citation, String citationMicroReference) {
183
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.");
188 }
189
190 if(oldTaxonNode.equals(newAcceptedTaxonNode)){
191 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
192 }
193
194 Taxon oldTaxon = (Taxon) HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
195 Taxon newAcceptedTaxon = (Taxon) HibernateProxyHelper.deproxy(newAcceptedTaxonNode.getTaxon());
196
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();
202 }else{
203 synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
204 }
205 }
206 SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName, synonymRelationshipType, citation, citationMicroReference);
207
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());
212 }
213
214
215 // CHILD NODES
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());
219 }
220 }
221
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());
230
231 }else if(toTaxon == oldTaxon){
232 taxonRelationship.getFromTaxon().addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
233 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
234
235 }else{
236 logger.warn("Taxon is not part of its own Taxonrelationship");
237 }
238 // Remove old relationships
239 taxonRelationship.setToTaxon(null);
240 taxonRelationship.setFromTaxon(null);
241 }
242
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);
247 }
248
249 oldTaxonNode.delete();
250
251 return synonmyRelationship.getSynonym();
252 }
253
254 /*
255 * (non-Javadoc)
256 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
257 */
258 @Transactional(readOnly = false)
259 public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){
260
261 TaxonNameBase synonymName = synonym.getName();
262 synonymName.removeTaxonBase(synonym);
263 TaxonNameBase taxonName = acceptedTaxon.getName();
264 taxonName.removeTaxonBase(acceptedTaxon);
265
266 synonym.setName(taxonName);
267 acceptedTaxon.setName(synonymName);
268
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());
272 }
273
274
275 /*
276 * (non-Javadoc)
277 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeSynonymAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
278 */
279 public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){
280
281 Taxon newAcceptedTaxon = Taxon.NewInstance(synonym.getName(), acceptedTaxon.getSec());
282
283 acceptedTaxon.removeSynonym(synonym);
284
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);
288
289 return newAcceptedTaxon;
290 }
291
292 public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, ReferenceBase citation, String microcitation){
293
294 // Get name from synonym
295 TaxonNameBase<?, ?> synonymName = synonym.getName();
296
297 // remove synonym from taxon
298 toTaxon.removeSynonym(synonym);
299
300 // Create a taxon with synonym name
301 Taxon fromTaxon = Taxon.NewInstance(synonymName, null);
302
303 // Add taxon relation
304 fromTaxon.addTaxonRelation(toTaxon, taxonRelationshipType, citation, microcitation);
305
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);
309
310 return fromTaxon;
311 }
312
313 /* (non-Javadoc)
314 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache()
315 */
316 @Override
317 @Transactional(readOnly = false)
318 public void updateTitleCache() {
319 Class<TaxonBase> clazz = TaxonBase.class;
320 super.updateTitleCache(clazz, null, null);
321 }
322
323 @Autowired
324 protected void setDao(ITaxonDao dao) {
325 this.dao = dao;
326 }
327
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);
330
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);
334 }
335
336 return new DefaultPagerImpl<TaxonBase>(pageNumber, numberOfResults, pageSize, results);
337 }
338
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);
341
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);
345 }
346
347 return results;
348 }
349
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);
352
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);
356 }
357 return results;
358 }
359
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);
362
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);
366 }
367 return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
368 }
369
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);
372
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);
376 }
377 return results;
378 }
379
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);
382
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);
386 }
387 return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
388 }
389
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);
392
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);
396 }
397
398 return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
399 }
400
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);
403
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);
407 }
408
409 return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
410 }
411
412 public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){
413 Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);
414 return t.getHomotypicSynonymsByHomotypicGroup();
415 }
416
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()));
423 }
424 return heterotypicSynonymyGroups;
425 }
426
427 /* (non-Javadoc)
428 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
429 */
430 public Pager<IdentifiableEntity> findTaxaAndNames(ITaxonServiceConfigurator configurator) {
431
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;
435
436 // Taxa and synonyms
437 long numberTaxaResults = 0L;
438
439 Class<? extends TaxonBase> clazz = null;
440 List<String> propertyPath = new ArrayList<String>();
441 if(configurator.getTaxonPropertyPath() != null){
442 propertyPath.addAll(configurator.getTaxonPropertyPath());
443 }
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()) {
449 clazz = Taxon.class;
450 //propertyPath = configurator.getTaxonPropertyPath();
451 } else if (configurator.isDoSynonyms()) {
452 clazz = Synonym.class;
453 //propertyPath = configurator.getSynonymPropertyPath();
454 }
455
456 if(clazz != null){
457 if(configurator.getPageSize() != null){ // no point counting if we need all anyway
458 numberTaxaResults =
459 dao.countTaxaByName(clazz,
460 configurator.getSearchString(), configurator.getTaxonomicTree(), configurator.getMatchMode(),
461 configurator.getNamedAreas());
462 }
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);
468 }
469 }
470
471 if (logger.isDebugEnabled()) { logger.debug(numberTaxaResults + " matching taxa counted"); }
472
473 if(taxa != null){
474 results.addAll(taxa);
475 }
476
477 numberOfResults += numberTaxaResults;
478
479 // Names without taxa
480 if (configurator.isDoNamesWithoutTaxa()) {
481 int numberNameResults = 0;
482
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);
491 numberNameResults++;
492 }
493 }
494 if (logger.isDebugEnabled()) { logger.debug(numberNameResults + " matching name(s) without taxa found"); }
495 numberOfResults += numberNameResults;
496 }
497 }
498
499 // Taxa from common names
500
501 if (configurator.isDoTaxaByCommonNames()) {
502 taxa = null;
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());
506 }
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());
509 }
510 if(taxa != null){
511 results.addAll(taxa);
512 }
513 numberOfResults += numberTaxaResults;
514
515 }
516
517 return new DefaultPagerImpl<IdentifiableEntity>
518 (configurator.getPageNumber(), numberOfResults, configurator.getPageSize(), results);
519 }
520
521 public List<UuidAndTitleCache<TaxonBase>> getTaxonUuidAndTitleCache(){
522 return dao.getUuidAndTitleCache();
523 }
524
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()){
533
534 //find the best matching representation
535 medRep.add(MediaUtils.findBestMatchingRepresentation(media, size, height, widthOrDuration, mimeTypes));
536
537 }
538 }
539 }
540 return medRep;
541 }
542
543 public List<TaxonBase> findTaxaByID(Set<Integer> listOfIDs) {
544 return this.dao.findById(listOfIDs);
545 }
546
547 public int countAllRelationships() {
548 return this.dao.countAllRelationships();
549 }
550
551 public List<Synonym> createAllInferredSynonyms(TaxonomicTree tree,
552 Taxon taxon) {
553
554 return this.dao.createAllInferredSynonyms(taxon, tree);
555 }
556
557 public List<Synonym> createInferredSynonyms(TaxonomicTree tree, Taxon taxon, SynonymRelationshipType type) {
558
559 return this.dao.createInferredSynonyms(taxon, tree, type);
560 }
561
562 public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {
563
564 return this.dao.findIdenticalTaxonNames(propertyPath);
565 }
566
567 public List<TaxonNameBase> findIdenticalTaxonNameIds(List<String> propertyPath) {
568
569 return this.dao.findIdenticalNamesNew(propertyPath);
570 }
571
572 public String getPhylumName(TaxonNameBase name){
573 return this.dao.getPhylumName(name);
574 }
575
576 private class TaxonAndNameComparator implements Comparator{
577
578 public int compare(Object arg0, Object arg1) {
579 IdentifiableEntity castArg0 = (IdentifiableEntity) arg0;
580 IdentifiableEntity castArg1 = (IdentifiableEntity) arg1;
581 return castArg0.compareTo(castArg1);
582 }
583
584 }
585
586 public long deleteSynonymRelationships(Synonym syn) {
587
588 return dao.deleteSynonymRelationships(syn);
589 }
590
591
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);
596
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);
600 }
601 return results;
602 }
603
604 /* (non-Javadoc)
605 * @see eu.etaxonomy.cdm.api.service.ITaxonService#matchToTaxon(eu.etaxonomy.cdm.model.name.NonViralName)
606 */
607 @Override
608 public Taxon findBestMatchingTaxon(String taxonName) {
609
610 Taxon matchedTaxon = null;
611 try{
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());
619 return matchedTaxon;
620 } else {
621 logger.info("using accepted Taxon: " + matchedTaxon.getTitleCache());
622 return matchedTaxon;
623 }
624 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
625 }
626 }
627
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());
637 return matchedTaxon;
638 } else {
639 logger.info("using accepted Taxon " + matchedTaxon.getTitleCache() + "for synonym " + taxonBase.getTitleCache());
640 return matchedTaxon;
641 }
642 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
643 }
644 }
645 }
646
647 } catch (Exception e){
648 logger.error(e);
649 }
650
651 return matchedTaxon;
652 }
653
654 @Override
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() );
661 return result;
662 } else {
663 logger.info("Several matching synonyms found. Using first: " + result.getTitleCache());
664 return result;
665 }
666 }
667 return null;
668 }
669
670
671 }