bugfix for DescriptionDaoImpl.getDescriptionElementForTaxon (missing implementation...
[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.List;
16 import java.util.Set;
17 import java.util.UUID;
18
19 import org.apache.log4j.Logger;
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Service;
22 import org.springframework.transaction.annotation.Propagation;
23 import org.springframework.transaction.annotation.Transactional;
24
25 import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
26 import eu.etaxonomy.cdm.api.service.pager.Pager;
27 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
28 import eu.etaxonomy.cdm.common.IProgressMonitor;
29 import eu.etaxonomy.cdm.model.common.CdmBase;
30 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
31 import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
32 import eu.etaxonomy.cdm.model.common.RelationshipBase;
33 import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
34 import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
35 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
36 import eu.etaxonomy.cdm.model.description.TaxonDescription;
37 import eu.etaxonomy.cdm.model.media.Media;
38 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
39 import eu.etaxonomy.cdm.model.media.MediaUtils;
40 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
41 import eu.etaxonomy.cdm.model.name.Rank;
42 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
43 import eu.etaxonomy.cdm.model.reference.Reference;
44 import eu.etaxonomy.cdm.model.taxon.Classification;
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.TaxonRelationship;
51 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
52 import eu.etaxonomy.cdm.persistence.dao.common.IOrderedTermVocabularyDao;
53 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
54 import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
55 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
56 import eu.etaxonomy.cdm.persistence.fetch.CdmFetch;
57 import eu.etaxonomy.cdm.persistence.query.MatchMode;
58 import eu.etaxonomy.cdm.persistence.query.OrderHint;
59 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
60
61
62 /**
63 * @author a.kohlbecker
64 * @date 10.09.2010
65 *
66 */
67 @Service
68 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
69 public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDao> implements ITaxonService{
70 private static final Logger logger = Logger.getLogger(TaxonServiceImpl.class);
71
72 @Autowired
73 private ITaxonNameDao nameDao;
74
75 @Autowired
76 private IDescriptionDao descriptionDao;
77
78 @Autowired
79 private IOrderedTermVocabularyDao orderedVocabularyDao;
80
81 /**
82 * Constructor
83 */
84 public TaxonServiceImpl(){
85 if (logger.isDebugEnabled()) { logger.debug("Load TaxonService Bean"); }
86 }
87
88 /**
89 * FIXME Candidate for harmonization
90 * rename searchByName ?
91 */
92 public List<TaxonBase> searchTaxaByName(String name, Reference sec) {
93 return dao.getTaxaByName(name, sec);
94 }
95
96 /**
97 * FIXME Candidate for harmonization
98 * list(Synonym.class, ...)
99 * (non-Javadoc)
100 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
101 */
102 public List<Synonym> getAllSynonyms(int limit, int start) {
103 return dao.getAllSynonyms(limit, start);
104 }
105
106 /**
107 * FIXME Candidate for harmonization
108 * list(Taxon.class, ...)
109 * (non-Javadoc)
110 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
111 */
112 public List<Taxon> getAllTaxa(int limit, int start) {
113 return dao.getAllTaxa(limit, start);
114 }
115
116
117 /**
118 * FIXME Candidate for harmonization
119 * merge with getRootTaxa(Reference sec, ..., ...)
120 * (non-Javadoc)
121 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference)
122 */
123 public List<Taxon> getRootTaxa(Reference sec){
124 return getRootTaxa(sec, CdmFetch.FETCH_CHILDTAXA(), true);
125 }
126
127 /**
128 * FIXME Candidate for harmonization
129 * merge with getRootTaxa(Reference sec, ..., ...)
130 * (non-Javadoc)
131 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)
132 */
133 public List<Taxon> getRootTaxa(Reference sec, CdmFetch cdmFetch, boolean onlyWithChildren) {
134 if (cdmFetch == null){
135 cdmFetch = CdmFetch.NO_FETCH();
136 }
137 return dao.getRootTaxa(sec, cdmFetch, onlyWithChildren, false);
138 }
139
140 /**
141 * FIXME Candidate for harmonization
142 * merge with getRootTaxa(Reference sec, ..., ...)
143 * (non-Javadoc)
144 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
145 */
146 public List<Taxon> getRootTaxa(Reference sec, boolean onlyWithChildren,
147 boolean withMisapplications) {
148 return dao.getRootTaxa(sec, null, onlyWithChildren, withMisapplications);
149 }
150
151 /* (non-Javadoc)
152 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)
153 */
154 public List<Taxon> getRootTaxa(Rank rank, Reference sec, boolean onlyWithChildren,
155 boolean withMisapplications, List<String> propertyPaths) {
156 return dao.getRootTaxa(rank, sec, null, onlyWithChildren, withMisapplications, propertyPaths);
157 }
158
159 /* (non-Javadoc)
160 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)
161 */
162 public List<RelationshipBase> getAllRelationships(int limit, int start){
163 return dao.getAllRelationships(limit, start);
164 }
165
166 /**
167 * FIXME Candidate for harmonization
168 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?
169 */
170 @Deprecated
171 public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypeVocabulary() {
172
173 String taxonRelTypeVocabularyId = "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
174 UUID uuid = UUID.fromString(taxonRelTypeVocabularyId);
175 OrderedTermVocabulary<TaxonRelationshipType> taxonRelTypeVocabulary =
176 (OrderedTermVocabulary)orderedVocabularyDao.findByUuid(uuid);
177 return taxonRelTypeVocabulary;
178 }
179
180
181
182 /*
183 * (non-Javadoc)
184 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
185 */
186 @Transactional(readOnly = false)
187 public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){
188
189 TaxonNameBase synonymName = synonym.getName();
190 synonymName.removeTaxonBase(synonym);
191 TaxonNameBase taxonName = acceptedTaxon.getName();
192 taxonName.removeTaxonBase(acceptedTaxon);
193
194 synonym.setName(taxonName);
195 acceptedTaxon.setName(synonymName);
196
197 // the accepted taxon needs a new uuid because the concept has changed
198 // FIXME this leads to an error "HibernateException: immutable natural identifier of an instance of eu.etaxonomy.cdm.model.taxon.Taxon was altered"
199 //acceptedTaxon.setUuid(UUID.randomUUID());
200 }
201
202
203 /* (non-Javadoc)
204 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
205 */
206 //TODO correct delete handling still needs to be implemented / checked
207 @Override
208 @Transactional(readOnly = false)
209 public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, boolean deleteSynonym, boolean copyCitationInfo, Reference citation, String microCitation) throws IllegalArgumentException{
210
211 TaxonNameBase acceptedName = acceptedTaxon.getName();
212 TaxonNameBase synonymName = synonym.getName();
213 HomotypicalGroup synonymHomotypicGroup = synonymName.getHomotypicalGroup();
214 if (acceptedName.getHomotypicalGroup().equals(synonymHomotypicGroup)){
215 String message = "The accepted taxon and the synonym are part of the same homotypical group and therefore can not be both accepted.";
216 throw new IllegalArgumentException(message);
217 }
218
219 Taxon newAcceptedTaxon = Taxon.NewInstance(synonym.getName(), acceptedTaxon.getSec());
220
221 SynonymRelationshipType relType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
222 List<Synonym> heteroSynonyms = synonymHomotypicGroup.getSynonymsInGroup(acceptedTaxon.getSec());
223 for (Synonym heteroSynonym : heteroSynonyms){
224 if (synonym.equals(heteroSynonym)){
225 acceptedTaxon.removeSynonym(heteroSynonym, false);
226 }else{
227 heteroSynonym.replaceAcceptedTaxon(newAcceptedTaxon, relType, copyCitationInfo, citation, microCitation);
228 }
229 }
230
231 // synonym.getName().removeTaxonBase(synonym);
232 //TODO correct delete handling still needs to be implemented / checked
233 if (deleteSynonym){
234 try {
235 this.delete(synonym);
236 } catch (Exception e) {
237 logger.info("Can't delete old synonym from database");
238 }
239 }
240
241
242 return newAcceptedTaxon;
243 }
244
245 public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, Reference citation, String microcitation){
246
247 // Get name from synonym
248 TaxonNameBase<?, ?> synonymName = synonym.getName();
249
250 // remove synonym from taxon
251 toTaxon.removeSynonym(synonym);
252
253 // Create a taxon with synonym name
254 Taxon fromTaxon = Taxon.NewInstance(synonymName, null);
255
256 // Add taxon relation
257 fromTaxon.addTaxonRelation(toTaxon, taxonRelationshipType, citation, microcitation);
258
259 // since we are swapping names, we have to detach the name from the synonym completely.
260 // Otherwise the synonym will still be in the list of typified names.
261 synonym.getName().removeTaxonBase(synonym);
262
263 return fromTaxon;
264 }
265
266 /* (non-Javadoc)
267 * @see eu.etaxonomy.cdm.api.service.ITaxonService#changeHomotypicalGroupOfSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.name.HomotypicalGroup, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)
268 */
269 @Transactional(readOnly = false)
270 @Override
271 public void changeHomotypicalGroupOfSynonym(Synonym synonym, HomotypicalGroup newHomotypicalGroup, Taxon targetTaxon,
272 boolean removeFromOtherTaxa, boolean setBasionymRelationIfApplicable){
273 // Get synonym name
274 TaxonNameBase synonymName = synonym.getName();
275 HomotypicalGroup oldHomotypicalGroup = synonymName.getHomotypicalGroup();
276
277
278 // Switch groups
279 oldHomotypicalGroup.removeTypifiedName(synonymName);
280 newHomotypicalGroup.addTypifiedName(synonymName);
281
282 //remove existing basionym relationships
283 synonymName.removeBasionyms();
284
285 //add basionym relationship
286 if (setBasionymRelationIfApplicable){
287 Set<TaxonNameBase> basionyms = newHomotypicalGroup.getBasionyms();
288 for (TaxonNameBase basionym : basionyms){
289 synonymName.addBasionym(basionym);
290 }
291 }
292
293 //set synonym relationship correctly
294 // SynonymRelationship relToTaxon = null;
295 boolean relToTargetTaxonExists = false;
296 Set<SynonymRelationship> existingRelations = synonym.getSynonymRelations();
297 for (SynonymRelationship rel : existingRelations){
298 Taxon acceptedTaxon = rel.getAcceptedTaxon();
299 boolean isTargetTaxon = acceptedTaxon != null && acceptedTaxon.equals(targetTaxon);
300 HomotypicalGroup acceptedGroup = acceptedTaxon.getHomotypicGroup();
301 boolean isHomotypicToTaxon = acceptedGroup.equals(newHomotypicalGroup);
302 SynonymRelationshipType newRelationType = isHomotypicToTaxon? SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
303 rel.setType(newRelationType);
304 //TODO handle citation and microCitation
305
306 if (isTargetTaxon){
307 relToTargetTaxonExists = true;
308 }else{
309 if (removeFromOtherTaxa){
310 acceptedTaxon.removeSynonym(synonym, false);
311 }else{
312 //do nothing
313 }
314 }
315 }
316 if (targetTaxon != null && ! relToTargetTaxonExists ){
317 Taxon acceptedTaxon = targetTaxon;
318 HomotypicalGroup acceptedGroup = acceptedTaxon.getHomotypicGroup();
319 boolean isHomotypicToTaxon = acceptedGroup.equals(newHomotypicalGroup);
320 SynonymRelationshipType relType = isHomotypicToTaxon? SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF() : SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
321 //TODO handle citation and microCitation
322 Reference citation = null;
323 String microCitation = null;
324 acceptedTaxon.addSynonym(synonym, relType, citation, microCitation);
325 }
326
327 }
328
329
330 /* (non-Javadoc)
331 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
332 */
333 @Override
334 public void updateTitleCache(Class<? extends TaxonBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<TaxonBase> cacheStrategy, IProgressMonitor monitor) {
335 if (clazz == null){
336 clazz = TaxonBase.class;
337 }
338 super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
339 }
340
341 @Autowired
342 protected void setDao(ITaxonDao dao) {
343 this.dao = dao;
344 }
345
346 /* (non-Javadoc)
347 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)
348 */
349 public Pager<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {
350 Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);
351
352 List<TaxonBase> results = new ArrayList<TaxonBase>();
353 if(numberOfResults > 0) { // no point checking again
354 results = dao.findTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank, pageSize, pageNumber);
355 }
356
357 return new DefaultPagerImpl<TaxonBase>(pageNumber, numberOfResults, pageSize, results);
358 }
359
360 /* (non-Javadoc)
361 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)
362 */
363 public List<TaxonBase> listTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {
364 Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);
365
366 List<TaxonBase> results = new ArrayList<TaxonBase>();
367 if(numberOfResults > 0) { // no point checking again
368 results = dao.findTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank, pageSize, pageNumber);
369 }
370
371 return results;
372 }
373
374 /* (non-Javadoc)
375 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listToTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
376 */
377 public List<TaxonRelationship> listToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
378 Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);
379
380 List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
381 if(numberOfResults > 0) { // no point checking again
382 results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedTo);
383 }
384 return results;
385 }
386
387 /* (non-Javadoc)
388 * @see eu.etaxonomy.cdm.api.service.ITaxonService#pageToTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
389 */
390 public Pager<TaxonRelationship> pageToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
391 Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);
392
393 List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
394 if(numberOfResults > 0) { // no point checking again
395 results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedTo);
396 }
397 return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
398 }
399
400 /* (non-Javadoc)
401 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listFromTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
402 */
403 public List<TaxonRelationship> listFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
404 Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);
405
406 List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
407 if(numberOfResults > 0) { // no point checking again
408 results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedFrom);
409 }
410 return results;
411 }
412
413 /* (non-Javadoc)
414 * @see eu.etaxonomy.cdm.api.service.ITaxonService#pageFromTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
415 */
416 public Pager<TaxonRelationship> pageFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
417 Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);
418
419 List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
420 if(numberOfResults > 0) { // no point checking again
421 results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedFrom);
422 }
423 return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
424 }
425
426 /* (non-Javadoc)
427 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getSynonyms(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
428 */
429 public Pager<SynonymRelationship> getSynonyms(Taxon taxon, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
430 Integer numberOfResults = dao.countSynonyms(taxon, type);
431
432 List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();
433 if(numberOfResults > 0) { // no point checking again
434 results = dao.getSynonyms(taxon, type, pageSize, pageNumber, orderHints, propertyPaths);
435 }
436
437 return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
438 }
439
440 /* (non-Javadoc)
441 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getSynonyms(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
442 */
443 public Pager<SynonymRelationship> getSynonyms(Synonym synonym, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
444 Integer numberOfResults = dao.countSynonyms(synonym, type);
445
446 List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();
447 if(numberOfResults > 0) { // no point checking again
448 results = dao.getSynonyms(synonym, type, pageSize, pageNumber, orderHints, propertyPaths);
449 }
450
451 return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
452 }
453
454 /* (non-Javadoc)
455 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
456 */
457 public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){
458 Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);
459 return t.getHomotypicSynonymsByHomotypicGroup();
460 }
461
462 /* (non-Javadoc)
463 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
464 */
465 public List<List<Synonym>> getHeterotypicSynonymyGroups(Taxon taxon, List<String> propertyPaths){
466 Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);
467 List<HomotypicalGroup> hsgl = t.getHeterotypicSynonymyGroups();
468 List<List<Synonym>> heterotypicSynonymyGroups = new ArrayList<List<Synonym>>(hsgl.size());
469 for(HomotypicalGroup hsg : hsgl){
470 heterotypicSynonymyGroups.add(hsg.getSynonymsInGroup(t.getSec()));
471 }
472 return heterotypicSynonymyGroups;
473 }
474
475 public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(ITaxonServiceConfigurator configurator){
476
477 List<UuidAndTitleCache<TaxonBase>> result = new ArrayList<UuidAndTitleCache<TaxonBase>>();
478 Class<? extends TaxonBase> clazz = null;
479 if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
480 clazz = TaxonBase.class;
481 //propertyPath.addAll(configurator.getTaxonPropertyPath());
482 //propertyPath.addAll(configurator.getSynonymPropertyPath());
483 } else if(configurator.isDoTaxa()) {
484 clazz = Taxon.class;
485 //propertyPath = configurator.getTaxonPropertyPath();
486 } else if (configurator.isDoSynonyms()) {
487 clazz = Synonym.class;
488 //propertyPath = configurator.getSynonymPropertyPath();
489 }
490
491
492 result = dao.getTaxaByNameForEditor(clazz, configurator.getSearchString(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
493 return result;
494 }
495 /* (non-Javadoc)
496 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)
497 */
498 public Pager<IdentifiableEntity> findTaxaAndNames(ITaxonServiceConfigurator configurator) {
499
500 List<IdentifiableEntity> results = new ArrayList<IdentifiableEntity>();
501 int numberOfResults = 0; // overall number of results (as opposed to number of results per page)
502 List<TaxonBase> taxa = null;
503
504 // Taxa and synonyms
505 long numberTaxaResults = 0L;
506
507 Class<? extends TaxonBase> clazz = null;
508 List<String> propertyPath = new ArrayList<String>();
509 if(configurator.getTaxonPropertyPath() != null){
510 propertyPath.addAll(configurator.getTaxonPropertyPath());
511 }
512 if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
513 clazz = TaxonBase.class;
514 //propertyPath.addAll(configurator.getTaxonPropertyPath());
515 //propertyPath.addAll(configurator.getSynonymPropertyPath());
516 } else if(configurator.isDoTaxa()) {
517 clazz = Taxon.class;
518 //propertyPath = configurator.getTaxonPropertyPath();
519 } else if (configurator.isDoSynonyms()) {
520 clazz = Synonym.class;
521 //propertyPath = configurator.getSynonymPropertyPath();
522 }
523
524 if(clazz != null){
525 if(configurator.getPageSize() != null){ // no point counting if we need all anyway
526 numberTaxaResults =
527 dao.countTaxaByName(clazz,
528 configurator.getSearchString(), configurator.getClassification(), configurator.getMatchMode(),
529 configurator.getNamedAreas());
530 }
531
532 if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){ // no point checking again if less results
533 taxa = dao.getTaxaByName(clazz,
534 configurator.getSearchString(), configurator.getClassification(), configurator.getMatchMode(),
535 configurator.getNamedAreas(), configurator.getPageSize(),
536 configurator.getPageNumber(), propertyPath);
537 }
538 }
539
540 if (logger.isDebugEnabled()) { logger.debug(numberTaxaResults + " matching taxa counted"); }
541
542 if(taxa != null){
543 results.addAll(taxa);
544 }
545
546 numberOfResults += numberTaxaResults;
547
548 // Names without taxa
549 if (configurator.isDoNamesWithoutTaxa()) {
550 int numberNameResults = 0;
551
552 List<? extends TaxonNameBase<?,?>> names =
553 nameDao.findByName(configurator.getSearchString(), configurator.getMatchMode(),
554 configurator.getPageSize(), configurator.getPageNumber(), null, configurator.getTaxonNamePropertyPath());
555 if (logger.isDebugEnabled()) { logger.debug(names.size() + " matching name(s) found"); }
556 if (names.size() > 0) {
557 for (TaxonNameBase<?,?> taxonName : names) {
558 if (taxonName.getTaxonBases().size() == 0) {
559 results.add(taxonName);
560 numberNameResults++;
561 }
562 }
563 if (logger.isDebugEnabled()) { logger.debug(numberNameResults + " matching name(s) without taxa found"); }
564 numberOfResults += numberNameResults;
565 }
566 }
567
568 // Taxa from common names
569
570 if (configurator.isDoTaxaByCommonNames()) {
571 taxa = null;
572 numberTaxaResults = 0;
573 if(configurator.getPageSize() != null){// no point counting if we need all anyway
574 numberTaxaResults = dao.countTaxaByCommonName(configurator.getSearchString(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
575 }
576 if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){
577 taxa = dao.getTaxaByCommonName(configurator.getSearchString(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());
578 }
579 if(taxa != null){
580 results.addAll(taxa);
581 }
582 numberOfResults += numberTaxaResults;
583
584 }
585
586 return new DefaultPagerImpl<IdentifiableEntity>
587 (configurator.getPageNumber(), numberOfResults, configurator.getPageSize(), results);
588 }
589
590 public List<UuidAndTitleCache<TaxonBase>> getTaxonUuidAndTitleCache(){
591 return dao.getUuidAndTitleCache();
592 }
593
594 /* (non-Javadoc)
595 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])
596 */
597 public List<MediaRepresentation> getAllMedia(Taxon taxon, int size, int height, int widthOrDuration, String[] mimeTypes){
598 List<MediaRepresentation> medRep = new ArrayList<MediaRepresentation>();
599 taxon = (Taxon)dao.load(taxon.getUuid());
600 Set<TaxonDescription> descriptions = taxon.getDescriptions();
601 for (TaxonDescription taxDesc: descriptions){
602 Set<DescriptionElementBase> elements = taxDesc.getElements();
603 for (DescriptionElementBase descElem: elements){
604 for(Media media : descElem.getMedia()){
605
606 //find the best matching representation
607 medRep.add(MediaUtils.findBestMatchingRepresentation(media, size, height, widthOrDuration, mimeTypes));
608
609 }
610 }
611 }
612 return medRep;
613 }
614
615 /* (non-Javadoc)
616 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)
617 */
618 public List<TaxonBase> findTaxaByID(Set<Integer> listOfIDs) {
619 return this.dao.findById(listOfIDs);
620 }
621
622 /* (non-Javadoc)
623 * @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()
624 */
625 public int countAllRelationships() {
626 return this.dao.countAllRelationships();
627 }
628
629 /* (non-Javadoc)
630 * @see eu.etaxonomy.cdm.api.service.ITaxonService#createAllInferredSynonyms(eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.model.taxon.Taxon)
631 */
632 public List<Synonym> createAllInferredSynonyms(Classification tree,
633 Taxon taxon) {
634
635 return this.dao.createAllInferredSynonyms(taxon, tree);
636 }
637
638 /* (non-Javadoc)
639 * @see eu.etaxonomy.cdm.api.service.ITaxonService#createInferredSynonyms(eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType)
640 */
641 public List<Synonym> createInferredSynonyms(Classification tree, Taxon taxon, SynonymRelationshipType type) {
642
643 return this.dao.createInferredSynonyms(taxon, tree, type);
644 }
645
646 /* (non-Javadoc)
647 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)
648 */
649 public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {
650
651 return this.dao.findIdenticalTaxonNames(propertyPath);
652 }
653
654 /* (non-Javadoc)
655 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)
656 */
657 public List<TaxonNameBase> findIdenticalTaxonNameIds(List<String> propertyPath) {
658
659 return this.dao.findIdenticalNamesNew(propertyPath);
660 }
661
662 /* (non-Javadoc)
663 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)
664 */
665 public String getPhylumName(TaxonNameBase name){
666 return this.dao.getPhylumName(name);
667 }
668
669 private class TaxonAndNameComparator implements Comparator{
670
671 public int compare(Object arg0, Object arg1) {
672 IdentifiableEntity castArg0 = (IdentifiableEntity) arg0;
673 IdentifiableEntity castArg1 = (IdentifiableEntity) arg1;
674 return castArg0.compareTo(castArg1);
675 }
676
677 }
678
679 /* (non-Javadoc)
680 * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)
681 */
682 public long deleteSynonymRelationships(Synonym syn) {
683
684 return dao.deleteSynonymRelationships(syn);
685 }
686
687
688 /* (non-Javadoc)
689 * @see eu.etaxonomy.cdm.api.service.ITaxonService#listSynonymRelationships(eu.etaxonomy.cdm.model.taxon.TaxonBase, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction)
690 */
691 public List<SynonymRelationship> listSynonymRelationships(
692 TaxonBase taxonBase, SynonymRelationshipType type, Integer pageSize, Integer pageNumber,
693 List<OrderHint> orderHints, List<String> propertyPaths, Direction direction) {
694 Integer numberOfResults = dao.countSynonymRelationships(taxonBase, type, direction);
695
696 List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();
697 if(numberOfResults > 0) { // no point checking again
698 results = dao.getSynonymRelationships(taxonBase, type, pageSize, pageNumber, orderHints, propertyPaths, direction);
699 }
700 return results;
701 }
702
703 /* (non-Javadoc)
704 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingTaxon(java.lang.String)
705 */
706 @Override
707 public Taxon findBestMatchingTaxon(String taxonName) {
708
709 Taxon matchedTaxon = null;
710 try{
711 // 1. search for acceptet taxa
712 List<TaxonBase> taxonList = dao.findByNameTitleCache(Taxon.class, taxonName, null, MatchMode.EXACT, null, 0, null, null);
713 for(IdentifiableEntity taxonBaseCandidate : taxonList){
714 if(taxonBaseCandidate instanceof Taxon){
715 matchedTaxon = (Taxon)taxonBaseCandidate;
716 if(taxonList.size() > 1){
717 logger.info(taxonList.size() + " TaxonBases found, using first accepted Taxon: " + matchedTaxon.getTitleCache());
718 return matchedTaxon;
719 } else {
720 logger.info("using accepted Taxon: " + matchedTaxon.getTitleCache());
721 return matchedTaxon;
722 }
723 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
724 }
725 }
726
727 // 2. search for synonyms
728 List<TaxonBase> synonymList = dao.findByNameTitleCache(Synonym.class, taxonName, null, MatchMode.EXACT, null, 0, null, null);
729 for(TaxonBase taxonBase : synonymList){
730 if(taxonBase instanceof Synonym){
731 Set<Taxon> acceptetdCandidates = ((Synonym)taxonBase).getAcceptedTaxa();
732 if(!acceptetdCandidates.isEmpty()){
733 matchedTaxon = acceptetdCandidates.iterator().next();
734 if(acceptetdCandidates.size() == 1){
735 logger.info(acceptetdCandidates.size() + " Accepted taxa found for synonym " + taxonBase.getTitleCache() + ", using first one: " + matchedTaxon.getTitleCache());
736 return matchedTaxon;
737 } else {
738 logger.info("using accepted Taxon " + matchedTaxon.getTitleCache() + "for synonym " + taxonBase.getTitleCache());
739 return matchedTaxon;
740 }
741 //TODO extend method: search using treeUUID, using SecUUID, first find accepted then include synonyms until a matching taxon is found
742 }
743 }
744 }
745
746 } catch (Exception e){
747 logger.error(e);
748 }
749
750 return matchedTaxon;
751 }
752
753 /* (non-Javadoc)
754 * @see eu.etaxonomy.cdm.api.service.ITaxonService#findBestMatchingSynonym(java.lang.String)
755 */
756 @Override
757 public Synonym findBestMatchingSynonym(String taxonName) {
758 List<TaxonBase> synonymList = dao.findByNameTitleCache(Synonym.class, taxonName, null, MatchMode.EXACT, null, 0, null, null);
759 if(! synonymList.isEmpty()){
760 Synonym result = CdmBase.deproxy(synonymList.iterator().next(), Synonym.class);
761 if(synonymList.size() == 1){
762 logger.info(synonymList.size() + " Synonym found " + result.getTitleCache() );
763 return result;
764 } else {
765 logger.info("Several matching synonyms found. Using first: " + result.getTitleCache());
766 return result;
767 }
768 }
769 return null;
770 }
771
772 /* (non-Javadoc)
773 * @see eu.etaxonomy.cdm.api.service.ITaxonService#moveSynonymToAnotherTaxon(eu.etaxonomy.cdm.model.taxon.SynonymRelationship, eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.reference.Reference, java.lang.String)
774 */
775 @Override
776 public Taxon moveSynonymToAnotherTaxon(SynonymRelationship synonymRelation,
777 Taxon toTaxon, SynonymRelationshipType synonymRelationshipType, Reference reference, String referenceDetail) {
778 Taxon fromTaxon = synonymRelation.getAcceptedTaxon();
779
780 toTaxon.addSynonym(synonymRelation.getSynonym(), synonymRelationshipType, reference, referenceDetail);
781
782 fromTaxon.removeSynonymRelation(synonymRelation);
783
784 return toTaxon;
785 }
786
787 /* (non-Javadoc)
788 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheTaxon()
789 */
790 @Override
791 public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheTaxon() {
792 return dao.getUuidAndTitleCacheTaxon();
793 }
794
795 /* (non-Javadoc)
796 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheSynonym()
797 */
798 @Override
799 public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheSynonym() {
800 return dao.getUuidAndTitleCacheSynonym();
801 }
802
803
804 }