Project

General

Profile

Download (34.6 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 int 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<T>(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
        Integer numberOfResults = dao.countDescriptionElements(description, descriptionType, features, type);
201
        List<T> results = new ArrayList<T>();
202
        if(AbstractPagerImpl.hasResultsInRange(numberOfResults.longValue(), 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
        Integer numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
221

    
222
        List<Annotation> results = new ArrayList<Annotation>();
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<Annotation>(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
        Integer numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes);
258

    
259
        List<TaxonDescription> results = new ArrayList<TaxonDescription>();
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<TaxonDescription>(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
        Integer 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<TaxonNameDescription>(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
        Integer numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
360

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

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

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

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

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

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

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

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

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

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

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

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

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

    
448

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

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

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

    
472

    
473
        return deleteResult;
474
    }
475

    
476

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

    
486

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

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

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

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

    
527

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

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

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

    
540
        StringBuilder naturalLanguageDescription = new StringBuilder();
541

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

    
551
            }
552
        }
553

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

    
556

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

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

    
563
            boolean useMicroFormatQuantitativeDescriptionBuilder = false;
564

    
565
            if(useMicroFormatQuantitativeDescriptionBuilder){
566

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

    
571
            } else {
572

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

    
579
            return naturalLanguageDescriptionText.getText(lang);
580

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

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

    
639

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

    
645

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

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

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

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

    
689

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

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

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

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

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

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

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

    
747

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

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

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

    
780
    }
781

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

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

    
807
    }
808

    
809
}
(16-16/105)