3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Collection
;
15 import java
.util
.HashSet
;
16 import java
.util
.List
;
19 import java
.util
.UUID
;
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
;
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
;
67 @Transactional(readOnly
= true, propagation
= Propagation
.SUPPORTS
)
68 public class DescriptionServiceImpl
extends IdentifiableServiceBase
<DescriptionBase
,IDescriptionDao
> implements IDescriptionService
{
70 private static final Logger logger
= Logger
.getLogger(DescriptionServiceImpl
.class);
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
;
83 protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao
) {
84 this.featureTreeDao
= featureTreeDao
;
88 protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao
) {
89 this.featureNodeDao
= featureNodeDao
;
93 protected void setFeatureDao(IFeatureDao featureDao
) {
94 this.featureDao
= featureDao
;
98 protected void setVocabularyDao(ITermVocabularyDao vocabularyDao
) {
99 this.vocabularyDao
= vocabularyDao
;
103 protected void setDefinedTermDao(IDefinedTermDao definedTermDao
) {
104 this.definedTermDao
= definedTermDao
;
108 protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao
) {
109 this.statisticalMeasurementValueDao
= statisticalMeasurementValueDao
;
113 protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao
) {
114 this.descriptionElementDao
= descriptionElementDao
;
118 protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator
) {
119 this.naturalLanguageGenerator
= naturalLanguageGenerator
;
125 public DescriptionServiceImpl() {
126 logger
.debug("Load DescriptionService Bean");
132 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
135 @Transactional(readOnly
= false)
136 public void updateTitleCache(Class
<?
extends DescriptionBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<DescriptionBase
> cacheStrategy
, IProgressMonitor monitor
) {
138 clazz
= DescriptionBase
.class;
140 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
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
);
151 protected void setDao(IDescriptionDao dao
) {
155 public int count(Class
<?
extends DescriptionBase
> type
, Boolean hasImages
, Boolean hasText
,Set
<Feature
> feature
) {
156 return dao
.countDescriptions(type
, hasImages
, hasText
, feature
);
160 * FIXME Candidate for harmonization
161 * rename -> getElements
163 public Pager
<DescriptionElementBase
> getDescriptionElements(DescriptionBase description
,
164 Set
<Feature
> features
, Class
<?
extends DescriptionElementBase
> type
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
166 List
<DescriptionElementBase
> results
= listDescriptionElements(description
, features
, type
, pageSize
, pageNumber
, propertyPaths
);
167 return new DefaultPagerImpl
<DescriptionElementBase
>(pageNumber
, results
.size(), pageSize
, results
);
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
);
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
);
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
);
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
);
189 return new DefaultPagerImpl
<Annotation
>(pageNumber
, numberOfResults
, pageSize
, results
);
194 public Pager
<Media
> getMedia(DescriptionElementBase descriptionElement
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
195 Integer numberOfResults
= descriptionElementDao
.countMedia(descriptionElement
);
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
);
202 return new DefaultPagerImpl
<Media
>(pageNumber
, numberOfResults
, pageSize
, results
);
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
);
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
);
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)
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
);
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
);
227 return new DefaultPagerImpl
<TaxonDescription
>(pageNumber
, numberOfResults
, pageSize
, results
);
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
);
237 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listTaxonDescriptionMedia(UUID, boolean, Set, Integer, Integer, List)
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
);
245 * @see IDescriptionService#countTaxonDescriptionMedia(UUID, boolean, Set)
248 public int countTaxonDescriptionMedia(UUID taxonUuid
, boolean limitToGalleries
, Set
<MarkerType
> markerTypes
){
249 return this.dao
.countTaxonDescriptionMedia(taxonUuid
, limitToGalleries
, markerTypes
);
255 public DistributionTree
getOrderedDistributions(
256 Set
<TaxonDescription
> taxonDescriptions
,
257 Set
<NamedAreaLevel
> omitLevels
,
258 List
<String
> propertyPaths
){
260 DistributionTree tree
= new DistributionTree();
261 List
<Distribution
> distList
= new ArrayList
<Distribution
>();
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
);
277 tree
.orderAsTree(distList
, omitLevels
);
282 public Pager
<TaxonNameDescription
> getTaxonNameDescriptions(TaxonNameBase name
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
283 Integer numberOfResults
= dao
.countTaxonNameDescriptions(name
);
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
);
290 return new DefaultPagerImpl
<TaxonNameDescription
>(pageNumber
, numberOfResults
, pageSize
, results
);
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
);
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
);
302 return new DefaultPagerImpl
<DescriptionBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
306 * FIXME Candidate for harmonization
307 * Rename: searchByDistribution
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
);
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
);
317 return new DefaultPagerImpl
<TaxonDescription
>(pageNumber
, numberOfResults
, pageSize
, results
);
321 * FIXME Candidate for harmonization
322 * move: descriptionElementService.search
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
);
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
);
332 return new DefaultPagerImpl
<DescriptionElementBase
>(pageNumber
, numberOfResults
, pageSize
, results
);
336 * FIXME Candidate for harmonization
337 * descriptionElementService.find
339 public DescriptionElementBase
getDescriptionElementByUuid(UUID uuid
) {
340 return descriptionElementDao
.findByUuid(uuid
);
344 * FIXME Candidate for harmonization
345 * descriptionElementService.load
347 public DescriptionElementBase
loadDescriptionElement(UUID uuid
, List
<String
> propertyPaths
) {
348 return descriptionElementDao
.load(uuid
, propertyPaths
);
352 * FIXME Candidate for harmonization
353 * descriptionElementService.save
355 @Transactional(readOnly
= false)
356 public UUID
saveDescriptionElement(DescriptionElementBase descriptionElement
) {
357 return descriptionElementDao
.save(descriptionElement
);
361 * FIXME Candidate for harmonization
362 * descriptionElementService.save
364 @Transactional(readOnly
= false)
365 public Map
<UUID
, DescriptionElementBase
> saveDescriptionElement(Collection
<DescriptionElementBase
> descriptionElements
) {
366 return descriptionElementDao
.saveAll(descriptionElements
);
370 * FIXME Candidate for harmonization
371 * descriptionElementService.delete
373 public UUID
deleteDescriptionElement(DescriptionElementBase descriptionElement
) {
374 return descriptionElementDao
.delete(descriptionElement
);
377 public TermVocabulary
<Feature
> getFeatureVocabulary(UUID uuid
) {
378 return (TermVocabulary
)vocabularyDao
.findByUuid(uuid
);
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
) {
386 return (List
<T
>) dao
.getDescriptionElementForTaxon(taxon
, features
, type
, pageSize
, pageNumber
, propertyPaths
);
389 public List
<DescriptionElementBase
> getDescriptionElementsForTaxon(
390 Taxon taxon
, FeatureTree featureTree
,
391 Class
<?
extends DescriptionElementBase
> type
, Integer pageSize
,
392 Integer pageNumber
, List
<String
> propertyPaths
) {
394 return (List
<DescriptionElementBase
>) dao
.getDescriptionElementForTaxon(taxon
, featureTree
.getDistinctFeatures(), type
, pageSize
, pageNumber
, propertyPaths
);
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)
401 public String
generateNaturalLanguageDescription(FeatureTree featureTree
,
402 TaxonDescription description
, List
<Language
> preferredLanguages
, String separator
) {
404 Language lang
= preferredLanguages
.size() > 0 ? preferredLanguages
.get(0) : Language
.DEFAULT();
406 description
= (TaxonDescription
)load(description
.getUuid());
407 featureTree
= featureTreeDao
.load(featureTree
.getUuid());
409 StringBuilder naturalLanguageDescription
= new StringBuilder();
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;
423 if(description
.hasStructuredData() && !isUseDescription
){
426 String lastCategory
= null;
427 String categorySeparator
= ". ";
429 List
<TextData
> textDataList
;
430 TextData naturalLanguageDescriptionText
= null;
432 boolean useMicroFormatQuantitativeDescriptionBuilder
= false;
434 if(useMicroFormatQuantitativeDescriptionBuilder
){
436 MicroFormatQuantitativeDescriptionBuilder micro
= new MicroFormatQuantitativeDescriptionBuilder();
437 naturalLanguageGenerator
.setQuantitativeDescriptionBuilder(micro
);
438 naturalLanguageDescriptionText
= naturalLanguageGenerator
.generateSingleTextData(featureTree
, ((TaxonDescription
)description
), lang
);
442 naturalLanguageDescriptionText
= naturalLanguageGenerator
.generateSingleTextData(
444 ((TaxonDescription
)description
),
448 return naturalLanguageDescriptionText
.getText(lang
);
451 // boolean doItBetter = false;
453 // for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
454 // if(textData.getMultilanguageText().size() > 0){
456 // if (!textData.getFeature().equals(Feature.UNKNOWN())) {
457 // String featureLabel = textData.getFeature().getLabel(lang);
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.
468 // featureLabel = StringUtils.remove(featureLabel, '>');
470 // String[] labelTokens = StringUtils.split(featureLabel, '<');
471 // if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
472 // if(naturalLanguageDescription.length() > 0){
473 // naturalLanguageDescription.append(separator);
475 // naturalLanguageDescription.append(labelTokens[1]);
477 // if(naturalLanguageDescription.length() > 0){
478 // naturalLanguageDescription.append(categorySeparator);
480 // naturalLanguageDescription.append(StringUtils.join(labelTokens));
482 // lastCategory = labelTokens[0];
483 // // end of demo code
485 // if(naturalLanguageDescription.length() > 0){
486 // naturalLanguageDescription.append(separator);
488 // naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
491 // if(naturalLanguageDescription.length() > 0){
492 // naturalLanguageDescription.append(separator);
495 // String text = textData.getMultilanguageText().values().iterator().next().getText();
496 // naturalLanguageDescription.append(text);
502 else if (isUseDescription
) {
503 //AT: Left Blank in case we need to generate a Natural language text string.
505 return naturalLanguageDescription
.toString();
509 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
512 public boolean hasStructuredData(DescriptionBase
<?
> description
) {
513 return load(description
.getUuid()).hasStructuredData();
518 * @see eu.etaxonomy.cdm.api.service.IDescriptionService#moveDescriptionElementsToDescription(java.util.Collection, eu.etaxonomy.cdm.model.description.DescriptionBase, boolean)
521 public void moveDescriptionElementsToDescription(Collection
<DescriptionElementBase
> descriptionElements
,
522 DescriptionBase targetDescription
, boolean isCopy
) {
524 if (descriptionElements
.isEmpty() ){
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;
534 for (DescriptionElementBase element
: descriptionElements
){
535 DescriptionBase description
= element
.getInDescription();
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
);
543 description
.removeElement(element
);