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