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