Project

General

Profile

Download (34.6 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
    @Override
231
    public Pager<Media> getMedia(DescriptionElementBase descriptionElement,	Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
232
        Integer numberOfResults = descriptionElementDao.countMedia(descriptionElement);
233

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

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

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

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

    
254
    @Override
255
    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
256
        Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
257

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

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

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

    
272

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

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

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

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

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

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

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

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

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

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

    
342

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

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

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

    
355

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

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

    
365
        return new DefaultPagerImpl<DescriptionBase>(pageNumber, numberOfResults, pageSize, results);
366
    }
367

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

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

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

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

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

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

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

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

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

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

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

    
447

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

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

    
461
    	if (description instanceof TaxonDescription){
462
    		TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
463
    		Taxon tax = taxDescription.getTaxon();
464
    		tax.removeDescription(taxDescription, true);
465
    		dao.delete(description);
466

    
467
            deleteResult.addUpdatedObject(tax);
468
            deleteResult.setCdmEntity(tax);
469
    	}
470

    
471

    
472
        return deleteResult;
473
    }
474

    
475

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

    
485

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

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

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

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

    
526

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

    
534
        Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
535

    
536
        description = (TaxonDescription)load(description.getUuid());
537
        featureTree = featureTreeDao.load(featureTree.getUuid());
538

    
539
        StringBuilder naturalLanguageDescription = new StringBuilder();
540

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

    
550
            }
551
        }
552

    
553
        if(description.hasStructuredData() && !isUseDescription){
554

    
555

    
556
            String lastCategory = null;
557
            String categorySeparator = ". ";
558

    
559
            List<TextData> textDataList;
560
            TextData naturalLanguageDescriptionText = null;
561

    
562
            boolean useMicroFormatQuantitativeDescriptionBuilder = false;
563

    
564
            if(useMicroFormatQuantitativeDescriptionBuilder){
565

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

    
570
            } else {
571

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

    
578
            return naturalLanguageDescriptionText.getText(lang);
579

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

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

    
638

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

    
644

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

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

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

    
687

    
688
        }
689
        dao.saveOrUpdate(targetDescription);
690
        result.addUpdatedObject(targetDescription);
691
        if (targetDescription instanceof TaxonDescription){
692
            result.addUpdatedObject(((TaxonDescription)targetDescription).getTaxon());
693
        }
694
        return result;
695
    }
696

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

    
709
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
710
    }
711

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

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

    
732
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy);
733
    }
734

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

    
745

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

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

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

    
778
    }
779

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

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

    
805
    }
806

    
807
}
(16-16/98)