Project

General

Profile

Download (25.3 KB) Statistics
| Branch: | Tag: | Revision:
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.Collections;
15
import java.util.Comparator;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import org.apache.log4j.Logger;
23
import org.springframework.beans.factory.annotation.Autowired;
24
import org.springframework.stereotype.Service;
25
import org.springframework.transaction.annotation.Propagation;
26
import org.springframework.transaction.annotation.Transactional;
27

    
28
import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
29
import eu.etaxonomy.cdm.api.service.pager.Pager;
30
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
31
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
32
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
33
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
34
import eu.etaxonomy.cdm.model.common.RelationshipBase;
35
import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
36
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
37
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
38
import eu.etaxonomy.cdm.model.description.TaxonDescription;
39
import eu.etaxonomy.cdm.model.media.Media;
40
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
41
import eu.etaxonomy.cdm.model.media.MediaUtils;
42
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
43
import eu.etaxonomy.cdm.model.name.NonViralName;
44
import eu.etaxonomy.cdm.model.name.Rank;
45
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
46
import eu.etaxonomy.cdm.model.name.TaxonNameComparator;
47
import eu.etaxonomy.cdm.model.reference.ReferenceBase;
48
import eu.etaxonomy.cdm.model.taxon.Synonym;
49
import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
50
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
51
import eu.etaxonomy.cdm.model.taxon.Taxon;
52
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
53
import eu.etaxonomy.cdm.model.taxon.TaxonComparator;
54
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
55
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
56
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
57
import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
58
import eu.etaxonomy.cdm.persistence.dao.BeanInitializer;
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.OrderHint;
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

    
76
	@Autowired
77
	private IOrderedTermVocabularyDao orderedVocabularyDao;
78
	@Autowired
79
	private IDescriptionDao descriptionDao;
80
	@Autowired
81
	private BeanInitializer defaultBeanInitializer;
82
	
83
	private Comparator<? super TaxonNode> taxonNodeComparator;
84
	@Autowired
85
	public void setTaxonNodeComparator(ITaxonNodeComparator<? super TaxonNode> taxonNodeComparator){
86
		this.taxonNodeComparator = (Comparator<? super TaxonNode>) taxonNodeComparator;
87
	}
88
	
89
	/**
90
	 * Constructor
91
	 */
92
	public TaxonServiceImpl(){
93
		if (logger.isDebugEnabled()) { logger.debug("Load TaxonService Bean"); }
94
	}
95

    
96
	/**
97
	 * FIXME Candidate for harmonization
98
	 * rename searchByName ? 
99
	 */
100
	public List<TaxonBase> searchTaxaByName(String name, ReferenceBase sec) {
101
		return dao.getTaxaByName(name, sec);
102
	}
103
	
104
	/**
105
	 * FIXME Candidate for harmonization
106
	 * list(Synonym.class, ...)
107
	 *  (non-Javadoc)
108
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)
109
	 */
110
	public List<Synonym> getAllSynonyms(int limit, int start) {
111
		return dao.getAllSynonyms(limit, start);
112
	}
113
	
114
	/**
115
	 * FIXME Candidate for harmonization
116
	 * list(Taxon.class, ...)
117
	 *  (non-Javadoc)
118
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)
119
	 */
120
	public List<Taxon> getAllTaxa(int limit, int start) {
121
		return dao.getAllTaxa(limit, start);
122
	}
123

    
124

    
125
	/**
126
	 * FIXME Candidate for harmonization
127
	 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
128
	 *  (non-Javadoc)
129
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)
130
	 */
131
	public List<Taxon> getRootTaxa(ReferenceBase sec){
132
		return getRootTaxa(sec, CdmFetch.FETCH_CHILDTAXA(), true);
133
	}
134

    
135
	/**
136
	 * FIXME Candidate for harmonization
137
	 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
138
	 *  (non-Javadoc)
139
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean)
140
	 */
141
	public List<Taxon> getRootTaxa(ReferenceBase sec, CdmFetch cdmFetch, boolean onlyWithChildren) {
142
		if (cdmFetch == null){
143
			cdmFetch = CdmFetch.NO_FETCH();
144
		}
145
		return dao.getRootTaxa(sec, cdmFetch, onlyWithChildren, false);
146
	}
147
	
148
	/**
149
 	 * FIXME Candidate for harmonization
150
	 * merge with getRootTaxa(ReferenceBase sec, ..., ...)
151
	 *  (non-Javadoc)
152
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
153
	 */
154
	public List<Taxon> getRootTaxa(ReferenceBase sec, boolean onlyWithChildren,
155
			boolean withMisapplications) {
156
		return dao.getRootTaxa(sec, null, onlyWithChildren, withMisapplications);
157
	}
158

    
159
	/* (non-Javadoc)
160
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, boolean, boolean)
161
	 */
162
	public List<Taxon> getRootTaxa(Rank rank, ReferenceBase sec, boolean onlyWithChildren,
163
			boolean withMisapplications, List<String> propertyPaths) {
164
		return dao.getRootTaxa(rank, sec, null, onlyWithChildren, withMisapplications, propertyPaths);
165
	}
166

    
167
	public List<RelationshipBase> getAllRelationships(int limit, int start){
168
		return dao.getAllRelationships(limit, start);
169
	}
170
	
171
	/**
172
	 * FIXME Candidate for harmonization
173
	 * is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ? 
174
	 */
175
	@Deprecated
176
	public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypeVocabulary() {
177
		
178
		String taxonRelTypeVocabularyId = "15db0cf7-7afc-4a86-a7d4-221c73b0c9ac";
179
		UUID uuid = UUID.fromString(taxonRelTypeVocabularyId);
180
		OrderedTermVocabulary<TaxonRelationshipType> taxonRelTypeVocabulary = 
181
			(OrderedTermVocabulary)orderedVocabularyDao.findByUuid(uuid);
182
		return taxonRelTypeVocabulary;
183
	}
184

    
185
	/* (non-Javadoc)
186
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeTaxonSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Taxon)
187
	 */
188
	@Transactional(readOnly = false)
189
	public Synonym changeAcceptedTaxonToSynonym(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, ReferenceBase citation, String citationMicroReference) {
190

    
191
		// TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
192
		// in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
193
		if (oldTaxonNode == null || newAcceptedTaxonNode == null || oldTaxonNode.getTaxon().getName() == null){
194
			throw new IllegalArgumentException("A mandatory parameter was null.");
195
		}
196
		
197
		if(oldTaxonNode.equals(newAcceptedTaxonNode)){
198
			throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
199
		}
200
		
201
		Taxon oldTaxon = (Taxon) HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
202
		Taxon newAcceptedTaxon = (Taxon) HibernateProxyHelper.deproxy(newAcceptedTaxonNode.getTaxon());
203
		
204
		// Move oldTaxon to newTaxon
205
		TaxonNameBase<?,?> synonymName = oldTaxon.getName();
206
		if (synonymRelationshipType == null){
207
			if (synonymName.isHomotypic(newAcceptedTaxon.getName())){
208
				synonymRelationshipType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
209
			}else{
210
				synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
211
			}
212
		}
213
		SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName, synonymRelationshipType, citation, citationMicroReference);
214
		
215
		//Move Synonym Relations to new Taxon
216
		for(SynonymRelationship synRelation : oldTaxon.getSynonymRelations()){
217
			newAcceptedTaxon.addSynonym(synRelation.getSynonym(), synRelation.getType(), 
218
					synRelation.getCitation(), synRelation.getCitationMicroReference());
219
		}
220

    
221
		
222
		// CHILD NODES
223
		if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){
224
			for(TaxonNode childNode : oldTaxonNode.getChildNodes()){
225
				newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference(), childNode.getSynonymToBeUsed());
226
			}
227
		}
228
		
229
		//Move Taxon RelationShips to new Taxon
230
		Set<TaxonRelationship> obsoleteTaxonRelationships = new HashSet<TaxonRelationship>();
231
		for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){
232
			Taxon fromTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());
233
			Taxon toTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());
234
			if (fromTaxon == oldTaxon){
235
				newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(), 
236
						taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
237
				
238
			}else if(toTaxon == oldTaxon){
239
				taxonRelationship.getFromTaxon().addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(), 
240
						taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
241

    
242
			}else{
243
				logger.warn("Taxon is not part of its own Taxonrelationship");
244
			}
245
			// Remove old relationships
246
			taxonRelationship.setToTaxon(null);
247
			taxonRelationship.setFromTaxon(null);
248
		}
249
		
250
		//Move descriptions to new taxon
251
		for(TaxonDescription oldDescription : oldTaxon.getDescriptions()){
252
			
253
			TaxonDescription newDescription = TaxonDescription.NewInstance(newAcceptedTaxon);
254
			newDescription.setTitleCache("Description copied from " + oldTaxon + ". Old title: " + oldDescription.getTitleCache(), true);
255
			
256
			for(DescriptionElementBase element : oldDescription.getElements()){
257
				newDescription.addElement(element);
258
			}
259
		}
260
				
261
		oldTaxonNode.delete();
262
		
263
		return synonmyRelationship.getSynonym();
264
	}
265

    
266
	/*
267
	 * (non-Javadoc)
268
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)
269
	 */
270
	@Transactional(readOnly = false)
271
	public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, SynonymRelationshipType synonymRelationshipType){
272
		
273
		// create a new synonym with the old acceptedName
274
		TaxonNameBase oldAcceptedTaxonName = acceptedTaxon.getName();
275
		
276
		// store the synonyms name
277
		TaxonNameBase newAcceptedTaxonName = synonym.getName();
278
		
279
		Set<SynonymRelationship> synrels = acceptedTaxon.getSynonymRelations();
280
		Iterator<SynonymRelationship> synRelIterator = synrels.iterator();
281
		SynonymRelationshipType type = null;
282
		while (synRelIterator.hasNext()){
283
			SynonymRelationship synRel = synRelIterator.next();
284
			if (synRel.getSynonym().equals(synonym)){
285
				type = synRel.getType();
286
				break;
287
			}
288
		}
289
		
290
		// remove synonym from oldAcceptedTaxon
291
		acceptedTaxon.removeSynonym(synonym);
292
		
293
		// make synonym name the accepted taxons name
294
		acceptedTaxon.setName(newAcceptedTaxonName);
295
		synonym.setName(oldAcceptedTaxonName);
296
		
297
		// add the new synonym to the acceptedTaxon
298
		if(synonymRelationshipType == null){
299
			//synonymRelationshipType = SynonymRelationshipType.SYNONYM_OF();
300
			synonymRelationshipType = type;
301
		}
302
		if (type.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
303
			acceptedTaxon.addHomotypicSynonym(synonym, null, null);
304
		}else{
305
			acceptedTaxon.addSynonymName(oldAcceptedTaxonName, synonymRelationshipType);
306
		}
307
	}
308
		
309
	
310
	/*
311
	 * (non-Javadoc)
312
	 * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeSynonymAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)
313
	 */
314
	public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){
315
		
316
		Taxon newAcceptedTaxon = Taxon.NewInstance(synonym.getName(), acceptedTaxon.getSec());
317
		
318
		acceptedTaxon.removeSynonym(synonym);
319
		
320
		// since we are swapping names, we have to detach the name from the synonym completely. 
321
		// Otherwise the synonym will still be in the list of typified names.
322
		synonym.getName().removeTaxonBase(synonym);
323
		
324
		return newAcceptedTaxon;
325
	}
326
	
327
	public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, ReferenceBase citation, String microcitation){
328
		
329
		// Get name from synonym
330
		TaxonNameBase<?, ?> synonymName = synonym.getName();
331
		
332
		// remove synonym from taxon
333
		toTaxon.removeSynonym(synonym);
334
		
335
		// Create a taxon with synonym name
336
		Taxon fromTaxon = Taxon.NewInstance(synonymName, null);
337
		
338
		// Add taxon relation 
339
		fromTaxon.addTaxonRelation(toTaxon, taxonRelationshipType, citation, microcitation);
340
				
341
		// since we are swapping names, we have to detach the name from the synonym completely. 
342
		// Otherwise the synonym will still be in the list of typified names.
343
		synonym.getName().removeTaxonBase(synonym);
344
		
345
		return fromTaxon;
346
	}
347

    
348
	public void generateTitleCache() {
349
		generateTitleCache(true);
350
	}
351
	//TODO
352
	public void generateTitleCache(boolean forceProtected) {
353
		logger.warn("generateTitleCache not yet fully implemented!");
354
	}
355

    
356
	@Autowired
357
	protected void setDao(ITaxonDao dao) {
358
		this.dao = dao;
359
	}
360

    
361
	public Pager<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz, String uninomial,	String infragenericEpithet, String specificEpithet,	String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {
362
        Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);
363
		
364
		List<TaxonBase> results = new ArrayList<TaxonBase>();
365
		if(numberOfResults > 0) { // no point checking again
366
			results = dao.findTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank, pageSize, pageNumber); 
367
		}
368
		
369
		return new DefaultPagerImpl<TaxonBase>(pageNumber, numberOfResults, pageSize, results);
370
	}
371

    
372
	public List<TaxonRelationship> listToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
373
		Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);
374
		
375
		List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
376
		if(numberOfResults > 0) { // no point checking again
377
			results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedTo); 
378
		}
379
		return results;
380
	}
381
	
382
	public Pager<TaxonRelationship> pageToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
383
        Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);
384
		
385
		List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
386
		if(numberOfResults > 0) { // no point checking again
387
			results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedTo); 
388
		}
389
		return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
390
	}
391
	
392
	public List<TaxonRelationship> listFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
393
		Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);
394
		
395
		List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
396
		if(numberOfResults > 0) { // no point checking again
397
			results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedFrom); 
398
		}
399
		return results;
400
	}
401
	
402
	public Pager<TaxonRelationship> pageFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
403
        Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);
404
		
405
		List<TaxonRelationship> results = new ArrayList<TaxonRelationship>();
406
		if(numberOfResults > 0) { // no point checking again
407
			results = dao.getTaxonRelationships(taxon, type, pageSize, pageNumber, orderHints, propertyPaths, TaxonRelationship.Direction.relatedFrom); 
408
		}
409
		return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);
410
	}
411

    
412
	public Pager<SynonymRelationship> getSynonyms(Taxon taxon,	SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
413
        Integer numberOfResults = dao.countSynonyms(taxon, type);
414
		
415
		List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();
416
		if(numberOfResults > 0) { // no point checking again
417
			results = dao.getSynonyms(taxon, type, pageSize, pageNumber, orderHints, propertyPaths); 
418
		}
419
		
420
		return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
421
	}
422
	
423
	public Pager<SynonymRelationship> getSynonyms(Synonym synonym,	SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
424
        Integer numberOfResults = dao.countSynonyms(synonym, type);
425
		
426
		List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();
427
		if(numberOfResults > 0) { // no point checking again
428
			results = dao.getSynonyms(synonym, type, pageSize, pageNumber, orderHints, propertyPaths); 
429
		}
430
		
431
		return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);
432
	}
433
	
434
	public List<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){
435
		Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);
436
		return t.getHomotypicSynonymsByHomotypicGroup();
437
	}
438
	
439
	public List<List<Synonym>> getHeterotypicSynonymyGroups(Taxon taxon, List<String> propertyPaths){
440
		Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);
441
		List<HomotypicalGroup> hsgl = t.getHeterotypicSynonymyGroups();
442
		List<List<Synonym>> heterotypicSynonymyGroups = new ArrayList<List<Synonym>>(hsgl.size());
443
		for(HomotypicalGroup hsg : hsgl){
444
			heterotypicSynonymyGroups.add(hsg.getSynonymsInGroup(t.getSec()));
445
		}
446
		return heterotypicSynonymyGroups;
447
	}
448
	
449
	public Pager<IdentifiableEntity> findTaxaAndNames(ITaxonServiceConfigurator configurator) {
450
		
451
		List<IdentifiableEntity> results = new ArrayList<IdentifiableEntity>();
452
		int numberOfResults = 0; // overall number of results (as opposed to number of results per page)
453
		List<TaxonBase> taxa = null; 
454

    
455
		// Taxa and synonyms
456
		long numberTaxaResults = 0L;
457
		
458
		Class<? extends TaxonBase> clazz = null;
459
		List<String> propertyPath = new ArrayList<String>();
460
		propertyPath.addAll(configurator.getTaxonPropertyPath());
461
		if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {
462
			clazz = TaxonBase.class;
463
			//propertyPath.addAll(configurator.getTaxonPropertyPath());
464
			//propertyPath.addAll(configurator.getSynonymPropertyPath());
465
		} else if(configurator.isDoTaxa()) {
466
			clazz = Taxon.class;
467
			//propertyPath = configurator.getTaxonPropertyPath();
468
		} else if (configurator.isDoSynonyms()) {
469
			clazz = Synonym.class;
470
			//propertyPath = configurator.getSynonymPropertyPath();
471
		}
472
		
473
		if(clazz != null){
474
			numberTaxaResults = 
475
				dao.countTaxaByName(clazz, 
476
					configurator.getSearchString(), configurator.getTaxonomicTree(), configurator.getMatchMode(),
477
					configurator.getNamedAreas());
478
			if(numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){ // no point checking again if less results
479
				taxa = dao.getTaxaByName(clazz, 
480
					configurator.getSearchString(), configurator.getTaxonomicTree(), configurator.getMatchMode(),
481
					configurator.getNamedAreas(), configurator.getPageSize(), 
482
					configurator.getPageNumber(), propertyPath);
483
			}
484
		}
485

    
486
		if (logger.isDebugEnabled()) { logger.debug(numberTaxaResults + " matching taxa counted"); }
487
		
488
		if(taxa != null){
489
			results.addAll(taxa);
490
		}
491
		
492
		numberOfResults += numberTaxaResults;
493

    
494
		// Names without taxa 
495
		if (configurator.isDoNamesWithoutTaxa()) {
496
            int numberNameResults = 0;
497
           
498
			List<? extends TaxonNameBase<?,?>> names = 
499
				nameDao.findByName(configurator.getSearchString(), configurator.getMatchMode(), 
500
						configurator.getPageSize(), configurator.getPageNumber(), null, configurator.getTaxonNamePropertyPath());
501
			if (logger.isDebugEnabled()) { logger.debug(names.size() + " matching name(s) found"); }
502
			if (names.size() > 0) {
503
				for (TaxonNameBase<?,?> taxonName : names) {
504
					if (taxonName.getTaxonBases().size() == 0) {
505
						results.add(taxonName);
506
						numberNameResults++;
507
					}
508
				}
509
				if (logger.isDebugEnabled()) { logger.debug(numberNameResults + " matching name(s) without taxa found"); }
510
				numberOfResults += numberNameResults;
511
			}
512
		}
513
		
514
		// Taxa from common names
515
		
516
		if (configurator.isDoTaxaByCommonNames()) {
517
			taxa = null;
518
			numberTaxaResults = 0;
519
			numberTaxaResults = dao.countTaxaByCommonName(configurator.getSearchString(), configurator.getTaxonomicTree(), configurator.getMatchMode(), configurator.getNamedAreas());
520
			if(numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){
521
				taxa = dao.getTaxaByCommonName(configurator.getSearchString(), configurator.getTaxonomicTree(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());
522
			}
523
			if(taxa != null){
524
				results.addAll(taxa);
525
			}
526
			numberOfResults += numberTaxaResults;
527
			 
528
		}
529
		
530
	   return new DefaultPagerImpl<IdentifiableEntity>
531
			(configurator.getPageNumber(), numberOfResults, configurator.getPageSize(), results);
532
	}
533
	
534
	public List<UuidAndTitleCache<TaxonBase>> getTaxonUuidAndTitleCache(){
535
		return dao.getUuidAndTitleCache();
536
	}
537

    
538
	public List<MediaRepresentation> getAllMedia(Taxon taxon, int size, int height, int widthOrDuration, String[] mimeTypes){
539
		List<MediaRepresentation> medRep = new ArrayList<MediaRepresentation>();
540
		taxon = (Taxon)dao.load(taxon.getUuid());
541
		Set<TaxonDescription> descriptions = taxon.getDescriptions();
542
		for (TaxonDescription taxDesc: descriptions){
543
			Set<DescriptionElementBase> elements = taxDesc.getElements();
544
			for (DescriptionElementBase descElem: elements){
545
				for(Media media : descElem.getMedia()){
546
									
547
					//find the best matching representation
548
					medRep.add(MediaUtils.findBestMatchingRepresentation(media, size, height, widthOrDuration, mimeTypes));
549
					
550
				}
551
			}
552
		}
553
		return medRep;
554
	}
555

    
556
	public List<TaxonBase> findTaxaByID(Set<Integer> listOfIDs) {
557
		return this.dao.findById(listOfIDs);
558
	}
559

    
560
	public int countAllRelationships() {
561
		return this.dao.countAllRelationships();
562
	}
563

    
564
	public List<Synonym> createAllInferredSynonyms(TaxonomicTree tree,
565
			Taxon taxon) {
566
		
567
		return this.dao.createAllInferredSynonyms(taxon, tree);
568
	}
569

    
570
	public List<Synonym> createInferredSynonyms(TaxonomicTree tree, Taxon taxon, SynonymRelationshipType type) {
571
		
572
		return this.dao.createInferredSynonyms(taxon, tree, type);
573
	}
574

    
575
	public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {
576
		
577
		return this.dao.findIdenticalTaxonNames(propertyPath);
578
	}
579
	
580
	public List<TaxonNameBase> findIdenticalTaxonNameIds(List<String> propertyPath) {
581
		
582
		return this.dao.findIdenticalNamesNew(propertyPath);
583
	}
584
	
585
	public String getPhylumName(TaxonNameBase name){
586
		return this.dao.getPhylumName(name);
587
	}
588
	
589
	private class TaxonAndNameComparator implements Comparator{
590

    
591
		public int compare(Object arg0, Object arg1) {
592
			IdentifiableEntity castArg0 = (IdentifiableEntity) arg0;
593
			IdentifiableEntity castArg1 = (IdentifiableEntity) arg1;
594
			return castArg0.compareTo(castArg1);
595
		}
596
		
597
	}
598

    
599
	public long deleteSynonymRelationships(Synonym syn) {
600
		
601
		return dao.deleteSynonymRelationships(syn);
602
	}
603

    
604
	
605
	public List<SynonymRelationship> listSynonymRelationships(
606
			TaxonBase taxonBase, SynonymRelationshipType type, Integer pageSize, Integer pageNumber,
607
			List<OrderHint> orderHints, List<String> propertyPaths, Direction direction) {
608
		Integer numberOfResults = dao.countSynonymRelationships(taxonBase, type, direction);
609
		
610
		List<SynonymRelationship> results = new ArrayList<SynonymRelationship>();
611
		if(numberOfResults > 0) { // no point checking again
612
			results = dao.getSynonymRelationships(taxonBase, type, pageSize, pageNumber, orderHints, propertyPaths, direction); 
613
		}
614
		return results;
615
	}
616
}
(59-59/65)