merge from trunk
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / DescriptionServiceImpl.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.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.commons.lang.StringUtils;
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.Transactional;
26
27 import eu.etaxonomy.cdm.api.service.pager.Pager;
28 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
29 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
30 import eu.etaxonomy.cdm.api.utility.DescriptionUtility;
31 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
32 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
33 import eu.etaxonomy.cdm.model.common.Annotation;
34 import eu.etaxonomy.cdm.model.common.AnnotationType;
35 import eu.etaxonomy.cdm.model.common.DefinedTerm;
36 import eu.etaxonomy.cdm.model.common.Language;
37 import eu.etaxonomy.cdm.model.common.Marker;
38 import eu.etaxonomy.cdm.model.common.MarkerType;
39 import eu.etaxonomy.cdm.model.common.TermVocabulary;
40 import eu.etaxonomy.cdm.model.description.DescriptionBase;
41 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
42 import eu.etaxonomy.cdm.model.description.Distribution;
43 import eu.etaxonomy.cdm.model.description.Feature;
44 import eu.etaxonomy.cdm.model.description.FeatureTree;
45 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
46 import eu.etaxonomy.cdm.model.description.TaxonDescription;
47 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
48 import eu.etaxonomy.cdm.model.description.TextData;
49 import eu.etaxonomy.cdm.model.location.NamedArea;
50 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
51 import eu.etaxonomy.cdm.model.media.Media;
52 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
53 import eu.etaxonomy.cdm.model.taxon.Taxon;
54 import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
55 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
56 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
57 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
58 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureDao;
59 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
60 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
61 import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
62 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
63 import eu.etaxonomy.cdm.persistence.query.OrderHint;
64 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
65
66 /**
67 * @author a.mueller
68 * @created 24.06.2008
69 * @version 1.0
70 */
71 /**
72 * @author a.kohlbecker
73 * @date Dec 5, 2013
74 *
75 */
76 @Service
77 @Transactional(readOnly = true)
78 public class DescriptionServiceImpl extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao> implements IDescriptionService {
79
80 private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
81
82 protected IDescriptionElementDao descriptionElementDao;
83 protected IFeatureTreeDao featureTreeDao;
84 protected IFeatureNodeDao featureNodeDao;
85 protected IFeatureDao featureDao;
86 protected ITermVocabularyDao vocabularyDao;
87 protected IDefinedTermDao definedTermDao;
88 protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
89 protected ITaxonDao taxonDao;
90
91 //TODO change to Interface
92 private NaturalLanguageGenerator naturalLanguageGenerator;
93
94 @Autowired
95 protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
96 this.featureTreeDao = featureTreeDao;
97 }
98
99 @Autowired
100 protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
101 this.featureNodeDao = featureNodeDao;
102 }
103
104 @Autowired
105 protected void setFeatureDao(IFeatureDao featureDao) {
106 this.featureDao = featureDao;
107 }
108
109 @Autowired
110 protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
111 this.vocabularyDao = vocabularyDao;
112 }
113
114 @Autowired
115 protected void setDefinedTermDao(IDefinedTermDao definedTermDao) {
116 this.definedTermDao = definedTermDao;
117 }
118
119 @Autowired
120 protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
121 this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
122 }
123
124 @Autowired
125 protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
126 this.descriptionElementDao = descriptionElementDao;
127 }
128
129 @Autowired
130 protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
131 this.naturalLanguageGenerator = naturalLanguageGenerator;
132 }
133
134 @Autowired
135 protected void setTaxonDao(ITaxonDao taxonDao) {
136 this.taxonDao = taxonDao;
137 }
138
139 /**
140 *
141 */
142 public DescriptionServiceImpl() {
143 logger.debug("Load DescriptionService Bean");
144 }
145
146
147
148 /* (non-Javadoc)
149 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
150 */
151 @Override
152 @Transactional(readOnly = false)
153 public void updateTitleCache(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
154 if (clazz == null){
155 clazz = DescriptionBase.class;
156 }
157 super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
158 }
159
160
161 @Override
162 public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
163 String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
164 UUID featureUuid = UUID.fromString(uuidFeature);
165 return vocabularyDao.findByUuid(featureUuid);
166 }
167
168 @Override
169 @Autowired
170 protected void setDao(IDescriptionDao dao) {
171 this.dao = dao;
172 }
173
174 @Override
175 public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
176 return dao.countDescriptions(type, hasImages, hasText, feature);
177 }
178
179 @Override
180 public Pager<DescriptionElementBase> pageDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
181 Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
182
183 List<DescriptionElementBase> results = listDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
184 return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, results.size(), pageSize, results);
185 }
186
187 /* (non-Javadoc)
188 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#getDescriptionElements(eu.etaxonomy.cdm.model.description.DescriptionBase, java.util.Set, java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List)
189 */
190 @Override
191 @Deprecated
192 public Pager<DescriptionElementBase> getDescriptionElements(DescriptionBase description,
193 Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
194 return pageDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
195 }
196
197 @Override
198 public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
199 Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
200
201 Integer numberOfResults = dao.countDescriptionElements(description, descriptionType, features, type);
202 List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
203 if(AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), pageNumber, pageSize)) {
204 results = dao.getDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
205 }
206 return results;
207 }
208
209 /* (non-Javadoc)
210 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listDescriptionElements(eu.etaxonomy.cdm.model.description.DescriptionBase, java.util.Set, java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List)
211 */
212 @Override
213 @Deprecated
214 public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description,
215 Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
216
217 return listDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
218 }
219
220 @Override
221 public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
222 Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
223
224 List<Annotation> results = new ArrayList<Annotation>();
225 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
226 results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths);
227 }
228
229 return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
230 }
231
232
233
234 @Override
235 public Pager<Media> getMedia(DescriptionElementBase descriptionElement, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
236 Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
237
238 List<Media> results = new ArrayList<Media>();
239 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
240 results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths);
241 }
242
243 return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
244 }
245
246 @Override
247 public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
248 Set<MarkerType> markerTypes = null;
249 return pageTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
250 }
251
252 @Override
253 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
254 Set<MarkerType> markerTypes = null;
255 return listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
256 }
257
258
259 /* (non-Javadoc)
260 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#pageMarkedTaxonDescriptions(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, java.util.Set, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)
261 */
262 @Override
263 public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
264 Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
265
266 List<TaxonDescription> results = new ArrayList<TaxonDescription>();
267 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
268 results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
269 }
270
271 return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
272 }
273
274 @Override
275 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
276 List<TaxonDescription> results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
277 return results;
278 }
279
280
281 /* (non-Javadoc)
282 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listTaxonDescriptionMedia(UUID, boolean, Set, Integer, Integer, List)
283 */
284 @Override
285 public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
286 return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
287 }
288
289 /*
290 * @see IDescriptionService#countTaxonDescriptionMedia(UUID, boolean, Set)
291 */
292 @Override
293 public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
294 return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
295 }
296
297
298 /* (non-Javadoc)
299 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#getOrderedDistributions(java.util.Set, boolean, boolean, java.util.Set, java.util.List)
300 */
301 @Override
302 @Deprecated
303 public DistributionTree getOrderedDistributions(
304 Set<TaxonDescription> taxonDescriptions,
305 boolean subAreaPreference,
306 boolean statusOrderPreference,
307 Set<MarkerType> hideMarkedAreas,
308 Set<NamedAreaLevel> omitLevels, List<String> propertyPaths){
309
310 List<Distribution> distList = new ArrayList<Distribution>();
311
312 List<UUID> uuids = new ArrayList<UUID>();
313 for (TaxonDescription taxonDescription : taxonDescriptions) {
314 if (! taxonDescription.isImageGallery()){ //image galleries should not have descriptions, but better filter fully on DTYPE of description element
315 uuids.add(taxonDescription.getUuid());
316 }
317 }
318
319 List<DescriptionBase> desclist = dao.list(uuids, null, null, null, propertyPaths);
320 for (DescriptionBase desc : desclist) {
321 if (desc.isInstanceOf(TaxonDescription.class)){
322 Set<DescriptionElementBase> elements = desc.getElements();
323 for (DescriptionElementBase element : elements) {
324 if (element.isInstanceOf(Distribution.class)) {
325 Distribution distribution = (Distribution) element;
326 if(distribution.getArea() != null){
327 distList.add(distribution);
328 }
329 }
330 }
331 }
332 }
333
334 //old
335 // for (TaxonDescription taxonDescription : taxonDescriptions) {
336 // if (logger.isDebugEnabled()){ logger.debug("load taxon description " + taxonDescription.getUuid());}
337 // //TODO why not loading all description via .list ? This may improve performance
338 // taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
339 // Set<DescriptionElementBase> elements = taxonDescription.getElements();
340 // for (DescriptionElementBase element : elements) {
341 // if (element.isInstanceOf(Distribution.class)) {
342 // Distribution distribution = (Distribution) element;
343 // if(distribution.getArea() != null){
344 // distList.add(distribution);
345 // }
346 // }
347 // }
348 // }
349
350 if (logger.isDebugEnabled()){logger.debug("filter tree for " + distList.size() + " distributions ...");}
351
352 // filter distributions
353 Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distList, subAreaPreference, statusOrderPreference, hideMarkedAreas);
354 distList.clear();
355 distList.addAll(filteredDistributions);
356
357 return DescriptionUtility.orderDistributions(omitLevels, distList);
358 }
359
360
361 @Override
362 public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
363 Integer numberOfResults = dao.countTaxonNameDescriptions(name);
364
365 List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
366 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
367 results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
368 }
369
370 return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
371 }
372
373
374 @Override
375 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) {
376 Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
377
378 List<DescriptionBase> results = new ArrayList<DescriptionBase>();
379 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
380 results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
381 }
382
383 return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
384 }
385
386 /**
387 * FIXME Candidate for harmonization
388 * Rename: searchByDistribution
389 */
390 @Override
391 public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm presence, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
392 Integer numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
393
394 List<TaxonDescription> results = new ArrayList<TaxonDescription>();
395 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
396 results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
397 }
398
399 return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
400 }
401
402 /**
403 * FIXME Candidate for harmonization
404 * move: descriptionElementService.search
405 */
406 @Override
407 public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
408 Integer numberOfResults = descriptionElementDao.count(clazz, queryString);
409
410 List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
411 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
412 results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
413 }
414
415 return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
416 }
417
418 /**
419 * FIXME Candidate for harmonization
420 * descriptionElementService.find
421 */
422 @Override
423 public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
424 return descriptionElementDao.findByUuid(uuid);
425 }
426
427 /**
428 * FIXME Candidate for harmonization
429 * descriptionElementService.load
430 */
431 @Override
432 public DescriptionElementBase loadDescriptionElement(UUID uuid, List<String> propertyPaths) {
433 return descriptionElementDao.load(uuid, propertyPaths);
434 }
435
436 /**
437 * FIXME Candidate for harmonization
438 * descriptionElementService.save
439 */
440 @Override
441 @Transactional(readOnly = false)
442 public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
443 return descriptionElementDao.save(descriptionElement);
444 }
445
446 /**
447 * FIXME Candidate for harmonization
448 * descriptionElementService.save
449 */
450 @Override
451 @Transactional(readOnly = false)
452 public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
453 return descriptionElementDao.saveAll(descriptionElements);
454 }
455
456 /**
457 * FIXME Candidate for harmonization
458 * descriptionElementService.delete
459 */
460 @Override
461 public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
462 return descriptionElementDao.delete(descriptionElement);
463 }
464
465 @Override
466 public UUID deleteDescription(DescriptionBase description) {
467 if (description instanceof TaxonDescription){
468 TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
469 Taxon tax = taxDescription.getTaxon();
470 tax.removeDescription(taxDescription, true);
471 }
472
473 return dao.delete(description);
474 }
475 @Override
476 public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
477 return vocabularyDao.findByUuid(uuid);
478 }
479
480 @Override
481 @Deprecated
482 public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
483 Taxon taxon, Set<Feature> features,
484 Class<T> type, Integer pageSize,
485 Integer pageNumber, List<String> propertyPaths) {
486 return listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
487 }
488
489 @Override
490 public <T extends DescriptionElementBase> List<T> listDescriptionElementsForTaxon(
491 Taxon taxon, Set<Feature> features,
492 Class<T> type, Integer pageSize,
493 Integer pageNumber, List<String> propertyPaths) {
494 return dao.getDescriptionElementForTaxon(taxon.getUuid(), features, type, pageSize, pageNumber, propertyPaths);
495 }
496
497 @Override
498 public <T extends DescriptionElementBase> Pager<T> pageDescriptionElementsForTaxon(
499 Taxon taxon, Set<Feature> features,
500 Class<T> type, Integer pageSize,
501 Integer pageNumber, List<String> propertyPaths) {
502 if (logger.isDebugEnabled()){logger.debug(" get count ...");}
503 Long count = dao.countDescriptionElementForTaxon(taxon.getUuid(), features, type);
504 List<T> descriptionElements;
505 if(AbstractPagerImpl.hasResultsInRange(count, pageNumber, pageSize)){ // no point checking again
506 if (logger.isDebugEnabled()){logger.debug(" get list ...");}
507 descriptionElements = listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
508 } else {
509 descriptionElements = new ArrayList<T>(0);
510 }
511 if (logger.isDebugEnabled()){logger.debug(" service - DONE ...");}
512 return new DefaultPagerImpl<T>(pageNumber, count.intValue(), pageSize, descriptionElements);
513 }
514
515
516 /* (non-Javadoc)
517 * @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)
518 */
519 @Override
520 public String generateNaturalLanguageDescription(FeatureTree featureTree,
521 TaxonDescription description, List<Language> preferredLanguages, String separator) {
522
523 Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
524
525 description = (TaxonDescription)load(description.getUuid());
526 featureTree = featureTreeDao.load(featureTree.getUuid());
527
528 StringBuilder naturalLanguageDescription = new StringBuilder();
529
530 MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
531 boolean isUseDescription = false;
532 if(!description.getMarkers().isEmpty()) {
533 for (Marker marker: description.getMarkers()) {
534 MarkerType markerType = marker.getMarkerType();
535 if (markerType.equals(useMarkerType)) {
536 isUseDescription = true;
537 }
538
539 }
540 }
541
542 if(description.hasStructuredData() && !isUseDescription){
543
544
545 String lastCategory = null;
546 String categorySeparator = ". ";
547
548 List<TextData> textDataList;
549 TextData naturalLanguageDescriptionText = null;
550
551 boolean useMicroFormatQuantitativeDescriptionBuilder = false;
552
553 if(useMicroFormatQuantitativeDescriptionBuilder){
554
555 MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
556 naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
557 naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, (description), lang);
558
559 } else {
560
561 naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
562 featureTree,
563 (description),
564 lang);
565 }
566
567 return naturalLanguageDescriptionText.getText(lang);
568
569 //
570 // boolean doItBetter = false;
571 //
572 // for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
573 // if(textData.getMultilanguageText().size() > 0){
574 //
575 // if (!textData.getFeature().equals(Feature.UNKNOWN())) {
576 // String featureLabel = textData.getFeature().getLabel(lang);
577 //
578 // if(doItBetter){
579 // /*
580 // * WARNING
581 // * The code lines below are desinged to handle
582 // * a special case where as the feature label contains
583 // * hierarchical information on the features. This code
584 // * exist only as a base for discussion, and is not
585 // * intendet to be used in production.
586 // */
587 // featureLabel = StringUtils.remove(featureLabel, '>');
588 //
589 // String[] labelTokens = StringUtils.split(featureLabel, '<');
590 // if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
591 // if(naturalLanguageDescription.length() > 0){
592 // naturalLanguageDescription.append(separator);
593 // }
594 // naturalLanguageDescription.append(labelTokens[1]);
595 // } else {
596 // if(naturalLanguageDescription.length() > 0){
597 // naturalLanguageDescription.append(categorySeparator);
598 // }
599 // naturalLanguageDescription.append(StringUtils.join(labelTokens));
600 // }
601 // lastCategory = labelTokens[0];
602 // // end of demo code
603 // } else {
604 // if(naturalLanguageDescription.length() > 0){
605 // naturalLanguageDescription.append(separator);
606 // }
607 // naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
608 // }
609 // } else {
610 // if(naturalLanguageDescription.length() > 0){
611 // naturalLanguageDescription.append(separator);
612 // }
613 // }
614 // String text = textData.getMultilanguageText().values().iterator().next().getText();
615 // naturalLanguageDescription.append(text);
616 //
617 // }
618 // }
619
620 }
621 else if (isUseDescription) {
622 //AT: Left Blank in case we need to generate a Natural language text string.
623 }
624 return naturalLanguageDescription.toString();
625 }
626
627 /* (non-Javadoc)
628 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
629 */
630 @Override
631 public boolean hasStructuredData(DescriptionBase<?> description) {
632 return load(description.getUuid()).hasStructuredData();
633 }
634
635
636 /* (non-Javadoc)
637 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#moveDescriptionElementsToDescription(java.util.Collection, eu.etaxonomy.cdm.model.description.DescriptionBase, boolean)
638 */
639 @Override
640 public void moveDescriptionElementsToDescription(Collection<DescriptionElementBase> descriptionElements,
641 DescriptionBase targetDescription, boolean isCopy) {
642
643 if (descriptionElements.isEmpty() ){
644 return ;
645 }
646
647 if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
648 //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
649 descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
650 // descriptionElementsTmp.addAll(descriptionElements);
651 // descriptionElements = descriptionElementsTmp;
652 }
653 for (DescriptionElementBase element : descriptionElements){
654 DescriptionBase description = element.getInDescription();
655 try {
656 DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
657 targetDescription.addElement(newElement);
658 } catch (CloneNotSupportedException e) {
659 new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
660 }
661 if (! isCopy){
662 description.removeElement(element);
663 }
664
665 }
666 }
667
668 @Override
669 public Pager<NamedArea> pageNamedAreasInUse(Integer pageSize,
670 Integer pageNumber, List<String> propertyPaths){
671
672 List<NamedArea> results = dao.listNamedAreasInUse(pageSize, pageNumber, propertyPaths);
673 return new DefaultPagerImpl<NamedArea>(pageNumber, results.size(), pageSize, results);
674 }
675
676
677 @Override
678 @Transactional(readOnly = false)
679 public void moveTaxonDescriptions(Taxon sourceTaxon, Taxon targetTaxon) {
680 List<TaxonDescription> descriptions = new ArrayList(sourceTaxon.getDescriptions());
681 for(TaxonDescription description : descriptions){
682
683 String moveMessage = String.format("Description moved from %s", sourceTaxon);
684 if(description.isProtectedTitleCache()){
685 String separator = "";
686 if(!StringUtils.isBlank(description.getTitleCache())){
687 separator = " - ";
688 }
689 description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
690 }
691 Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
692 annotation.setAnnotationType(AnnotationType.TECHNICAL());
693 description.addAnnotation(annotation);
694 targetTaxon.addDescription(description);
695 }
696 }
697
698 @Override
699 @Transactional(readOnly = false)
700 public void moveTaxonDescriptions(UUID sourceTaxonUuid, UUID targetTaxonUuid) {
701 Taxon sourceTaxon = HibernateProxyHelper.deproxy(taxonDao.load(sourceTaxonUuid), Taxon.class);
702 Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
703 moveTaxonDescriptions(sourceTaxon, targetTaxon);
704
705 }
706
707 }