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