Project

General

Profile

Download (20.1 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.Collection;
15
import java.util.HashSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20

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

    
27
import eu.etaxonomy.cdm.api.service.pager.Pager;
28
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
29
import eu.etaxonomy.cdm.common.IProgressMonitor;
30
import eu.etaxonomy.cdm.model.common.Annotation;
31
import eu.etaxonomy.cdm.model.common.Language;
32
import eu.etaxonomy.cdm.model.common.MarkerType;
33
import eu.etaxonomy.cdm.model.common.TermVocabulary;
34
import eu.etaxonomy.cdm.model.description.DescriptionBase;
35
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
36
import eu.etaxonomy.cdm.model.description.Distribution;
37
import eu.etaxonomy.cdm.model.description.Feature;
38
import eu.etaxonomy.cdm.model.description.FeatureTree;
39
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
40
import eu.etaxonomy.cdm.model.description.Scope;
41
import eu.etaxonomy.cdm.model.description.TaxonDescription;
42
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
43
import eu.etaxonomy.cdm.model.description.TextData;
44
import eu.etaxonomy.cdm.model.location.NamedArea;
45
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
46
import eu.etaxonomy.cdm.model.media.Media;
47
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
48
import eu.etaxonomy.cdm.model.taxon.Taxon;
49
import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
50
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
51
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
52
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureDao;
53
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
54
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
55
import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
56
import eu.etaxonomy.cdm.persistence.query.OrderHint;
57
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
58

    
59
/**
60
 * @author a.mueller
61
 * @created 24.06.2008
62
 * @version 1.0
63
 */
64
@Service
65
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
66
public class DescriptionServiceImpl extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao> implements IDescriptionService {
67
 	
68
	private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
69

    
70
	protected IDescriptionElementDao descriptionElementDao;
71
	protected IFeatureTreeDao featureTreeDao;
72
	protected IFeatureNodeDao featureNodeDao;
73
	protected IFeatureDao featureDao;
74
	protected ITermVocabularyDao vocabularyDao;
75
	protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
76
	//TODO change to Interface
77
	private NaturalLanguageGenerator naturalLanguageGenerator;
78
	
79
	@Autowired
80
	protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
81
		this.featureTreeDao = featureTreeDao;
82
	}
83
	
84
	@Autowired
85
	protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
86
		this.featureNodeDao = featureNodeDao;
87
	}
88
	
89
	@Autowired
90
	protected void setFeatureDao(IFeatureDao featureDao) {
91
		this.featureDao = featureDao;
92
	}
93
	
94
	@Autowired
95
	protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
96
		this.vocabularyDao = vocabularyDao;
97
	}
98
	
99
	@Autowired
100
	protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
101
		this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
102
	}
103
	
104
	@Autowired
105
	protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
106
		this.descriptionElementDao = descriptionElementDao;
107
	}
108
	
109
	@Autowired
110
	protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
111
		this.naturalLanguageGenerator = naturalLanguageGenerator;
112
	}
113
	
114
	/**
115
	 * 
116
	 */
117
	public DescriptionServiceImpl() {
118
		logger.debug("Load DescriptionService Bean");
119
	}
120
	
121
	
122

    
123
	/* (non-Javadoc)
124
	 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
125
	 */
126
	@Override
127
	public void updateTitleCache(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
128
		if (clazz == null){
129
			clazz = DescriptionBase.class;
130
		}
131
		super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
132
	}
133

    
134
	
135
	public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
136
		String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
137
		UUID featureUuid = UUID.fromString(uuidFeature);
138
		return (TermVocabulary)vocabularyDao.findByUuid(featureUuid);
139
	}
140

    
141
	@Autowired
142
	protected void setDao(IDescriptionDao dao) {
143
		this.dao = dao;
144
	}
145

    
146
	public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
147
		return dao.countDescriptions(type, hasImages, hasText, feature);
148
	}
149

    
150
	/**
151
	 * FIXME Candidate for harmonization
152
	 * rename -> getElements
153
	 */
154
	public Pager<DescriptionElementBase> getDescriptionElements(DescriptionBase description,
155
			Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
156

    
157
		List<DescriptionElementBase> results = listDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
158
		return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, results.size(), pageSize, results);
159
	}
160

    
161
	public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description,
162
			Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
163
		Integer numberOfResults = dao.countDescriptionElements(description, features, type);
164
		
165
		List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
166
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
167
			results = dao.getDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
168
		}
169
		return results;
170
	}
171
	
172
	public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
173
		Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
174
		
175
		List<Annotation> results = new ArrayList<Annotation>();
176
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
177
			results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths); 
178
		}
179
		
180
		return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
181
	}
182
	
183
	
184

    
185
	public Pager<Media> getMedia(DescriptionElementBase descriptionElement,	Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
186
        Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
187
		
188
		List<Media> results = new ArrayList<Media>();
189
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
190
			results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths); 
191
		}
192
		
193
		return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
194
	}
195

    
196
	public Pager<TaxonDescription> getTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
197
        Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope);
198
		
199
		List<TaxonDescription> results = new ArrayList<TaxonDescription>();
200
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
201
			results = dao.getTaxonDescriptions(taxon, scopes, geographicalScope, pageSize, pageNumber, propertyPaths); 
202
		}
203
		
204
		return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
205
	}
206
	
207
	public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
208
		List<TaxonDescription> results = dao.getTaxonDescriptions(taxon, scopes, geographicalScope, pageSize, pageNumber, propertyPaths);
209
		return results;
210
	}
211
	
212
	public DistributionTree getOrderedDistributions(
213
			Set<TaxonDescription> taxonDescriptions,
214
			Set<NamedAreaLevel> omitLevels,
215
			List<String> propertyPaths){
216
		
217
		DistributionTree tree = new DistributionTree();
218
		List<Distribution> distList = new ArrayList<Distribution>();
219
		
220
		for (TaxonDescription taxonDescription : taxonDescriptions) {
221
			taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
222
			Set<DescriptionElementBase> elements = taxonDescription.getElements();
223
			for (DescriptionElementBase element : elements) {
224
					if (element.isInstanceOf(Distribution.class)) {
225
						Distribution distribution = (Distribution) element;
226
						if(distribution.getArea() != null){
227
							distList.add(distribution);							
228
						}
229
					}
230
			}
231
		}
232
		
233
		//ordering the areas
234
		tree.merge(distList, omitLevels);
235
		tree.sortChildren();
236
		return tree;
237
	}
238

    
239
	public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
240
        Integer numberOfResults = dao.countTaxonNameDescriptions(name);
241
		
242
		List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
243
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
244
			results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths); 
245
		}
246
		
247
		return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
248
	}
249

    
250
	
251
	public Pager<DescriptionBase> page(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText, Set<Feature> feature, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
252
        Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
253
		
254
		List<DescriptionBase> results = new ArrayList<DescriptionBase>();
255
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
256
			results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths); 
257
		}
258
		
259
		return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
260
	}
261

    
262
	/**
263
	 * FIXME Candidate for harmonization
264
	 * Rename: searchByDistribution
265
	 */
266
	public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase presence,	Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
267
        Integer numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
268
		
269
		List<TaxonDescription> results = new ArrayList<TaxonDescription>();
270
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
271
			results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths); 
272
		}
273
		
274
		return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
275
	}
276

    
277
	/**
278
	 * FIXME Candidate for harmonization
279
	 * move: descriptionElementService.search
280
	 */
281
	public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
282
        Integer numberOfResults = descriptionElementDao.count(clazz,queryString);
283
		
284
		List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
285
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
286
			results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths); 
287
		}
288
		
289
		return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
290
	}
291

    
292
	/**
293
	 * FIXME Candidate for harmonization
294
	 * descriptionElementService.find
295
	 */
296
	public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
297
		return descriptionElementDao.findByUuid(uuid);
298
	}	
299
	
300
	/**
301
	 * FIXME Candidate for harmonization
302
	 * descriptionElementService.load
303
	 */
304
	public DescriptionElementBase loadDescriptionElement(UUID uuid,	List<String> propertyPaths) {
305
		return descriptionElementDao.load(uuid, propertyPaths);
306
	}
307

    
308
    /**
309
     * FIXME Candidate for harmonization
310
     * descriptionElementService.save
311
     */
312
	@Transactional(readOnly = false)
313
	public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
314
		return descriptionElementDao.save(descriptionElement);
315
	}
316
	
317
    /**
318
     * FIXME Candidate for harmonization
319
     * descriptionElementService.save
320
     */
321
	@Transactional(readOnly = false)
322
	public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
323
		return descriptionElementDao.saveAll(descriptionElements);
324
	}
325

    
326
    /**
327
     * FIXME Candidate for harmonization
328
     * descriptionElementService.delete
329
     */
330
	public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
331
		return descriptionElementDao.delete(descriptionElement);
332
	}
333

    
334
	public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
335
		return (TermVocabulary)vocabularyDao.findByUuid(uuid);
336
	}
337

    
338
	public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
339
			Taxon taxon, Set<Feature> features,
340
			Class<? extends T> type, Integer pageSize,
341
			Integer pageNumber, List<String> propertyPaths) {
342
		//FIXME remove cast
343
		return (List<T>) dao.getDescriptionElementForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
344
	}
345
	
346
	public List<DescriptionElementBase> getDescriptionElementsForTaxon(
347
			Taxon taxon, FeatureTree featureTree,
348
			Class<? extends DescriptionElementBase> type, Integer pageSize,
349
			Integer pageNumber, List<String> propertyPaths) {
350
		 //FIXME remove cast
351
		 return (List<DescriptionElementBase>) dao.getDescriptionElementForTaxon(taxon, featureTree.getDistinctFeatures(), type, pageSize, pageNumber, propertyPaths);
352
	}
353

    
354
	/* (non-Javadoc)
355
	 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#generateNaturalLanguageDescription(eu.etaxonomy.cdm.model.description.FeatureTree, eu.etaxonomy.cdm.model.description.TaxonDescription, eu.etaxonomy.cdm.model.common.Language, java.util.List)
356
	 */
357
	@Override
358
	public String generateNaturalLanguageDescription(FeatureTree featureTree,
359
			TaxonDescription description, List<Language> preferredLanguages, String separator) {
360
		
361
		Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
362
		
363
		description = (TaxonDescription)load(description.getUuid());
364
		featureTree = featureTreeDao.load(featureTree.getUuid());
365
		
366
		StringBuilder naturalLanguageDescription = new StringBuilder();
367
		
368
		if(description.hasStructuredData()){
369
			
370
			
371
			String lastCategory = null;
372
			String categorySeparator = ". ";
373
			
374
			List<TextData> textDataList;
375
			TextData naturalLanguageDescriptionText = null;
376
			
377
			boolean useMicroFormatQuantitativeDescriptionBuilder = false;
378
			
379
			if(useMicroFormatQuantitativeDescriptionBuilder){
380
				
381
				MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
382
				naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
383
				naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, ((TaxonDescription)description), lang);
384
					
385
			} else {
386
				
387
				naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
388
						featureTree, 
389
						((TaxonDescription)description),
390
						lang);				
391
			}
392

    
393
			return naturalLanguageDescriptionText.getText(lang);
394
			
395
//			
396
//			boolean doItBetter = false;
397
//
398
//			for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
399
//				if(textData.getMultilanguageText().size() > 0){
400
//					
401
//					if (!textData.getFeature().equals(Feature.UNKNOWN())) {
402
//						String featureLabel = textData.getFeature().getLabel(lang);
403
//
404
//						if(doItBetter){
405
//							/*
406
//							 *  WARNING
407
//							 *  The code lines below are desinged to handle
408
//							 *  a special case where as the feature label contains 
409
//							 *  hierarchical information on the features. This code 
410
//							 *  exist only as a base for discussion, and is not 
411
//							 *  intendet to be used in production.
412
//							 */
413
//							featureLabel = StringUtils.remove(featureLabel, '>');
414
//							
415
//							String[] labelTokens = StringUtils.split(featureLabel, '<');
416
//							if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
417
//								if(naturalLanguageDescription.length() > 0){
418
//									naturalLanguageDescription.append(separator);
419
//								}
420
//								naturalLanguageDescription.append(labelTokens[1]);
421
//							} else {
422
//								if(naturalLanguageDescription.length() > 0){
423
//									naturalLanguageDescription.append(categorySeparator);
424
//								}
425
//								naturalLanguageDescription.append(StringUtils.join(labelTokens));
426
//							}
427
//							lastCategory = labelTokens[0];
428
//							// end of demo code
429
//						} else {
430
//							if(naturalLanguageDescription.length() > 0){
431
//								naturalLanguageDescription.append(separator);
432
//							}
433
//							naturalLanguageDescription.append(textData.getFeature().getLabel(lang));							
434
//						}
435
//					} else {
436
//						if(naturalLanguageDescription.length() > 0){
437
//							naturalLanguageDescription.append(separator);
438
//						}
439
//					}
440
//					String text = textData.getMultilanguageText().values().iterator().next().getText();
441
//					naturalLanguageDescription.append(text);		
442
//					
443
//				}
444
//			}
445
		
446
		}
447
		return naturalLanguageDescription.toString();
448
	}
449

    
450
	/* (non-Javadoc)
451
	 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
452
	 */
453
	@Override
454
	public boolean hasStructuredData(DescriptionBase<?> description) {
455
		return load(description.getUuid()).hasStructuredData();
456
	}
457

    
458

    
459
	/* (non-Javadoc)
460
	 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#moveDescriptionElementsToDescription(java.util.Collection, eu.etaxonomy.cdm.model.description.DescriptionBase, boolean)
461
	 */
462
	@Override
463
	public void moveDescriptionElementsToDescription(Collection<DescriptionElementBase> descriptionElements,
464
													DescriptionBase targetDescription, boolean isCopy) {
465
		
466
		if (descriptionElements.isEmpty() ){
467
			return ;
468
		}
469

    
470
		if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
471
			//if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
472
			descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
473
//			descriptionElementsTmp.addAll(descriptionElements);
474
//			descriptionElements = descriptionElementsTmp;
475
		}
476
		for (DescriptionElementBase element : descriptionElements){
477
			DescriptionBase description = element.getInDescription();
478
			try {
479
				DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
480
				targetDescription.addElement(newElement);	
481
			} catch (CloneNotSupportedException e) {
482
				new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
483
			}
484
			if (! isCopy){
485
				description.removeElement(element);
486
			}
487
			
488
		}
489
	}
490

    
491
}
(15-15/76)