Project

General

Profile

Download (35.3 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10

    
11
package eu.etaxonomy.cdm.api.service;
12

    
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.HashSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import org.apache.commons.lang.StringUtils;
22
import org.apache.log4j.Logger;
23
import org.springframework.beans.factory.annotation.Autowired;
24
import org.springframework.stereotype.Service;
25
import org.springframework.transaction.annotation.Transactional;
26

    
27
import eu.etaxonomy.cdm.api.service.pager.Pager;
28
import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
29
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
30
import eu.etaxonomy.cdm.api.utility.DescriptionUtility;
31
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
32
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
33
import eu.etaxonomy.cdm.model.common.Annotation;
34
import eu.etaxonomy.cdm.model.common.AnnotationType;
35
import eu.etaxonomy.cdm.model.common.CdmBase;
36
import eu.etaxonomy.cdm.model.common.DefinedTerm;
37
import eu.etaxonomy.cdm.model.common.Language;
38
import eu.etaxonomy.cdm.model.common.Marker;
39
import eu.etaxonomy.cdm.model.common.MarkerType;
40
import eu.etaxonomy.cdm.model.common.TermVocabulary;
41
import eu.etaxonomy.cdm.model.description.DescriptionBase;
42
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
43
import eu.etaxonomy.cdm.model.description.Distribution;
44
import eu.etaxonomy.cdm.model.description.Feature;
45
import eu.etaxonomy.cdm.model.description.FeatureTree;
46
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
47
import eu.etaxonomy.cdm.model.description.TaxonDescription;
48
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
49
import eu.etaxonomy.cdm.model.description.TextData;
50
import eu.etaxonomy.cdm.model.location.NamedArea;
51
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
52
import eu.etaxonomy.cdm.model.media.Media;
53
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
54
import eu.etaxonomy.cdm.model.taxon.Taxon;
55
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
56
import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
57
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
58
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
59
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureDao;
60
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureNodeDao;
61
import eu.etaxonomy.cdm.persistence.dao.description.IFeatureTreeDao;
62
import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
63
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
64
import eu.etaxonomy.cdm.persistence.dto.TermDto;
65
import eu.etaxonomy.cdm.persistence.query.OrderHint;
66
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
67

    
68
/**
69
 * @author a.mueller
70
 * @created 24.06.2008
71
 * @version 1.0
72
 */
73
/**
74
 * @author a.kohlbecker
75
 * @date Dec 5, 2013
76
 *
77
 */
78
@Service
79
@Transactional(readOnly = true)
80
public class DescriptionServiceImpl extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao> implements IDescriptionService {
81

    
82
    private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
83

    
84
    protected IDescriptionElementDao descriptionElementDao;
85
    protected IFeatureTreeDao featureTreeDao;
86
    protected IFeatureNodeDao featureNodeDao;
87
    protected IFeatureDao featureDao;
88
    protected ITermVocabularyDao vocabularyDao;
89
    protected IDefinedTermDao definedTermDao;
90
    protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
91
    protected ITaxonDao taxonDao;
92

    
93
    //TODO change to Interface
94
    private NaturalLanguageGenerator naturalLanguageGenerator;
95

    
96
    @Autowired
97
    protected void setFeatureTreeDao(IFeatureTreeDao featureTreeDao) {
98
        this.featureTreeDao = featureTreeDao;
99
    }
100

    
101
    @Autowired
102
    protected void setFeatureNodeDao(IFeatureNodeDao featureNodeDao) {
103
        this.featureNodeDao = featureNodeDao;
104
    }
105

    
106
    @Autowired
107
    protected void setFeatureDao(IFeatureDao featureDao) {
108
        this.featureDao = featureDao;
109
    }
110

    
111
    @Autowired
112
    protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
113
        this.vocabularyDao = vocabularyDao;
114
    }
115

    
116
    @Autowired
117
    protected void setDefinedTermDao(IDefinedTermDao definedTermDao) {
118
        this.definedTermDao = definedTermDao;
119
    }
120

    
121
    @Autowired
122
    protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
123
        this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
124
    }
125

    
126
    @Autowired
127
    protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
128
        this.descriptionElementDao = descriptionElementDao;
129
    }
130

    
131
    @Autowired
132
    protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
133
        this.naturalLanguageGenerator = naturalLanguageGenerator;
134
    }
135

    
136
    @Autowired
137
    protected void setTaxonDao(ITaxonDao taxonDao) {
138
        this.taxonDao = taxonDao;
139
    }
140

    
141
    /**
142
     *
143
     */
144
    public DescriptionServiceImpl() {
145
        logger.debug("Load DescriptionService Bean");
146
    }
147

    
148

    
149
    @Override
150
    @Transactional(readOnly = false)
151
    public void updateTitleCache(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
152
        if (clazz == null){
153
            clazz = DescriptionBase.class;
154
        }
155
        super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
156
    }
157

    
158

    
159
    @Override
160
    public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
161
        String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
162
        UUID featureUuid = UUID.fromString(uuidFeature);
163
        return vocabularyDao.findByUuid(featureUuid);
164
    }
165

    
166
    @Override
167
    @Autowired
168
    protected void setDao(IDescriptionDao dao) {
169
        this.dao = dao;
170
    }
171

    
172
    @Override
173
    public int count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
174
        return dao.countDescriptions(type, hasImages, hasText, feature);
175
    }
176

    
177
    @Override
178
    public <T extends DescriptionElementBase> Pager<T> pageDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
179
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
180

    
181
        List<T> results = listDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
182
        return new DefaultPagerImpl<T>(pageNumber, results.size(), pageSize, results);
183
    }
184

    
185
    @Override
186
    @Deprecated
187
    public <T extends DescriptionElementBase> Pager<T> getDescriptionElements(DescriptionBase description,
188
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
189
        return pageDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
190
    }
191

    
192

    
193

    
194
    @Override
195
    public <T extends DescriptionElementBase> List<T> listDescriptionElements(DescriptionBase description,
196
            Class<? extends DescriptionBase> descriptionType, Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber,
197
            List<String> propertyPaths) {
198

    
199
        Integer numberOfResults = dao.countDescriptionElements(description, descriptionType, features, type);
200
        List<T> results = new ArrayList<T>();
201
        if(AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), pageNumber, pageSize)) {
202
            results = dao.getDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
203
        }
204
        return results;
205

    
206
    }
207

    
208

    
209
    @Override
210
    @Deprecated
211
    public <T extends DescriptionElementBase> List<T> listDescriptionElements(DescriptionBase description,
212
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
213

    
214
        return listDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
215
    }
216

    
217
    @Override
218
    public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
219
        Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
220

    
221
        List<Annotation> results = new ArrayList<Annotation>();
222
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
223
            results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths);
224
        }
225

    
226
        return new DefaultPagerImpl<Annotation>(pageNumber, numberOfResults, pageSize, results);
227
    }
228

    
229

    
230

    
231
    @Override
232
    public Pager<Media> getMedia(DescriptionElementBase descriptionElement,	Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
233
        Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
234

    
235
        List<Media> results = new ArrayList<Media>();
236
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
237
            results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths);
238
        }
239

    
240
        return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
241
    }
242

    
243
    @Override
244
    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
245
        Set<MarkerType> markerTypes = null;
246
        return pageTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
247
    }
248

    
249
    @Override
250
    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
251
        Set<MarkerType> markerTypes = null;
252
        return listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
253
    }
254

    
255

    
256
    /* (non-Javadoc)
257
     * @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)
258
     */
259
    @Override
260
    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
261
        Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
262

    
263
        List<TaxonDescription> results = new ArrayList<TaxonDescription>();
264
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
265
            results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
266
        }
267

    
268
        return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
269
    }
270

    
271
    @Override
272
    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
273
        List<TaxonDescription> results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, pageSize, pageNumber, propertyPaths);
274
        return results;
275
    }
276

    
277

    
278
    /* (non-Javadoc)
279
     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#listTaxonDescriptionMedia(UUID, boolean, Set, Integer, Integer, List)
280
     */
281
    @Override
282
    public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
283
        return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
284
    }
285

    
286
    /*
287
     * @see IDescriptionService#countTaxonDescriptionMedia(UUID, boolean, Set)
288
     */
289
    @Override
290
    public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
291
        return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
292
    }
293

    
294

    
295
    /* (non-Javadoc)
296
     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#getOrderedDistributions(java.util.Set, boolean, boolean, java.util.Set, java.util.List)
297
     */
298
    @Override
299
    @Deprecated
300
    public DistributionTree getOrderedDistributions(
301
            Set<TaxonDescription> taxonDescriptions,
302
            boolean subAreaPreference,
303
            boolean statusOrderPreference,
304
            Set<MarkerType> hiddenAreaMarkerTypes,
305
            Set<NamedAreaLevel> omitLevels, List<String> propertyPaths){
306

    
307
        List<Distribution> distList = new ArrayList<Distribution>();
308

    
309
        List<UUID> uuids = new ArrayList<UUID>();
310
        for (TaxonDescription taxonDescription : taxonDescriptions) {
311
            if (! taxonDescription.isImageGallery()){    //image galleries should not have descriptions, but better filter fully on DTYPE of description element
312
                uuids.add(taxonDescription.getUuid());
313
            }
314
        }
315

    
316
        List<DescriptionBase> desclist = dao.list(uuids, null, null, null, propertyPaths);
317
        for (DescriptionBase desc : desclist) {
318
            if (desc.isInstanceOf(TaxonDescription.class)){
319
                Set<DescriptionElementBase> elements = desc.getElements();
320
                for (DescriptionElementBase element : elements) {
321
                        if (element.isInstanceOf(Distribution.class)) {
322
                            Distribution distribution = (Distribution) element;
323
                            if(distribution.getArea() != null){
324
                                distList.add(distribution);
325
                            }
326
                        }
327
                }
328
            }
329
        }
330

    
331
        //old
332
//        for (TaxonDescription taxonDescription : taxonDescriptions) {
333
//            if (logger.isDebugEnabled()){ logger.debug("load taxon description " + taxonDescription.getUuid());}
334
//        	//TODO why not loading all description via .list ? This may improve performance
335
//            taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
336
//            Set<DescriptionElementBase> elements = taxonDescription.getElements();
337
//            for (DescriptionElementBase element : elements) {
338
//                    if (element.isInstanceOf(Distribution.class)) {
339
//                        Distribution distribution = (Distribution) element;
340
//                        if(distribution.getArea() != null){
341
//                            distList.add(distribution);
342
//                        }
343
//                    }
344
//            }
345
//        }
346

    
347
        if (logger.isDebugEnabled()){logger.debug("filter tree for " + distList.size() + " distributions ...");}
348

    
349
        // filter distributions
350
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distList, hiddenAreaMarkerTypes, true, statusOrderPreference, false);
351
        distList.clear();
352
        distList.addAll(filteredDistributions);
353

    
354
        return DescriptionUtility.orderDistributions(definedTermDao, omitLevels, distList, hiddenAreaMarkerTypes);
355
    }
356

    
357

    
358
    @Override
359
    public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
360
        Integer numberOfResults = dao.countTaxonNameDescriptions(name);
361

    
362
        List<TaxonNameDescription> results = new ArrayList<TaxonNameDescription>();
363
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
364
            results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
365
        }
366

    
367
        return new DefaultPagerImpl<TaxonNameDescription>(pageNumber, numberOfResults, pageSize, results);
368
    }
369

    
370

    
371
    @Override
372
    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) {
373
        Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
374

    
375
        List<DescriptionBase> results = new ArrayList<DescriptionBase>();
376
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
377
            results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
378
        }
379

    
380
        return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
381
    }
382

    
383
    /**
384
     * FIXME Candidate for harmonization
385
     * Rename: searchByDistribution
386
     */
387
    @Override
388
    public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm presence,	Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
389
        Integer numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
390

    
391
        List<TaxonDescription> results = new ArrayList<TaxonDescription>();
392
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
393
            results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
394
        }
395

    
396
        return new DefaultPagerImpl<TaxonDescription>(pageNumber, numberOfResults, pageSize, results);
397
    }
398

    
399
    /**
400
     * FIXME Candidate for harmonization
401
     * move: descriptionElementService.search
402
     */
403
    @Override
404
    public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
405
        Integer numberOfResults = descriptionElementDao.count(clazz, queryString);
406

    
407
        List<DescriptionElementBase> results = new ArrayList<DescriptionElementBase>();
408
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
409
            results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
410
        }
411

    
412
        return new DefaultPagerImpl<DescriptionElementBase>(pageNumber, numberOfResults, pageSize, results);
413
    }
414

    
415
    /**
416
     * FIXME Candidate for harmonization
417
     * descriptionElementService.find
418
     */
419
    @Override
420
    public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
421
        return descriptionElementDao.findByUuid(uuid);
422
    }
423

    
424
    /**
425
     * FIXME Candidate for harmonization
426
     * descriptionElementService.load
427
     */
428
    @Override
429
    public DescriptionElementBase loadDescriptionElement(UUID uuid,	List<String> propertyPaths) {
430
        return descriptionElementDao.load(uuid, propertyPaths);
431
    }
432

    
433
    /**
434
     * FIXME Candidate for harmonization
435
     * descriptionElementService.save
436
     */
437
    @Override
438
    @Transactional(readOnly = false)
439
    public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
440
        return descriptionElementDao.save(descriptionElement).getUuid();
441
    }
442

    
443
    /**
444
     * FIXME Candidate for harmonization
445
     * descriptionElementService.save
446
     */
447
    @Override
448
    @Transactional(readOnly = false)
449
    public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
450
        return descriptionElementDao.saveAll(descriptionElements);
451
    }
452

    
453
    /**
454
     * FIXME Candidate for harmonization
455
     * descriptionElementService.delete
456
     */
457
    @Override
458
    public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
459
        return descriptionElementDao.delete(descriptionElement);
460
    }
461

    
462

    
463
    /* (non-Javadoc)
464
     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#deleteDescriptionElement(java.util.UUID)
465
     */
466
    @Override
467
    public UUID deleteDescriptionElement(UUID descriptionElementUuid) {
468
        return deleteDescriptionElement(descriptionElementDao.load(descriptionElementUuid));
469
    }
470

    
471
    @Override
472
    @Transactional(readOnly = false)
473
    public DeleteResult deleteDescription(DescriptionBase description) {
474
        DeleteResult deleteResult = new DeleteResult();
475

    
476
    	if (description instanceof TaxonDescription){
477
    		TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
478
    		Taxon tax = taxDescription.getTaxon();
479
    		tax.removeDescription(taxDescription, true);
480
    		dao.delete(description);
481

    
482
            deleteResult.addUpdatedObject(tax);
483
            deleteResult.setCdmEntity(tax);
484
    	}
485

    
486

    
487
        return deleteResult;
488
    }
489

    
490

    
491
    /* (non-Javadoc)
492
     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#deleteDescription(java.util.UUID)
493
     */
494
    @Override
495
    @Transactional(readOnly = false)
496
    public DeleteResult deleteDescription(UUID descriptionUuid) {
497
        return deleteDescription(dao.load(descriptionUuid));
498
    }
499

    
500

    
501
    @Override
502
    public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
503
        return vocabularyDao.findByUuid(uuid);
504
    }
505

    
506
    @Override
507
    @Deprecated
508
    public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
509
            Taxon taxon, Set<Feature> features,
510
            Class<T> type, Integer pageSize,
511
            Integer pageNumber, List<String> propertyPaths) {
512
        return listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
513
    }
514

    
515
    @Override
516
    public <T extends DescriptionElementBase> List<T> listDescriptionElementsForTaxon(
517
            Taxon taxon, Set<Feature> features,
518
            Class<T> type, Integer pageSize,
519
            Integer pageNumber, List<String> propertyPaths) {
520
        return dao.getDescriptionElementForTaxon(taxon.getUuid(), features, type, pageSize, pageNumber, propertyPaths);
521
    }
522

    
523
    @Override
524
    public <T extends DescriptionElementBase> Pager<T> pageDescriptionElementsForTaxon(
525
            Taxon taxon, Set<Feature> features,
526
            Class<T> type, Integer pageSize,
527
            Integer pageNumber, List<String> propertyPaths) {
528
        if (logger.isDebugEnabled()){logger.debug(" get count ...");}
529
        Long count = dao.countDescriptionElementForTaxon(taxon.getUuid(), features, type);
530
        List<T> descriptionElements;
531
        if(AbstractPagerImpl.hasResultsInRange(count, pageNumber, pageSize)){ // no point checking again
532
            if (logger.isDebugEnabled()){logger.debug(" get list ...");}
533
            descriptionElements = listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
534
        } else {
535
            descriptionElements = new ArrayList<T>(0);
536
        }
537
        if (logger.isDebugEnabled()){logger.debug(" service - DONE ...");}
538
        return new DefaultPagerImpl<T>(pageNumber, count.intValue(), pageSize, descriptionElements);
539
    }
540

    
541

    
542
    /* (non-Javadoc)
543
     * @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)
544
     */
545
    @Override
546
    public String generateNaturalLanguageDescription(FeatureTree featureTree,
547
            TaxonDescription description, List<Language> preferredLanguages, String separator) {
548

    
549
        Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
550

    
551
        description = (TaxonDescription)load(description.getUuid());
552
        featureTree = featureTreeDao.load(featureTree.getUuid());
553

    
554
        StringBuilder naturalLanguageDescription = new StringBuilder();
555

    
556
        MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
557
        boolean isUseDescription = false;
558
        if(!description.getMarkers().isEmpty()) {
559
            for (Marker marker: description.getMarkers()) {
560
                MarkerType markerType = marker.getMarkerType();
561
                if (markerType.equals(useMarkerType)) {
562
                    isUseDescription = true;
563
                }
564

    
565
            }
566
        }
567

    
568
        if(description.hasStructuredData() && !isUseDescription){
569

    
570

    
571
            String lastCategory = null;
572
            String categorySeparator = ". ";
573

    
574
            List<TextData> textDataList;
575
            TextData naturalLanguageDescriptionText = null;
576

    
577
            boolean useMicroFormatQuantitativeDescriptionBuilder = false;
578

    
579
            if(useMicroFormatQuantitativeDescriptionBuilder){
580

    
581
                MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
582
                naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
583
                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, (description), lang);
584

    
585
            } else {
586

    
587
                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
588
                        featureTree,
589
                        (description),
590
                        lang);
591
            }
592

    
593
            return naturalLanguageDescriptionText.getText(lang);
594

    
595
//
596
//			boolean doItBetter = false;
597
//
598
//			for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
599
//				if(textData.getMultilanguageText().size() > 0){
600
//
601
//					if (!textData.getFeature().equals(Feature.UNKNOWN())) {
602
//						String featureLabel = textData.getFeature().getLabel(lang);
603
//
604
//						if(doItBetter){
605
//							/*
606
//							 *  WARNING
607
//							 *  The code lines below are desinged to handle
608
//							 *  a special case where as the feature label contains
609
//							 *  hierarchical information on the features. This code
610
//							 *  exist only as a base for discussion, and is not
611
//							 *  intendet to be used in production.
612
//							 */
613
//							featureLabel = StringUtils.remove(featureLabel, '>');
614
//
615
//							String[] labelTokens = StringUtils.split(featureLabel, '<');
616
//							if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
617
//								if(naturalLanguageDescription.length() > 0){
618
//									naturalLanguageDescription.append(separator);
619
//								}
620
//								naturalLanguageDescription.append(labelTokens[1]);
621
//							} else {
622
//								if(naturalLanguageDescription.length() > 0){
623
//									naturalLanguageDescription.append(categorySeparator);
624
//								}
625
//								naturalLanguageDescription.append(StringUtils.join(labelTokens));
626
//							}
627
//							lastCategory = labelTokens[0];
628
//							// end of demo code
629
//						} else {
630
//							if(naturalLanguageDescription.length() > 0){
631
//								naturalLanguageDescription.append(separator);
632
//							}
633
//							naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
634
//						}
635
//					} else {
636
//						if(naturalLanguageDescription.length() > 0){
637
//							naturalLanguageDescription.append(separator);
638
//						}
639
//					}
640
//					String text = textData.getMultilanguageText().values().iterator().next().getText();
641
//					naturalLanguageDescription.append(text);
642
//
643
//				}
644
//			}
645

    
646
        }
647
        else if (isUseDescription) {
648
            //AT: Left Blank in case we need to generate a Natural language text string.
649
        }
650
        return naturalLanguageDescription.toString();
651
    }
652

    
653

    
654
    @Override
655
    public boolean hasStructuredData(DescriptionBase<?> description) {
656
        return load(description.getUuid()).hasStructuredData();
657
    }
658

    
659

    
660
    @Override
661
    @Transactional(readOnly = false)
662
    public UpdateResult moveDescriptionElementsToDescription(
663
            Collection<DescriptionElementBase> descriptionElements,
664
            DescriptionBase targetDescription,
665
            boolean isCopy) {
666

    
667
        UpdateResult result = new UpdateResult();
668
        if (descriptionElements.isEmpty() ){
669
            return result;
670
        }
671

    
672
        if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
673
            //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
674
            descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
675
//			descriptionElementsTmp.addAll(descriptionElements);
676
//			descriptionElements = descriptionElementsTmp;
677
        }
678
        for (DescriptionElementBase element : descriptionElements){
679
            DescriptionBase<?> description = element.getInDescription();
680
            try {
681
                DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
682
                targetDescription.addElement(newElement);
683
            } catch (CloneNotSupportedException e) {
684
                throw new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
685
            }
686
            if (! isCopy){
687
                description.removeElement(element);
688
                if (description.getElements().isEmpty()){
689
                   if (description instanceof TaxonDescription){
690
                       TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
691
                       if (taxDescription.getTaxon() != null){
692
                           taxDescription.getTaxon().removeDescription((TaxonDescription)description);
693
                       }
694
                   }
695
                    dao.delete(description);
696
                }else{
697
                    dao.saveOrUpdate(description);
698
                    result.addUpdatedObject(description);
699
                }
700
            }
701

    
702

    
703
        }
704
        dao.saveOrUpdate(targetDescription);
705
        result.addUpdatedObject(targetDescription);
706
        if (targetDescription instanceof TaxonDescription){
707
            result.addUpdatedObject(((TaxonDescription)targetDescription).getTaxon());
708
        }
709
        return result;
710
    }
711

    
712
    @Override
713
    @Transactional(readOnly = false)
714
    public UpdateResult moveDescriptionElementsToDescription(
715
            Set<UUID> descriptionElementUUIDs,
716
            UUID targetDescriptionUuid,
717
            boolean isCopy) {
718
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
719
        for(UUID deUuid : descriptionElementUUIDs) {
720
            descriptionElements.add(descriptionElementDao.load(deUuid));
721
        }
722
        DescriptionBase targetDescription = dao.load(targetDescriptionUuid);
723

    
724
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
725
    }
726

    
727
    @Override
728
    @Transactional(readOnly = false)
729
    public UpdateResult moveDescriptionElementsToDescription(
730
            Set<UUID> descriptionElementUUIDs,
731
            UUID targetTaxonUuid,
732
            String moveMessage,
733
            boolean isCopy) {
734
        Taxon targetTaxon = CdmBase.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
735
        DescriptionBase targetDescription = TaxonDescription.NewInstance(targetTaxon);
736
        targetDescription.setTitleCache(moveMessage, true);
737
        Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
738
        annotation.setAnnotationType(AnnotationType.TECHNICAL());
739
        targetDescription.addAnnotation(annotation);
740

    
741
        targetDescription = dao.save(targetDescription);
742
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
743
        for(UUID deUuid : descriptionElementUUIDs) {
744
            descriptionElements.add(descriptionElementDao.load(deUuid));
745
        }
746

    
747
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
748
    }
749

    
750
    @Override
751
    public Pager<TermDto> pageNamedAreasInUse(boolean includeAllParents, Integer pageSize,
752
            Integer pageNumber){
753
        List<TermDto> results = dao.listNamedAreasInUse(includeAllParents, null, null);
754
        int startIndex= pageNumber * pageSize;
755
        int toIndex = Math.min(startIndex + pageSize, results.size());
756
        List<TermDto> page = results.subList(startIndex, toIndex);
757
        return new DefaultPagerImpl<TermDto>(pageNumber, results.size(), pageSize, page);
758
    }
759

    
760

    
761
    @Override
762
    @Transactional(readOnly = false)
763
    public UpdateResult moveTaxonDescriptions(Taxon sourceTaxon, Taxon targetTaxon) {
764
        List<TaxonDescription> descriptions = new ArrayList(sourceTaxon.getDescriptions());
765
        UpdateResult result = new UpdateResult();
766
        result.addUpdatedObject(sourceTaxon);
767
        result.addUpdatedObject(targetTaxon);
768
        for(TaxonDescription description : descriptions){
769

    
770
            String moveMessage = String.format("Description moved from %s", sourceTaxon);
771
            if(description.isProtectedTitleCache()){
772
                String separator = "";
773
                if(!StringUtils.isBlank(description.getTitleCache())){
774
                    separator = " - ";
775
                }
776
                description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
777
            }
778
            Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
779
            annotation.setAnnotationType(AnnotationType.TECHNICAL());
780
            description.addAnnotation(annotation);
781
            targetTaxon.addDescription(description);
782
        }
783
        return result;
784
    }
785

    
786
    @Override
787
    @Transactional(readOnly = false)
788
    public UpdateResult moveTaxonDescriptions(UUID sourceTaxonUuid, UUID targetTaxonUuid) {
789
        Taxon sourceTaxon = HibernateProxyHelper.deproxy(taxonDao.load(sourceTaxonUuid), Taxon.class);
790
        Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
791
        return moveTaxonDescriptions(sourceTaxon, targetTaxon);
792

    
793
    }
794

    
795
    @Override
796
    @Transactional(readOnly = false)
797
    public UpdateResult moveTaxonDescription(UUID descriptionUuid, UUID targetTaxonUuid){
798
        UpdateResult result = new UpdateResult();
799
        TaxonDescription description = HibernateProxyHelper.deproxy(dao.load(descriptionUuid), TaxonDescription.class);
800

    
801
        Taxon sourceTaxon = description.getTaxon();
802
        String moveMessage = String.format("Description moved from %s", sourceTaxon);
803
        if(description.isProtectedTitleCache()){
804
            String separator = "";
805
            if(!StringUtils.isBlank(description.getTitleCache())){
806
                separator = " - ";
807
            }
808
            description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
809
        }
810
        Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
811
        annotation.setAnnotationType(AnnotationType.TECHNICAL());
812
        description.addAnnotation(annotation);
813
        Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
814
        targetTaxon.addDescription(description);
815
        result.addUpdatedObject(targetTaxon);
816
        result.addUpdatedObject(sourceTaxon);
817
       // dao.merge(description);
818
        return result;
819

    
820
    }
821

    
822

    
823

    
824
}
(16-16/97)