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