Project

General

Profile

Download (16.5 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.List;
16
import java.util.Map;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import org.apache.commons.lang.StringUtils;
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.model.common.Annotation;
30
import eu.etaxonomy.cdm.model.common.Language;
31
import eu.etaxonomy.cdm.model.common.MarkerType;
32
import eu.etaxonomy.cdm.model.common.TermVocabulary;
33
import eu.etaxonomy.cdm.model.description.DescriptionBase;
34
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
35
import eu.etaxonomy.cdm.model.description.Distribution;
36
import eu.etaxonomy.cdm.model.description.Feature;
37
import eu.etaxonomy.cdm.model.description.FeatureTree;
38
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
39
import eu.etaxonomy.cdm.model.description.Scope;
40
import eu.etaxonomy.cdm.model.description.TaxonDescription;
41
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
42
import eu.etaxonomy.cdm.model.description.TextData;
43
import eu.etaxonomy.cdm.model.location.NamedArea;
44
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
45
import eu.etaxonomy.cdm.model.media.Media;
46
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
47
import eu.etaxonomy.cdm.model.taxon.Taxon;
48
import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
49
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
50
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
51
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureDao;
52
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
53
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
54
import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
55
import eu.etaxonomy.cdm.persistence.query.OrderHint;
56

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

    
68
	protected IDescriptionElementDao descriptionElementDao;
69
	protected IFeatureTreeDao featureTreeDao;
70
	protected IFeatureNodeDao featureNodeDao;
71
	protected IFeatureDao featureDao;
72
	protected ITermVocabularyDao vocabularyDao;
73
	protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
74
	private INaturalLanguageGenerator naturalLanguageGenerator;
75
	
76
	@Autowired
77
	protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
78
		this.featureTreeDao = featureTreeDao;
79
	}
80
	
81
	@Autowired
82
	protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
83
		this.featureNodeDao = featureNodeDao;
84
	}
85
	
86
	@Autowired
87
	protected void setFeatureDao(IFeatureDao featureDao) {
88
		this.featureDao = featureDao;
89
	}
90
	
91
	@Autowired
92
	protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
93
		this.vocabularyDao = vocabularyDao;
94
	}
95
	
96
	@Autowired
97
	protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
98
		this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
99
	}
100
	
101
	@Autowired
102
	protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
103
		this.descriptionElementDao = descriptionElementDao;
104
	}
105
	
106
	@Autowired
107
	protected void setNaturalLanguageGenerator(INaturalLanguageGenerator naturalLanguageGenerator) {
108
		this.naturalLanguageGenerator = naturalLanguageGenerator;
109
	}
110
	
111
	/**
112
	 * 
113
	 */
114
	public DescriptionServiceImpl() {
115
		logger.debug("Load DescriptionService Bean");
116
	}
117
	
118
	/* (non-Javadoc)
119
	 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache()
120
	 */
121
	@Override
122
	public void updateTitleCache() {
123
		Class<DescriptionBase> clazz = DescriptionBase.class;
124
		super.updateTitleCache(clazz, null, null);
125
	}
126
	
127
	public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
128
		String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
129
		UUID featureUuid = UUID.fromString(uuidFeature);
130
		return (TermVocabulary)vocabularyDao.findByUuid(featureUuid);
131
	}
132

    
133
	@Autowired
134
	protected void setDao(IDescriptionDao dao) {
135
		this.dao = dao;
136
	}
137

    
138
	public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
139
		return dao.countDescriptions(type, hasImages, hasText, feature);
140
	}
141

    
142
	/**
143
	 * FIXME Candidate for harmonization
144
	 * rename -> getElements
145
	 */
146
	public Pager<DescriptionElementBase> getDescriptionElements(DescriptionBase description,
147
			Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
148

    
149
		List<DescriptionElementBase> results = listDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
150
		return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, results.size(), pageSize, results);
151
	}
152

    
153
	public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description,
154
			Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
155
		Integer numberOfResults = dao.countDescriptionElements(description, features, type);
156
		
157
		List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
158
		if(numberOfResults > 0) { // no point checking again
159
			results = dao.getDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
160
		}
161
		return results;
162
	}
163
	public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
164
		Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
165
		
166
		List<Annotation> results = new ArrayList<Annotation>();
167
		if(numberOfResults > 0) { // no point checking again
168
			results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths); 
169
		}
170
		
171
		return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
172
	}
173
	
174
	
175

    
176
	public Pager<Media> getMedia(DescriptionElementBase descriptionElement,	Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
177
        Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
178
		
179
		List<Media> results = new ArrayList<Media>();
180
		if(numberOfResults > 0) { // no point checking again
181
			results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths); 
182
		}
183
		
184
		return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
185
	}
186

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

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

    
253
	
254
	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) {
255
        Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
256
		
257
		List<DescriptionBase> results = new ArrayList<DescriptionBase>();
258
		if(numberOfResults > 0) { // no point checking again
259
			results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths); 
260
		}
261
		
262
		return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
263
	}
264

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

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

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

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

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

    
337
	public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
338
		return (TermVocabulary)vocabularyDao.findByUuid(uuid);
339
	}
340

    
341
	public List<DescriptionElementBase> getDescriptionElementsForTaxon(
342
			Taxon taxon, Set<Feature> features,
343
			Class<? extends DescriptionElementBase> type, Integer pageSize,
344
			Integer pageNumber, List<String> propertyPaths) {
345
		 return dao.getDescriptionElementForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
346
	}
347

    
348
	/* (non-Javadoc)
349
	 * @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)
350
	 */
351
	@Override
352
	public String generateNaturalLanguageDescription(FeatureTree featureTree,
353
			TaxonDescription description, List<Language> preferredLanguages, String separator) {
354
		
355
		Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
356
		
357
		description = (TaxonDescription)load(description.getUuid());
358
		featureTree = featureTreeDao.load(featureTree.getUuid());
359
		
360
		StringBuilder naturalLanguageDescription = new StringBuilder();
361
		
362
		if(description.hasStructuredData()){
363
			
364
			List<TextData> textDataList = naturalLanguageGenerator.generateNaturalLanguageDescription(
365
					featureTree, 
366
					((TaxonDescription)description),
367
					lang);
368
			
369
			String lastCategory = null;
370
			String categorySeparator = "; ";
371
			
372
			String sep = separator;
373

    
374
			for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
375
				if(textData.getMultilanguageText().size() > 0){
376
					
377
					if (!textData.getFeature().equals(Feature.UNKNOWN())) {
378
						String featureLabel = textData.getFeature().getLabel(lang);
379
						
380
						/*
381
						 *  WARNING
382
						 *  The code lines below are desinged to handle
383
						 *  a special case where as the fealure label contains 
384
						 *  hirarchical information on the features. This code 
385
						 *  exist only as a base for discussion, and is not 
386
						 *  intendet to be used in production.
387
						 */
388
						featureLabel = StringUtils.remove(featureLabel, '>');
389
						
390
						String[] labelTokens = StringUtils.split(featureLabel, '<');
391
						if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
392
							if(naturalLanguageDescription.length() > 0){
393
								naturalLanguageDescription.append(separator);
394
}
395
							naturalLanguageDescription.append(labelTokens[1]);
396
						} else {
397
							if(naturalLanguageDescription.length() > 0){
398
								naturalLanguageDescription.append(categorySeparator);
399
							}
400
							naturalLanguageDescription.append(StringUtils.join(labelTokens));
401
						}
402
						lastCategory = labelTokens[0];
403
						// end of demo code
404
					}
405
					String text = textData.getMultilanguageText().values().iterator().next().getText();
406
					naturalLanguageDescription.append(text);		
407
					
408
				}
409
			}
410
		
411
		}
412
		return naturalLanguageDescription.toString();
413
	}
414

    
415
	/* (non-Javadoc)
416
	 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
417
	 */
418
	@Override
419
	public boolean hasStructuredData(DescriptionBase<?> description) {
420
		return load(description.getUuid()).hasStructuredData();
421
	}
422
}
(14-14/67)