Merged sdd-branch to trunk.
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / DescriptionServiceImpl.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.api.service;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.apache.log4j.Logger;
22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.stereotype.Service;
24 import org.springframework.transaction.annotation.Propagation;
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.DefaultPagerImpl;
29 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
30 import eu.etaxonomy.cdm.model.common.Annotation;
31 import eu.etaxonomy.cdm.model.common.Language;
32 import eu.etaxonomy.cdm.model.common.Marker;
33 import eu.etaxonomy.cdm.model.common.MarkerType;
34 import eu.etaxonomy.cdm.model.common.TermVocabulary;
35 import eu.etaxonomy.cdm.model.description.DescriptionBase;
36 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
37 import eu.etaxonomy.cdm.model.description.Distribution;
38 import eu.etaxonomy.cdm.model.description.Feature;
39 import eu.etaxonomy.cdm.model.description.FeatureTree;
40 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
41 import eu.etaxonomy.cdm.model.description.Scope;
42 import eu.etaxonomy.cdm.model.description.TaxonDescription;
43 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
44 import eu.etaxonomy.cdm.model.description.TextData;
45 import eu.etaxonomy.cdm.model.location.NamedArea;
46 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
47 import eu.etaxonomy.cdm.model.media.Media;
48 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
49 import eu.etaxonomy.cdm.model.taxon.Taxon;
50 import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
51 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
52 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
53 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
54 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureDao;
55 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
56 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
57 import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
58 import eu.etaxonomy.cdm.persistence.query.OrderHint;
59 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
60
61 /**
62 * @author a.mueller
63 * @created 24.06.2008
64 * @version 1.0
65 */
66 @Service
67 @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
68 public class DescriptionServiceImpl extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao> implements IDescriptionService {
69
70 private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
71
72 protected IDescriptionElementDao descriptionElementDao;
73 protected IFeatureTreeDao featureTreeDao;
74 protected IFeatureNodeDao featureNodeDao;
75 protected IFeatureDao featureDao;
76 protected ITermVocabularyDao vocabularyDao;
77 protected IDefinedTermDao definedTermDao;
78 protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
79 //TODO change to Interface
80 private NaturalLanguageGenerator naturalLanguageGenerator;
81
82 @Autowired
83 protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
84 this.featureTreeDao = featureTreeDao;
85 }
86
87 @Autowired
88 protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
89 this.featureNodeDao = featureNodeDao;
90 }
91
92 @Autowired
93 protected void setFeatureDao(IFeatureDao featureDao) {
94 this.featureDao = featureDao;
95 }
96
97 @Autowired
98 protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
99 this.vocabularyDao = vocabularyDao;
100 }
101
102 @Autowired
103 protected void setDefinedTermDao(IDefinedTermDao definedTermDao) {
104 this.definedTermDao = definedTermDao;
105 }
106
107 @Autowired
108 protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
109 this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
110 }
111
112 @Autowired
113 protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
114 this.descriptionElementDao = descriptionElementDao;
115 }
116
117 @Autowired
118 protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
119 this.naturalLanguageGenerator = naturalLanguageGenerator;
120 }
121
122 /**
123 *
124 */
125 public DescriptionServiceImpl() {
126 logger.debug("Load DescriptionService Bean");
127 }
128
129
130
131 /* (non-Javadoc)
132 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
133 */
134 @Override
135 @Transactional(readOnly = false)
136 public void updateTitleCache(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
137 if (clazz == null){
138 clazz = DescriptionBase.class;
139 }
140 super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
141 }
142
143
144 public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
145 String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
146 UUID featureUuid = UUID.fromString(uuidFeature);
147 return (TermVocabulary)vocabularyDao.findByUuid(featureUuid);
148 }
149
150 @Autowired
151 protected void setDao(IDescriptionDao dao) {
152 this.dao = dao;
153 }
154
155 public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
156 return dao.countDescriptions(type, hasImages, hasText, feature);
157 }
158
159 /**
160 * FIXME Candidate for harmonization
161 * rename -> getElements
162 */
163 public Pager<DescriptionElementBase> getDescriptionElements(DescriptionBase description,
164 Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
165
166 List<DescriptionElementBase> results = listDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
167 return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, results.size(), pageSize, results);
168 }
169
170 public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description,
171 Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
172 Integer numberOfResults = dao.countDescriptionElements(description, features, type);
173
174 List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
175 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
176 results = dao.getDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
177 }
178 return results;
179 }
180
181 public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
182 Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
183
184 List<Annotation> results = new ArrayList<Annotation>();
185 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
186 results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths);
187 }
188
189 return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
190 }
191
192
193
194 public Pager<Media> getMedia(DescriptionElementBase descriptionElement, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
195 Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
196
197 List<Media> results = new ArrayList<Media>();
198 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
199 results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths);
200 }
201
202 return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
203 }
204
205 public Pager<TaxonDescription> getTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
206 Set<MarkerType> markerTypes = null;
207 return pageTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
208 }
209
210 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
211 Set<MarkerType> markerTypes = null;
212 return listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
213 }
214
215
216 /* (non-Javadoc)
217 * @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)
218 */
219 public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
220 Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
221
222 List<TaxonDescription> results = new ArrayList<TaxonDescription>();
223 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
224 results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
225 }
226
227 return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
228 }
229
230 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
231 List<TaxonDescription> results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
232 return results;
233 }
234
235
236 /* (non-Javadoc)
237 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listTaxonDescriptionMedia(UUID, boolean, Set, Integer, Integer, List)
238 */
239 @Override
240 public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
241 return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
242 }
243
244 /*
245 * @see IDescriptionService#countTaxonDescriptionMedia(UUID, boolean, Set)
246 */
247 @Override
248 public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
249 return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
250 }
251
252
253
254
255 public DistributionTree getOrderedDistributions(
256 Set<TaxonDescription> taxonDescriptions,
257 Set<NamedAreaLevel> omitLevels,
258 List<String> propertyPaths){
259
260 DistributionTree tree = new DistributionTree();
261 List<Distribution> distList = new ArrayList<Distribution>();
262
263 for (TaxonDescription taxonDescription : taxonDescriptions) {
264 taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
265 Set<DescriptionElementBase> elements = taxonDescription.getElements();
266 for (DescriptionElementBase element : elements) {
267 if (element.isInstanceOf(Distribution.class)) {
268 Distribution distribution = (Distribution) element;
269 if(distribution.getArea() != null){
270 distList.add(distribution);
271 }
272 }
273 }
274 }
275
276 //ordering the areas
277 tree.orderAsTree(distList, omitLevels);
278 tree.sortChildren();
279 return tree;
280 }
281
282 public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
283 Integer numberOfResults = dao.countTaxonNameDescriptions(name);
284
285 List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
286 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
287 results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
288 }
289
290 return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
291 }
292
293
294 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) {
295 Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
296
297 List<DescriptionBase> results = new ArrayList<DescriptionBase>();
298 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
299 results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
300 }
301
302 return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
303 }
304
305 /**
306 * FIXME Candidate for harmonization
307 * Rename: searchByDistribution
308 */
309 public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase presence, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
310 Integer numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
311
312 List<TaxonDescription> results = new ArrayList<TaxonDescription>();
313 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
314 results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
315 }
316
317 return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
318 }
319
320 /**
321 * FIXME Candidate for harmonization
322 * move: descriptionElementService.search
323 */
324 public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
325 Integer numberOfResults = descriptionElementDao.count(clazz, queryString);
326
327 List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
328 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
329 results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
330 }
331
332 return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
333 }
334
335 /**
336 * FIXME Candidate for harmonization
337 * descriptionElementService.find
338 */
339 public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
340 return descriptionElementDao.findByUuid(uuid);
341 }
342
343 /**
344 * FIXME Candidate for harmonization
345 * descriptionElementService.load
346 */
347 public DescriptionElementBase loadDescriptionElement(UUID uuid, List<String> propertyPaths) {
348 return descriptionElementDao.load(uuid, propertyPaths);
349 }
350
351 /**
352 * FIXME Candidate for harmonization
353 * descriptionElementService.save
354 */
355 @Transactional(readOnly = false)
356 public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
357 return descriptionElementDao.save(descriptionElement);
358 }
359
360 /**
361 * FIXME Candidate for harmonization
362 * descriptionElementService.save
363 */
364 @Transactional(readOnly = false)
365 public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
366 return descriptionElementDao.saveAll(descriptionElements);
367 }
368
369 /**
370 * FIXME Candidate for harmonization
371 * descriptionElementService.delete
372 */
373 public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
374 return descriptionElementDao.delete(descriptionElement);
375 }
376
377 public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
378 return (TermVocabulary)vocabularyDao.findByUuid(uuid);
379 }
380
381 public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
382 Taxon taxon, Set<Feature> features,
383 Class<? extends T> type, Integer pageSize,
384 Integer pageNumber, List<String> propertyPaths) {
385 //FIXME remove cast
386 return (List<T>) dao.getDescriptionElementForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
387 }
388
389 public List<DescriptionElementBase> getDescriptionElementsForTaxon(
390 Taxon taxon, FeatureTree featureTree,
391 Class<? extends DescriptionElementBase> type, Integer pageSize,
392 Integer pageNumber, List<String> propertyPaths) {
393 //FIXME remove cast
394 return (List<DescriptionElementBase>) dao.getDescriptionElementForTaxon(taxon, featureTree.getDistinctFeatures(), type, pageSize, pageNumber, propertyPaths);
395 }
396
397 /* (non-Javadoc)
398 * @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)
399 */
400 @Override
401 public String generateNaturalLanguageDescription(FeatureTree featureTree,
402 TaxonDescription description, List<Language> preferredLanguages, String separator) {
403
404 Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
405
406 description = (TaxonDescription)load(description.getUuid());
407 featureTree = featureTreeDao.load(featureTree.getUuid());
408
409 StringBuilder naturalLanguageDescription = new StringBuilder();
410
411 MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
412 boolean isUseDescription = false;
413 if(!description.getMarkers().isEmpty()) {
414 for (Marker marker: description.getMarkers()) {
415 MarkerType markerType = marker.getMarkerType();
416 if (markerType.equals(useMarkerType)) {
417 isUseDescription = true;
418 }
419
420 }
421 }
422
423 if(description.hasStructuredData() && !isUseDescription){
424
425
426 String lastCategory = null;
427 String categorySeparator = ". ";
428
429 List<TextData> textDataList;
430 TextData naturalLanguageDescriptionText = null;
431
432 boolean useMicroFormatQuantitativeDescriptionBuilder = false;
433
434 if(useMicroFormatQuantitativeDescriptionBuilder){
435
436 MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
437 naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
438 naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, ((TaxonDescription)description), lang);
439
440 } else {
441
442 naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
443 featureTree,
444 ((TaxonDescription)description),
445 lang);
446 }
447
448 return naturalLanguageDescriptionText.getText(lang);
449
450 //
451 // boolean doItBetter = false;
452 //
453 // for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
454 // if(textData.getMultilanguageText().size() > 0){
455 //
456 // if (!textData.getFeature().equals(Feature.UNKNOWN())) {
457 // String featureLabel = textData.getFeature().getLabel(lang);
458 //
459 // if(doItBetter){
460 // /*
461 // * WARNING
462 // * The code lines below are desinged to handle
463 // * a special case where as the feature label contains
464 // * hierarchical information on the features. This code
465 // * exist only as a base for discussion, and is not
466 // * intendet to be used in production.
467 // */
468 // featureLabel = StringUtils.remove(featureLabel, '>');
469 //
470 // String[] labelTokens = StringUtils.split(featureLabel, '<');
471 // if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
472 // if(naturalLanguageDescription.length() > 0){
473 // naturalLanguageDescription.append(separator);
474 // }
475 // naturalLanguageDescription.append(labelTokens[1]);
476 // } else {
477 // if(naturalLanguageDescription.length() > 0){
478 // naturalLanguageDescription.append(categorySeparator);
479 // }
480 // naturalLanguageDescription.append(StringUtils.join(labelTokens));
481 // }
482 // lastCategory = labelTokens[0];
483 // // end of demo code
484 // } else {
485 // if(naturalLanguageDescription.length() > 0){
486 // naturalLanguageDescription.append(separator);
487 // }
488 // naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
489 // }
490 // } else {
491 // if(naturalLanguageDescription.length() > 0){
492 // naturalLanguageDescription.append(separator);
493 // }
494 // }
495 // String text = textData.getMultilanguageText().values().iterator().next().getText();
496 // naturalLanguageDescription.append(text);
497 //
498 // }
499 // }
500
501 }
502 else if (isUseDescription) {
503 //AT: Left Blank in case we need to generate a Natural language text string.
504 }
505 return naturalLanguageDescription.toString();
506 }
507
508 /* (non-Javadoc)
509 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
510 */
511 @Override
512 public boolean hasStructuredData(DescriptionBase<?> description) {
513 return load(description.getUuid()).hasStructuredData();
514 }
515
516
517 /* (non-Javadoc)
518 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#moveDescriptionElementsToDescription(java.util.Collection, eu.etaxonomy.cdm.model.description.DescriptionBase, boolean)
519 */
520 @Override
521 public void moveDescriptionElementsToDescription(Collection<DescriptionElementBase> descriptionElements,
522 DescriptionBase targetDescription, boolean isCopy) {
523
524 if (descriptionElements.isEmpty() ){
525 return ;
526 }
527
528 if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
529 //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
530 descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
531 // descriptionElementsTmp.addAll(descriptionElements);
532 // descriptionElements = descriptionElementsTmp;
533 }
534 for (DescriptionElementBase element : descriptionElements){
535 DescriptionBase description = element.getInDescription();
536 try {
537 DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
538 targetDescription.addElement(newElement);
539 } catch (CloneNotSupportedException e) {
540 new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
541 }
542 if (! isCopy){
543 description.removeElement(element);
544 }
545
546 }
547 }
548
549 }