Project

General

Profile

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

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

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

    
20
import org.apache.commons.lang.StringUtils;
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.Transactional;
25

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
149

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

    
159

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

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

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

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

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

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

    
193

    
194

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

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

    
207
    }
208

    
209

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

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

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

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

    
227
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
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
    @Override
256
    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
257
        long numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
258

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

    
264
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
265
    }
266

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

    
273

    
274
    @Override
275
    public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
276
        return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
277
    }
278

    
279
    @Override
280
    public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
281
        return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
282
    }
283

    
284
    @Override
285
    @Deprecated
286
    public DistributionTree getOrderedDistributions(
287
            Set<TaxonDescription> taxonDescriptions,
288
            boolean subAreaPreference,
289
            boolean statusOrderPreference,
290
            Set<MarkerType> hiddenAreaMarkerTypes,
291
            Set<NamedAreaLevel> omitLevels, List<String> propertyPaths){
292

    
293
        List<Distribution> distList = new ArrayList<Distribution>();
294

    
295
        List<UUID> uuids = new ArrayList<UUID>();
296
        for (TaxonDescription taxonDescription : taxonDescriptions) {
297
            if (! taxonDescription.isImageGallery()){    //image galleries should not have descriptions, but better filter fully on DTYPE of description element
298
                uuids.add(taxonDescription.getUuid());
299
            }
300
        }
301

    
302
        List<DescriptionBase> desclist = dao.list(uuids, null, null, null, propertyPaths);
303
        for (DescriptionBase desc : desclist) {
304
            if (desc.isInstanceOf(TaxonDescription.class)){
305
                Set<DescriptionElementBase> elements = desc.getElements();
306
                for (DescriptionElementBase element : elements) {
307
                        if (element.isInstanceOf(Distribution.class)) {
308
                            Distribution distribution = (Distribution) element;
309
                            if(distribution.getArea() != null){
310
                                distList.add(distribution);
311
                            }
312
                        }
313
                }
314
            }
315
        }
316

    
317
        //old
318
//        for (TaxonDescription taxonDescription : taxonDescriptions) {
319
//            if (logger.isDebugEnabled()){ logger.debug("load taxon description " + taxonDescription.getUuid());}
320
//        	//TODO why not loading all description via .list ? This may improve performance
321
//            taxonDescription = (TaxonDescription) dao.load(taxonDescription.getUuid(), propertyPaths);
322
//            Set<DescriptionElementBase> elements = taxonDescription.getElements();
323
//            for (DescriptionElementBase element : elements) {
324
//                    if (element.isInstanceOf(Distribution.class)) {
325
//                        Distribution distribution = (Distribution) element;
326
//                        if(distribution.getArea() != null){
327
//                            distList.add(distribution);
328
//                        }
329
//                    }
330
//            }
331
//        }
332

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

    
335
        // filter distributions
336
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distList, hiddenAreaMarkerTypes, true, statusOrderPreference, false);
337
        distList.clear();
338
        distList.addAll(filteredDistributions);
339

    
340
        return DescriptionUtility.orderDistributions(definedTermDao, omitLevels, distList, hiddenAreaMarkerTypes, null);
341
    }
342

    
343

    
344
    @Override
345
    public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonName name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
346
        long numberOfResults = dao.countTaxonNameDescriptions(name);
347

    
348
        List<TaxonNameDescription> results = new ArrayList<>();
349
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
350
            results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
351
        }
352

    
353
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
354
    }
355

    
356

    
357
    @Override
358
    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) {
359
        long numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
360

    
361
        @SuppressWarnings("rawtypes")
362
        List<DescriptionBase> results = new ArrayList<>();
363
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
364
            results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
365
        }
366

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

    
370
    /**
371
     * FIXME Candidate for harmonization
372
     * Rename: searchByDistribution
373
     */
374
    @Override
375
    public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm presence,	Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
376
        long numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
377

    
378
        List<TaxonDescription> results = new ArrayList<>();
379
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
380
            results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
381
        }
382

    
383
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
384
    }
385

    
386
    /**
387
     * FIXME Candidate for harmonization
388
     * move: descriptionElementService.search
389
     */
390
    @Override
391
    public Pager<DescriptionElementBase> searchElements(Class<? extends DescriptionElementBase> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
392
        long numberOfResults = descriptionElementDao.count(clazz, queryString);
393

    
394
        List<DescriptionElementBase> results = new ArrayList<>();
395
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
396
            results = descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
397
        }
398

    
399
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
400
    }
401

    
402
    /**
403
     * FIXME Candidate for harmonization
404
     * descriptionElementService.find
405
     */
406
    @Override
407
    public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
408
        return descriptionElementDao.findByUuid(uuid);
409
    }
410

    
411
    /**
412
     * FIXME Candidate for harmonization
413
     * descriptionElementService.load
414
     */
415
    @Override
416
    public DescriptionElementBase loadDescriptionElement(UUID uuid,	List<String> propertyPaths) {
417
        return descriptionElementDao.load(uuid, propertyPaths);
418
    }
419

    
420
    /**
421
     * FIXME Candidate for harmonization
422
     * descriptionElementService.save
423
     */
424
    @Override
425
    @Transactional(readOnly = false)
426
    public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
427
        return descriptionElementDao.save(descriptionElement).getUuid();
428
    }
429

    
430
    /**
431
     * FIXME Candidate for harmonization
432
     * descriptionElementService.save
433
     */
434
    @Override
435
    @Transactional(readOnly = false)
436
    public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
437
        return descriptionElementDao.saveAll(descriptionElements);
438
    }
439

    
440
    /**
441
     * FIXME Candidate for harmonization
442
     * descriptionElementService.delete
443
     */
444
    @Override
445
    public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
446
        return descriptionElementDao.delete(descriptionElement);
447
    }
448

    
449

    
450
    /* (non-Javadoc)
451
     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#deleteDescriptionElement(java.util.UUID)
452
     */
453
    @Override
454
    public UUID deleteDescriptionElement(UUID descriptionElementUuid) {
455
        return deleteDescriptionElement(descriptionElementDao.load(descriptionElementUuid));
456
    }
457

    
458
    @Override
459
    @Transactional(readOnly = false)
460
    public DeleteResult deleteDescription(DescriptionBase description) {
461
        DeleteResult deleteResult = new DeleteResult();
462

    
463
    	if (description instanceof TaxonDescription){
464
    		TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
465
    		Taxon tax = taxDescription.getTaxon();
466
    		tax.removeDescription(taxDescription, true);
467
    		dao.delete(description);
468
    		deleteResult.addDeletedObject(taxDescription);
469
            deleteResult.addUpdatedObject(tax);
470
            deleteResult.setCdmEntity(tax);
471
    	}
472

    
473

    
474
        return deleteResult;
475
    }
476

    
477

    
478
    /* (non-Javadoc)
479
     * @see eu.etaxonomy.cdm.api.service.IDescriptionService#deleteDescription(java.util.UUID)
480
     */
481
    @Override
482
    @Transactional(readOnly = false)
483
    public DeleteResult deleteDescription(UUID descriptionUuid) {
484
        return deleteDescription(dao.load(descriptionUuid));
485
    }
486

    
487

    
488
    @Override
489
    public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
490
        return vocabularyDao.findByUuid(uuid);
491
    }
492

    
493
    @Override
494
    @Deprecated
495
    public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
496
            Taxon taxon, Set<Feature> features,
497
            Class<T> type, Integer pageSize,
498
            Integer pageNumber, List<String> propertyPaths) {
499
        return listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
500
    }
501

    
502
    @Override
503
    public <T extends DescriptionElementBase> List<T> listDescriptionElementsForTaxon(
504
            Taxon taxon, Set<Feature> features,
505
            Class<T> type, Integer pageSize,
506
            Integer pageNumber, List<String> propertyPaths) {
507
        return dao.getDescriptionElementForTaxon(taxon.getUuid(), features, type, pageSize, pageNumber, propertyPaths);
508
    }
509

    
510
    @Override
511
    public <T extends DescriptionElementBase> Pager<T> pageDescriptionElementsForTaxon(
512
            Taxon taxon, Set<Feature> features,
513
            Class<T> type, Integer pageSize,
514
            Integer pageNumber, List<String> propertyPaths) {
515
        if (logger.isDebugEnabled()){logger.debug(" get count ...");}
516
        Long count = dao.countDescriptionElementForTaxon(taxon.getUuid(), features, type);
517
        List<T> descriptionElements;
518
        if(AbstractPagerImpl.hasResultsInRange(count, pageNumber, pageSize)){ // no point checking again
519
            if (logger.isDebugEnabled()){logger.debug(" get list ...");}
520
            descriptionElements = listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
521
        } else {
522
            descriptionElements = new ArrayList<T>(0);
523
        }
524
        if (logger.isDebugEnabled()){logger.debug(" service - DONE ...");}
525
        return new DefaultPagerImpl<T>(pageNumber, count, pageSize, descriptionElements);
526
    }
527

    
528

    
529
    /* (non-Javadoc)
530
     * @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)
531
     */
532
    @Override
533
    public String generateNaturalLanguageDescription(FeatureTree featureTree,
534
            TaxonDescription description, List<Language> preferredLanguages, String separator) {
535

    
536
        Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
537

    
538
        description = (TaxonDescription)load(description.getUuid());
539
        featureTree = featureTreeDao.load(featureTree.getUuid());
540

    
541
        StringBuilder naturalLanguageDescription = new StringBuilder();
542

    
543
        MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
544
        boolean isUseDescription = false;
545
        if(!description.getMarkers().isEmpty()) {
546
            for (Marker marker: description.getMarkers()) {
547
                MarkerType markerType = marker.getMarkerType();
548
                if (markerType.equals(useMarkerType)) {
549
                    isUseDescription = true;
550
                }
551

    
552
            }
553
        }
554

    
555
        if(description.hasStructuredData() && !isUseDescription){
556

    
557

    
558
            String lastCategory = null;
559
            String categorySeparator = ". ";
560

    
561
            List<TextData> textDataList;
562
            TextData naturalLanguageDescriptionText = null;
563

    
564
            boolean useMicroFormatQuantitativeDescriptionBuilder = false;
565

    
566
            if(useMicroFormatQuantitativeDescriptionBuilder){
567

    
568
                MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
569
                naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
570
                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, (description), lang);
571

    
572
            } else {
573

    
574
                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
575
                        featureTree,
576
                        (description),
577
                        lang);
578
            }
579

    
580
            return naturalLanguageDescriptionText.getText(lang);
581

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

    
633
        }
634
        else if (isUseDescription) {
635
            //AT: Left Blank in case we need to generate a Natural language text string.
636
        }
637
        return naturalLanguageDescription.toString();
638
    }
639

    
640

    
641
    @Override
642
    public boolean hasStructuredData(DescriptionBase<?> description) {
643
        return load(description.getUuid()).hasStructuredData();
644
    }
645

    
646

    
647
    @Override
648
    @Transactional(readOnly = false)
649
    public UpdateResult moveDescriptionElementsToDescription(
650
            Collection<DescriptionElementBase> descriptionElements,
651
            DescriptionBase targetDescription,
652
            boolean isCopy) {
653

    
654
        UpdateResult result = new UpdateResult();
655
        if (descriptionElements.isEmpty() ){
656
            return result;
657
        }
658

    
659
        if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
660
            //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
661
            descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
662
//			descriptionElementsTmp.addAll(descriptionElements);
663
//			descriptionElements = descriptionElementsTmp;
664
        }
665
        for (DescriptionElementBase element : descriptionElements){
666
            DescriptionBase<?> description = element.getInDescription();
667
            try {
668
                DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
669
                targetDescription.addElement(newElement);
670
            } catch (CloneNotSupportedException e) {
671
                throw new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
672
            }
673
            if (! isCopy){
674
                description.removeElement(element);
675
                if (description.getElements().isEmpty()){
676
                   if (description instanceof TaxonDescription){
677
                       TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
678
                       if (taxDescription.getTaxon() != null){
679
                           taxDescription.getTaxon().removeDescription((TaxonDescription)description);
680
                       }
681
                   }
682
                    dao.delete(description);
683

    
684
                }else{
685
                    dao.saveOrUpdate(description);
686
                    result.addUpdatedObject(description);
687
                }
688
            }
689

    
690

    
691
        }
692
        dao.saveOrUpdate(targetDescription);
693
        result.addUpdatedObject(targetDescription);
694
        if (targetDescription instanceof TaxonDescription){
695
            result.addUpdatedObject(((TaxonDescription)targetDescription).getTaxon());
696
        }
697
        return result;
698
    }
699

    
700
    @Override
701
    @Transactional(readOnly = false)
702
    public UpdateResult moveDescriptionElementsToDescription(
703
            Set<UUID> descriptionElementUUIDs,
704
            UUID targetDescriptionUuid,
705
            boolean isCopy) {
706
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
707
        for(UUID deUuid : descriptionElementUUIDs) {
708
            descriptionElements.add(descriptionElementDao.load(deUuid));
709
        }
710
        DescriptionBase targetDescription = dao.load(targetDescriptionUuid);
711

    
712
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
713
    }
714

    
715
    @Override
716
    @Transactional(readOnly = false)
717
    public UpdateResult moveDescriptionElementsToDescription(
718
            Set<UUID> descriptionElementUUIDs,
719
            UUID targetTaxonUuid,
720
            String moveMessage,
721
            boolean isCopy) {
722
        Taxon targetTaxon = CdmBase.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
723
        DescriptionBase targetDescription = TaxonDescription.NewInstance(targetTaxon);
724
        targetDescription.setTitleCache(moveMessage, true);
725
        Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
726
        annotation.setAnnotationType(AnnotationType.TECHNICAL());
727
        targetDescription.addAnnotation(annotation);
728

    
729
        targetDescription = dao.save(targetDescription);
730
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
731
        for(UUID deUuid : descriptionElementUUIDs) {
732
            descriptionElements.add(descriptionElementDao.load(deUuid));
733
        }
734

    
735
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
736
    }
737

    
738
    @Override
739
    public Pager<TermDto> pageNamedAreasInUse(boolean includeAllParents, Integer pageSize,
740
            Integer pageNumber){
741
        List<TermDto> results = dao.listNamedAreasInUse(includeAllParents, null, null);
742
        int startIndex= pageNumber * pageSize;
743
        int toIndex = Math.min(startIndex + pageSize, results.size());
744
        List<TermDto> page = results.subList(startIndex, toIndex);
745
        return new DefaultPagerImpl<TermDto>(pageNumber, results.size(), pageSize, page);
746
    }
747

    
748

    
749
    @Override
750
    @Transactional(readOnly = false)
751
    public UpdateResult moveTaxonDescriptions(Taxon sourceTaxon, Taxon targetTaxon) {
752
        List<TaxonDescription> descriptions = new ArrayList(sourceTaxon.getDescriptions());
753
        UpdateResult result = new UpdateResult();
754
        result.addUpdatedObject(sourceTaxon);
755
        result.addUpdatedObject(targetTaxon);
756
        for(TaxonDescription description : descriptions){
757

    
758
            String moveMessage = String.format("Description moved from %s", sourceTaxon);
759
            if(description.isProtectedTitleCache()){
760
                String separator = "";
761
                if(!StringUtils.isBlank(description.getTitleCache())){
762
                    separator = " - ";
763
                }
764
                description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
765
            }
766
            Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
767
            annotation.setAnnotationType(AnnotationType.TECHNICAL());
768
            description.addAnnotation(annotation);
769
            targetTaxon.addDescription(description);
770
        }
771
        return result;
772
    }
773

    
774
    @Override
775
    @Transactional(readOnly = false)
776
    public UpdateResult moveTaxonDescriptions(UUID sourceTaxonUuid, UUID targetTaxonUuid) {
777
        Taxon sourceTaxon = HibernateProxyHelper.deproxy(taxonDao.load(sourceTaxonUuid), Taxon.class);
778
        Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
779
        return moveTaxonDescriptions(sourceTaxon, targetTaxon);
780

    
781
    }
782

    
783
    @Override
784
    @Transactional(readOnly = false)
785
    public UpdateResult moveTaxonDescription(UUID descriptionUuid, UUID targetTaxonUuid){
786
        UpdateResult result = new UpdateResult();
787
        TaxonDescription description = HibernateProxyHelper.deproxy(dao.load(descriptionUuid), TaxonDescription.class);
788

    
789
        Taxon sourceTaxon = description.getTaxon();
790
        String moveMessage = String.format("Description moved from %s", sourceTaxon);
791
        if(description.isProtectedTitleCache()){
792
            String separator = "";
793
            if(!StringUtils.isBlank(description.getTitleCache())){
794
                separator = " - ";
795
            }
796
            description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
797
        }
798
        Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
799
        annotation.setAnnotationType(AnnotationType.TECHNICAL());
800
        description.addAnnotation(annotation);
801
        Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
802
        targetTaxon.addDescription(description);
803
        result.addUpdatedObject(targetTaxon);
804
        result.addUpdatedObject(sourceTaxon);
805
       // dao.merge(description);
806
        return result;
807

    
808
    }
809

    
810
}
(16-16/106)