- removed @Cascade for country in GatheringEvent because DefinedTerms should not...
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / DescriptionServiceImpl.java
index e679e37938fe771db68478f7e881cf349894b6c4..e0a7fee8c398717932ac00c190bc2b727579e691 100644 (file)
@@ -1,9 +1,9 @@
 // $Id$
 /**
 * Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy 
+* European Distributed Institute of Taxonomy
 * http://www.e-taxonomy.eu
-* 
+*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * See LICENSE.TXT at the top of this package for the full license terms.
 */
@@ -12,22 +12,26 @@ package eu.etaxonomy.cdm.api.service;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
-import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
 import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
+import eu.etaxonomy.cdm.api.utility.DescriptionUtility;
+import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
 import eu.etaxonomy.cdm.model.common.Annotation;
+import eu.etaxonomy.cdm.model.common.DefinedTerm;
 import eu.etaxonomy.cdm.model.common.Language;
+import eu.etaxonomy.cdm.model.common.Marker;
 import eu.etaxonomy.cdm.model.common.MarkerType;
 import eu.etaxonomy.cdm.model.common.TermVocabulary;
 import eu.etaxonomy.cdm.model.description.DescriptionBase;
@@ -36,7 +40,6 @@ import eu.etaxonomy.cdm.model.description.Distribution;
 import eu.etaxonomy.cdm.model.description.Feature;
 import eu.etaxonomy.cdm.model.description.FeatureTree;
 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
-import eu.etaxonomy.cdm.model.description.Scope;
 import eu.etaxonomy.cdm.model.description.TaxonDescription;
 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
 import eu.etaxonomy.cdm.model.description.TextData;
@@ -45,6 +48,7 @@ import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
 import eu.etaxonomy.cdm.model.media.Media;
 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
@@ -53,379 +57,599 @@ import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
 import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
 import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
 import eu.etaxonomy.cdm.persistence.query.OrderHint;
+import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
 
 /**
  * @author a.mueller
  * @created 24.06.2008
  * @version 1.0
  */
+/**
+ * @author a.kohlbecker
+ * @date Dec 5, 2013
+ *
+ */
 @Service
-@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
+@Transactional(readOnly = true)
 public class DescriptionServiceImpl extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao> implements IDescriptionService {
-       
-       private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
-
-       protected IDescriptionElementDao descriptionElementDao;
-       protected IFeatureTreeDao featureTreeDao;
-       protected IFeatureNodeDao featureNodeDao;
-       protected IFeatureDao featureDao;
-       protected ITermVocabularyDao vocabularyDao;
-       protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
-       private INaturalLanguageGenerator naturalLanguageGenerator;
-       
-       @Autowired
-       protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
-               this.featureTreeDao = featureTreeDao;
-       }
-       
-       @Autowired
-       protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
-               this.featureNodeDao = featureNodeDao;
-       }
-       
-       @Autowired
-       protected void setFeatureDao(IFeatureDao featureDao) {
-               this.featureDao = featureDao;
-       }
-       
-       @Autowired
-       protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
-               this.vocabularyDao = vocabularyDao;
-       }
-       
-       @Autowired
-       protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
-               this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
-       }
-       
-       @Autowired
-       protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
-               this.descriptionElementDao = descriptionElementDao;
-       }
-       
-       @Autowired
-       protected void setNaturalLanguageGenerator(INaturalLanguageGenerator naturalLanguageGenerator) {
-               this.naturalLanguageGenerator = naturalLanguageGenerator;
-       }
-       
-       /**
-        * 
-        */
-       public DescriptionServiceImpl() {
-               logger.debug("Load DescriptionService Bean");
-       }
-       
-       /* (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache()
-        */
-       @Override
-       public void updateTitleCache() {
-               Class<DescriptionBase> clazz = DescriptionBase.class;
-               super.updateTitleCache(clazz, null, null);
-       }
-       
-       public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
-               String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
-               UUID featureUuid = UUID.fromString(uuidFeature);
-               return (TermVocabulary)vocabularyDao.findByUuid(featureUuid);
-       }
-
-       @Autowired
-       protected void setDao(IDescriptionDao dao) {
-               this.dao = dao;
-       }
-
-       public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
-               return dao.countDescriptions(type, hasImages, hasText, feature);
-       }
-
-       /**
-        * FIXME Candidate for harmonization
-        * rename -> getElements
-        */
-       public Pager<DescriptionElementBase> getDescriptionElements(DescriptionBase description,
-                       Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
-
-               List<DescriptionElementBase> results = listDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
-               return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, results.size(), pageSize, results);
-       }
-
-       public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description,
-                       Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
-               Integer numberOfResults = dao.countDescriptionElements(description, features, type);
-               
-               List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths);
-               }
-               return results;
-       }
-       public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
-               Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
-               
-               List<Annotation> results = new ArrayList<Annotation>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
-       }
-       
-       
-
-       public Pager<Media> getMedia(DescriptionElementBase descriptionElement, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+
+    private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
+
+    protected IDescriptionElementDao descriptionElementDao;
+    protected IFeatureTreeDao featureTreeDao;
+    protected IFeatureNodeDao featureNodeDao;
+    protected IFeatureDao featureDao;
+    protected ITermVocabularyDao vocabularyDao;
+    protected IDefinedTermDao definedTermDao;
+    protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
+    //TODO change to Interface
+    private NaturalLanguageGenerator naturalLanguageGenerator;
+
+    @Autowired
+    protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
+        this.featureTreeDao = featureTreeDao;
+    }
+
+    @Autowired
+    protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
+        this.featureNodeDao = featureNodeDao;
+    }
+
+    @Autowired
+    protected void setFeatureDao(IFeatureDao featureDao) {
+        this.featureDao = featureDao;
+    }
+
+    @Autowired
+    protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
+        this.vocabularyDao = vocabularyDao;
+    }
+
+    @Autowired
+    protected void setDefinedTermDao(IDefinedTermDao definedTermDao) {
+        this.definedTermDao = definedTermDao;
+    }
+
+    @Autowired
+    protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
+        this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
+    }
+
+    @Autowired
+    protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
+        this.descriptionElementDao = descriptionElementDao;
+    }
+
+    @Autowired
+    protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
+        this.naturalLanguageGenerator = naturalLanguageGenerator;
+    }
+
+    /**
+     *
+     */
+    public DescriptionServiceImpl() {
+        logger.debug("Load DescriptionService Bean");
+    }
+
+
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)
+     */
+    @Override
+    @Transactional(readOnly = false)
+    public void updateTitleCache(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
+        if (clazz == null){
+            clazz = DescriptionBase.class;
+        }
+        super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
+    }
+
+
+    @Override
+    public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
+        String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
+        UUID featureUuid = UUID.fromString(uuidFeature);
+        return vocabularyDao.findByUuid(featureUuid);
+    }
+
+    @Override
+    @Autowired
+    protected void setDao(IDescriptionDao dao) {
+        this.dao = dao;
+    }
+
+    @Override
+    public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
+        return dao.countDescriptions(type, hasImages, hasText, feature);
+    }
+
+    @Override
+    public Pager<DescriptionElementBase> pageDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
+            Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+
+        List<DescriptionElementBase> results = listDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
+        return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, results.size(), pageSize, results);
+    }
+
+    /* (non-Javadoc)
+     * @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)
+     */
+    @Override
+    @Deprecated
+    public Pager<DescriptionElementBase> getDescriptionElements(DescriptionBase description,
+            Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        return pageDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
+    }
+
+    @Override
+    public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
+            Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+
+        Integer numberOfResults = dao.countDescriptionElements(description, descriptionType, features, type);
+        List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
+        if(AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), pageNumber, pageSize)) {
+            results = dao.getDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
+        }
+        return results;
+    }
+
+    /* (non-Javadoc)
+     * @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)
+     */
+    @Override
+    @Deprecated
+    public List<DescriptionElementBase> listDescriptionElements(DescriptionBase description,
+            Set<Feature> features, Class<? extends DescriptionElementBase> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+
+        return listDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
+    }
+
+    @Override
+    public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
+        Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
+
+        List<Annotation> results = new ArrayList<Annotation>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths);
+        }
+
+        return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+
+
+    @Override
+    public Pager<Media> getMedia(DescriptionElementBase descriptionElement,    Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
         Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
-               
-               List<Media> results = new ArrayList<Media>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
-       }
-
-       public Pager<TaxonDescription> getTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
-        Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope);
-               
-               List<TaxonDescription> results = new ArrayList<TaxonDescription>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getTaxonDescriptions(taxon, scopes, geographicalScope, pageSize, pageNumber, propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
-       }
-       
-       public NamedAreaTree getOrderedDistributions(Set<TaxonDescription> taxonDescriptions, Set<NamedAreaLevel> omitLevels){
-               List<NamedArea> areaList = new ArrayList<NamedArea>();
-               NamedAreaTree tree = new NamedAreaTree();
-               //getting all the areas
-               for (TaxonDescription taxonDescription : taxonDescriptions) {
-                       taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid());
-                       Set<DescriptionElementBase> elements = taxonDescription.getElements();
-                       for (DescriptionElementBase element : elements) {
-                               if(element.isInstanceOf(Distribution.class)){
-                                       Distribution distribution = (Distribution) element;
-                                       areaList.add(distribution.getArea());
-                               }
-                       }
-               }
-               //ordering the areas
-               tree.merge(areaList, omitLevels);
-               tree.sortChildren();
-               return tree;    
-       }
-       
-       public DistributionTree getOrderedDistributionsB(
-                       Set<TaxonDescription> taxonDescriptions,
-                       Set<NamedAreaLevel> omitLevels){
-               
-               DistributionTree tree = new DistributionTree();
-               List<Distribution> distList = new ArrayList<Distribution>();
-               
-               for (TaxonDescription taxonDescription : taxonDescriptions) {
-                       taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid());
-                       Set<DescriptionElementBase> elements = taxonDescription.getElements();
-                       for (DescriptionElementBase element : elements) {
-                               if(element.isInstanceOf(Distribution.class)){
-                                       Distribution distribution = (Distribution) element;
-                                       distList.add(distribution);
-                               }
-                       }
-               }
-               
-               //ordering the areas
-               tree.merge(distList, omitLevels);
-               tree.sortChildren();
-               return tree;
-       }
-
-       public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+
+        List<Media> results = new ArrayList<Media>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths);
+        }
+
+        return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+    @Override
+    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        Set<MarkerType> markerTypes = null;
+        return pageTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
+    }
+
+    @Override
+    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        Set<MarkerType> markerTypes = null;
+        return listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
+    }
+
+
+    /* (non-Javadoc)
+     * @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)
+     */
+    @Override
+    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
+
+        List<TaxonDescription> results = new ArrayList<TaxonDescription>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
+        }
+
+        return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+    @Override
+    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        List<TaxonDescription> results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
+        return results;
+    }
+
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listTaxonDescriptionMedia(UUID, boolean, Set, Integer, Integer, List)
+     */
+    @Override
+    public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
+        return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
+    }
+
+    /*
+     * @see IDescriptionService#countTaxonDescriptionMedia(UUID, boolean, Set)
+     */
+    @Override
+    public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
+        return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
+    }
+
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#getOrderedDistributions(java.util.Set, boolean, boolean, java.util.Set, java.util.List)
+     */
+    @Override
+    @Deprecated
+    public DistributionTree getOrderedDistributions(
+            Set<TaxonDescription> taxonDescriptions,
+            boolean subAreaPreference,
+            boolean statusOrderPreference,
+            Set<MarkerType> hideMarkedAreas,
+            Set<NamedAreaLevel> omitLevels, List<String> propertyPaths){
+
+        List<Distribution> distList = new ArrayList<Distribution>();
+
+        List<UUID> uuids = new ArrayList<UUID>();
+        for (TaxonDescription taxonDescription : taxonDescriptions) {
+            if (! taxonDescription.isImageGallery()){    //image galleries should not have descriptions, but better filter fully on DTYPE of description element
+                uuids.add(taxonDescription.getUuid());
+            }
+        }
+
+        List<DescriptionBase> desclist = dao.list(uuids, null, null, null, propertyPaths);
+        for (DescriptionBase desc : desclist) {
+            if (desc.isInstanceOf(TaxonDescription.class)){
+                Set<DescriptionElementBase> elements = desc.getElements();
+                for (DescriptionElementBase element : elements) {
+                        if (element.isInstanceOf(Distribution.class)) {
+                            Distribution distribution = (Distribution) element;
+                            if(distribution.getArea() != null){
+                                distList.add(distribution);
+                            }
+                        }
+                }
+            }
+        }
+
+        //old
+//        for (TaxonDescription taxonDescription : taxonDescriptions) {
+//            if (logger.isDebugEnabled()){ logger.debug("load taxon description " + taxonDescription.getUuid());}
+//             //TODO why not loading all description via .list ? This may improve performance
+//            taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
+//            Set<DescriptionElementBase> elements = taxonDescription.getElements();
+//            for (DescriptionElementBase element : elements) {
+//                    if (element.isInstanceOf(Distribution.class)) {
+//                        Distribution distribution = (Distribution) element;
+//                        if(distribution.getArea() != null){
+//                            distList.add(distribution);
+//                        }
+//                    }
+//            }
+//        }
+
+        if (logger.isDebugEnabled()){logger.debug("filter tree for " + distList.size() + " distributions ...");}
+
+        // filter distributions
+        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distList, subAreaPreference, statusOrderPreference, hideMarkedAreas);
+        distList.clear();
+        distList.addAll(filteredDistributions);
+
+        return DescriptionUtility.orderDistributions(omitLevels, distList);
+    }
+
+
+    @Override
+    public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
         Integer numberOfResults = dao.countTaxonNameDescriptions(name);
-               
-               List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
-       }
-
-       
-       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) {
+
+        List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
+        }
+
+        return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+
+    @Override
+    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) {
         Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
-               
-               List<DescriptionBase> results = new ArrayList<DescriptionBase>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
-       }
-
-       /**
-        * FIXME Candidate for harmonization
-        * Rename: searchByDistribution
-        */
-       public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase presence,     Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
+
+        List<DescriptionBase> results = new ArrayList<DescriptionBase>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
+        }
+
+        return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+    /**
+     * FIXME Candidate for harmonization
+     * Rename: searchByDistribution
+     */
+    @Override
+    public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase presence,        Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
         Integer numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
-               
-               List<TaxonDescription> results = new ArrayList<TaxonDescription>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
-       }
-
-       /**
-        * FIXME Candidate for harmonization
-        * move: descriptionElementService.search
-        */
-       public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
-        Integer numberOfResults = descriptionElementDao.count(clazz,queryString);
-               
-               List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths); 
-               }
-               
-               return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
-       }
-
-       /**
-        * FIXME Candidate for harmonization
-        * descriptionElementService.find
-        */
-       public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
-               return descriptionElementDao.findByUuid(uuid);
-       }       
-       
-       /**
-        * FIXME Candidate for harmonization
-        * descriptionElementService.load
-        */
-       public DescriptionElementBase loadDescriptionElement(UUID uuid, List<String> propertyPaths) {
-               return descriptionElementDao.load(uuid, propertyPaths);
-       }
+
+        List<TaxonDescription> results = new ArrayList<TaxonDescription>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
+        }
+
+        return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+    /**
+     * FIXME Candidate for harmonization
+     * move: descriptionElementService.search
+     */
+    @Override
+    public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
+        Integer numberOfResults = descriptionElementDao.count(clazz, queryString);
+
+        List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
+        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+            results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
+        }
+
+        return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
+    }
+
+    /**
+     * FIXME Candidate for harmonization
+     * descriptionElementService.find
+     */
+    @Override
+    public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
+        return descriptionElementDao.findByUuid(uuid);
+    }
+
+    /**
+     * FIXME Candidate for harmonization
+     * descriptionElementService.load
+     */
+    @Override
+    public DescriptionElementBase loadDescriptionElement(UUID uuid,    List<String> propertyPaths) {
+        return descriptionElementDao.load(uuid, propertyPaths);
+    }
 
     /**
      * FIXME Candidate for harmonization
      * descriptionElementService.save
      */
-       @Transactional(readOnly = false)
-       public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
-               return descriptionElementDao.save(descriptionElement);
-       }
-       
+    @Override
+    @Transactional(readOnly = false)
+    public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
+        return descriptionElementDao.save(descriptionElement);
+    }
+
     /**
      * FIXME Candidate for harmonization
      * descriptionElementService.save
      */
-       @Transactional(readOnly = false)
-       public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
-               return descriptionElementDao.saveAll(descriptionElements);
-       }
+    @Override
+    @Transactional(readOnly = false)
+    public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
+        return descriptionElementDao.saveAll(descriptionElements);
+    }
 
     /**
      * FIXME Candidate for harmonization
      * descriptionElementService.delete
      */
-       public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
-               return descriptionElementDao.delete(descriptionElement);
-       }
-
-       public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
-               return (TermVocabulary)vocabularyDao.findByUuid(uuid);
-       }
-
-       public List<DescriptionElementBase> getDescriptionElementsForTaxon(
-                       Taxon taxon, Set<Feature> features,
-                       Class<? extends DescriptionElementBase> type, Integer pageSize,
-                       Integer pageNumber, List<String> propertyPaths) {
-                return dao.getDescriptionElementForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
-       }
-
-       /* (non-Javadoc)
-        * @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)
-        */
-       @Override
-       public String generateNaturalLanguageDescription(FeatureTree featureTree,
-                       TaxonDescription description, List<Language> preferredLanguages, String separator) {
-               
-               Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
-               
-               description = (TaxonDescription)load(description.getUuid());
-               featureTree = featureTreeDao.load(featureTree.getUuid());
-               
-               StringBuilder naturalLanguageDescription = new StringBuilder();
-               
-               if(description.hasStructuredData()){
-                       
-                       List<TextData> textDataList = naturalLanguageGenerator.generateNaturalLanguageDescription(
-                                       featureTree, 
-                                       ((TaxonDescription)description),
-                                       lang);
-                       
-                       String lastCategory = null;
-                       String categorySeparator = ". ";
-                       
-                       String sep = separator;
-                       
-                       boolean doItBetter = true;
-
-                       for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
-                               if(textData.getMultilanguageText().size() > 0){
-                                       
-                                       if (!textData.getFeature().equals(Feature.UNKNOWN())) {
-                                               String featureLabel = textData.getFeature().getLabel(lang);
-
-                                               if(doItBetter){
-                                               /*
-                                                *  WARNING
-                                                *  The code lines below are desinged to handle
-                                                *  a special case where as the fealure label contains 
-                                                *  hirarchical information on the features. This code 
-                                                *  exist only as a base for discussion, and is not 
-                                                *  intendet to be used in production.
-                                                */
-                                               featureLabel = StringUtils.remove(featureLabel, '>');
-                                               
-                                               String[] labelTokens = StringUtils.split(featureLabel, '<');
-                                               if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
-                                                       if(naturalLanguageDescription.length() > 0){
-                                                               naturalLanguageDescription.append(separator);
-}
-                                                       naturalLanguageDescription.append(labelTokens[1]);
-                                               } else {
-                                                       if(naturalLanguageDescription.length() > 0){
-                                                               naturalLanguageDescription.append(categorySeparator);
-                                                       }
-                                                       naturalLanguageDescription.append(StringUtils.join(labelTokens));
-                                               }
-                                               lastCategory = labelTokens[0];
-                                               // end of demo code
-                                               } else {
-                                                       if(naturalLanguageDescription.length() > 0){
-                                                               naturalLanguageDescription.append(categorySeparator);
-                                                       }
-                                                       naturalLanguageDescription.append(textData.getFeature().getLabel(lang));                                                        
-                                               }
-                                       }
-                                       String text = textData.getMultilanguageText().values().iterator().next().getText();
-                                       naturalLanguageDescription.append(text);                
-                                       
-                               }
-                       }
-               
-               }
-               return naturalLanguageDescription.toString();
-       }
-
-       /* (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
-        */
-       @Override
-       public boolean hasStructuredData(DescriptionBase<?> description) {
-               return load(description.getUuid()).hasStructuredData();
-       }
+    @Override
+    public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
+        return descriptionElementDao.delete(descriptionElement);
+    }
+
+    @Override
+    public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
+        return vocabularyDao.findByUuid(uuid);
+    }
+
+    @Override
+    @Deprecated
+    public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
+            Taxon taxon, Set<Feature> features,
+            Class<T> type, Integer pageSize,
+            Integer pageNumber, List<String> propertyPaths) {
+        return listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
+    }
+
+    @Override
+    public <T extends DescriptionElementBase> List<T> listDescriptionElementsForTaxon(
+            Taxon taxon, Set<Feature> features,
+            Class<T> type, Integer pageSize,
+            Integer pageNumber, List<String> propertyPaths) {
+        return dao.getDescriptionElementForTaxon(taxon.getUuid(), features, type, pageSize, pageNumber, propertyPaths);
+    }
+
+    @Override
+    public <T extends DescriptionElementBase> Pager<T> pageDescriptionElementsForTaxon(
+            Taxon taxon, Set<Feature> features,
+            Class<T> type, Integer pageSize,
+            Integer pageNumber, List<String> propertyPaths) {
+        if (logger.isDebugEnabled()){logger.debug(" get count ...");}
+        Long count = dao.countDescriptionElementForTaxon(taxon.getUuid(), features, type);
+        List<T> descriptionElements;
+        if(AbstractPagerImpl.hasResultsInRange(count, pageNumber, pageSize)){ // no point checking again
+            if (logger.isDebugEnabled()){logger.debug(" get list ...");}
+            descriptionElements = listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
+        } else {
+            descriptionElements = new ArrayList<T>(0);
+        }
+        if (logger.isDebugEnabled()){logger.debug(" service - DONE ...");}
+        return new DefaultPagerImpl<T>(pageNumber, count.intValue(), pageSize, descriptionElements);
+    }
+
+
+    /* (non-Javadoc)
+     * @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)
+     */
+    @Override
+    public String generateNaturalLanguageDescription(FeatureTree featureTree,
+            TaxonDescription description, List<Language> preferredLanguages, String separator) {
+
+        Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
+
+        description = (TaxonDescription)load(description.getUuid());
+        featureTree = featureTreeDao.load(featureTree.getUuid());
+
+        StringBuilder naturalLanguageDescription = new StringBuilder();
+
+        MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
+        boolean isUseDescription = false;
+        if(!description.getMarkers().isEmpty()) {
+            for (Marker marker: description.getMarkers()) {
+                MarkerType markerType = marker.getMarkerType();
+                if (markerType.equals(useMarkerType)) {
+                    isUseDescription = true;
+                }
+
+            }
+        }
+
+        if(description.hasStructuredData() && !isUseDescription){
+
+
+            String lastCategory = null;
+            String categorySeparator = ". ";
+
+            List<TextData> textDataList;
+            TextData naturalLanguageDescriptionText = null;
+
+            boolean useMicroFormatQuantitativeDescriptionBuilder = false;
+
+            if(useMicroFormatQuantitativeDescriptionBuilder){
+
+                MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
+                naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
+                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, (description), lang);
+
+            } else {
+
+                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
+                        featureTree,
+                        (description),
+                        lang);
+            }
+
+            return naturalLanguageDescriptionText.getText(lang);
+
+//
+//                     boolean doItBetter = false;
+//
+//                     for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
+//                             if(textData.getMultilanguageText().size() > 0){
+//
+//                                     if (!textData.getFeature().equals(Feature.UNKNOWN())) {
+//                                             String featureLabel = textData.getFeature().getLabel(lang);
+//
+//                                             if(doItBetter){
+//                                                     /*
+//                                                      *  WARNING
+//                                                      *  The code lines below are desinged to handle
+//                                                      *  a special case where as the feature label contains
+//                                                      *  hierarchical information on the features. This code
+//                                                      *  exist only as a base for discussion, and is not
+//                                                      *  intendet to be used in production.
+//                                                      */
+//                                                     featureLabel = StringUtils.remove(featureLabel, '>');
+//
+//                                                     String[] labelTokens = StringUtils.split(featureLabel, '<');
+//                                                     if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
+//                                                             if(naturalLanguageDescription.length() > 0){
+//                                                                     naturalLanguageDescription.append(separator);
+//                                                             }
+//                                                             naturalLanguageDescription.append(labelTokens[1]);
+//                                                     } else {
+//                                                             if(naturalLanguageDescription.length() > 0){
+//                                                                     naturalLanguageDescription.append(categorySeparator);
+//                                                             }
+//                                                             naturalLanguageDescription.append(StringUtils.join(labelTokens));
+//                                                     }
+//                                                     lastCategory = labelTokens[0];
+//                                                     // end of demo code
+//                                             } else {
+//                                                     if(naturalLanguageDescription.length() > 0){
+//                                                             naturalLanguageDescription.append(separator);
+//                                                     }
+//                                                     naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
+//                                             }
+//                                     } else {
+//                                             if(naturalLanguageDescription.length() > 0){
+//                                                     naturalLanguageDescription.append(separator);
+//                                             }
+//                                     }
+//                                     String text = textData.getMultilanguageText().values().iterator().next().getText();
+//                                     naturalLanguageDescription.append(text);
+//
+//                             }
+//                     }
+
+        }
+        else if (isUseDescription) {
+            //AT: Left Blank in case we need to generate a Natural language text string.
+        }
+        return naturalLanguageDescription.toString();
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#hasStructuredData(eu.etaxonomy.cdm.model.description.DescriptionBase)
+     */
+    @Override
+    public boolean hasStructuredData(DescriptionBase<?> description) {
+        return load(description.getUuid()).hasStructuredData();
+    }
+
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#moveDescriptionElementsToDescription(java.util.Collection, eu.etaxonomy.cdm.model.description.DescriptionBase, boolean)
+     */
+    @Override
+    public void moveDescriptionElementsToDescription(Collection<DescriptionElementBase> descriptionElements,
+                                                    DescriptionBase targetDescription, boolean isCopy) {
+
+        if (descriptionElements.isEmpty() ){
+            return ;
+        }
+
+        if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
+            //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
+            descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
+//                     descriptionElementsTmp.addAll(descriptionElements);
+//                     descriptionElements = descriptionElementsTmp;
+        }
+        for (DescriptionElementBase element : descriptionElements){
+            DescriptionBase description = element.getInDescription();
+            try {
+                DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
+                targetDescription.addElement(newElement);
+            } catch (CloneNotSupportedException e) {
+                new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
+            }
+            if (! isCopy){
+                description.removeElement(element);
+            }
+
+        }
+    }
+
+    @Override
+    public Pager<NamedArea> pageNamedAreasInUse(Integer pageSize,
+            Integer pageNumber, List<String> propertyPaths){
+
+        List<NamedArea> results = dao.listNamedAreasInUse(pageSize, pageNumber, propertyPaths);
+        return new DefaultPagerImpl<NamedArea>(pageNumber, results.size(), pageSize, results);
+    }
+
 }