Project

General

Profile

Download (52.1 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
package eu.etaxonomy.cdm.api.service;
10

    
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.Collection;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.Iterator;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.UUID;
21
import java.util.stream.Collectors;
22

    
23
import org.apache.commons.lang.StringUtils;
24
import org.apache.log4j.Logger;
25
import org.hibernate.Query;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.springframework.stereotype.Service;
28
import org.springframework.transaction.annotation.Transactional;
29

    
30
import eu.etaxonomy.cdm.api.service.description.MissingMaximumMode;
31
import eu.etaxonomy.cdm.api.service.description.MissingMinimumMode;
32
import eu.etaxonomy.cdm.api.service.description.StructuredDescriptionAggregation;
33
import eu.etaxonomy.cdm.api.service.dto.CategoricalDataDto;
34
import eu.etaxonomy.cdm.api.service.dto.DescriptionBaseDto;
35
import eu.etaxonomy.cdm.api.service.dto.DescriptionElementDto;
36
import eu.etaxonomy.cdm.api.service.dto.QuantitativeDataDto;
37
import eu.etaxonomy.cdm.api.service.dto.StateDataDto;
38
import eu.etaxonomy.cdm.api.service.dto.StatisticalMeasurementValueDto;
39
import eu.etaxonomy.cdm.api.service.dto.TaxonDistributionDTO;
40
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
41
import eu.etaxonomy.cdm.api.service.pager.Pager;
42
import eu.etaxonomy.cdm.api.service.pager.PagerUtils;
43
import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
44
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
45
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
46
import eu.etaxonomy.cdm.format.description.MicroFormatQuantitativeDescriptionBuilder;
47
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
48
import eu.etaxonomy.cdm.model.common.Annotation;
49
import eu.etaxonomy.cdm.model.common.AnnotationType;
50
import eu.etaxonomy.cdm.model.common.CdmBase;
51
import eu.etaxonomy.cdm.model.common.Language;
52
import eu.etaxonomy.cdm.model.common.Marker;
53
import eu.etaxonomy.cdm.model.common.MarkerType;
54
import eu.etaxonomy.cdm.model.description.CategoricalData;
55
import eu.etaxonomy.cdm.model.description.DescriptionBase;
56
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
57
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
58
import eu.etaxonomy.cdm.model.description.DescriptionType;
59
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
60
import eu.etaxonomy.cdm.model.description.Feature;
61
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
62
import eu.etaxonomy.cdm.model.description.QuantitativeData;
63
import eu.etaxonomy.cdm.model.description.SpecimenDescription;
64
import eu.etaxonomy.cdm.model.description.State;
65
import eu.etaxonomy.cdm.model.description.StateData;
66
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
67
import eu.etaxonomy.cdm.model.description.StatisticalMeasurementValue;
68
import eu.etaxonomy.cdm.model.description.TaxonDescription;
69
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
70
import eu.etaxonomy.cdm.model.description.TextData;
71
import eu.etaxonomy.cdm.model.location.NamedArea;
72
import eu.etaxonomy.cdm.model.media.Media;
73
import eu.etaxonomy.cdm.model.name.TaxonName;
74
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
75
import eu.etaxonomy.cdm.model.reference.CdmLinkSource;
76
import eu.etaxonomy.cdm.model.reference.ICdmTarget;
77
import eu.etaxonomy.cdm.model.taxon.Taxon;
78
import eu.etaxonomy.cdm.model.term.DefinedTerm;
79
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
80
import eu.etaxonomy.cdm.model.term.TermTree;
81
import eu.etaxonomy.cdm.model.term.TermVocabulary;
82
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
83
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
84
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptiveDataSetDao;
85
import eu.etaxonomy.cdm.persistence.dao.description.IStatisticalMeasurementValueDao;
86
import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
87
import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;
88
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
89
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
90
import eu.etaxonomy.cdm.persistence.dao.term.IDefinedTermDao;
91
import eu.etaxonomy.cdm.persistence.dao.term.ITermNodeDao;
92
import eu.etaxonomy.cdm.persistence.dao.term.ITermTreeDao;
93
import eu.etaxonomy.cdm.persistence.dao.term.ITermVocabularyDao;
94
import eu.etaxonomy.cdm.persistence.dto.MergeResult;
95
import eu.etaxonomy.cdm.persistence.dto.TermDto;
96
import eu.etaxonomy.cdm.persistence.query.OrderHint;
97
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
98

    
99
/**
100
 * @author a.mueller
101
 * @author a.kohlbecker
102
 *
103
 * @since 24.06.2008
104
 */
105
@Service
106
@Transactional(readOnly = true)
107
public class DescriptionServiceImpl
108
        extends IdentifiableServiceBase<DescriptionBase,IDescriptionDao>
109
        implements IDescriptionService {
110

    
111
    private static final Logger logger = Logger.getLogger(DescriptionServiceImpl.class);
112

    
113
    protected IDescriptionElementDao descriptionElementDao;
114
    protected ITermTreeDao featureTreeDao;
115
    protected IDescriptiveDataSetDao descriptiveDataSetDao;
116
    protected ITermNodeDao termNodeDao;
117
    protected ITermVocabularyDao vocabularyDao;
118
    protected IDefinedTermDao definedTermDao;
119
    protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao;
120
    protected ITaxonDao taxonDao;
121
    protected ITaxonNameDao nameDao;
122
    protected IOccurrenceDao occurrenceDao;
123
    protected ITaxonNodeDao taxonNodeDao;
124
    protected IDescriptiveDataSetDao dataSetDao;
125

    
126
    //TODO change to Interface
127
    private NaturalLanguageGenerator naturalLanguageGenerator;
128

    
129
    @Autowired
130
    protected void setFeatureTreeDao(ITermTreeDao featureTreeDao) {
131
        this.featureTreeDao = featureTreeDao;
132
    }
133

    
134
    @Autowired
135
    protected void setDescriptiveDataSetDao(IDescriptiveDataSetDao descriptiveDataSetDao) {
136
        this.descriptiveDataSetDao = descriptiveDataSetDao;
137
    }
138

    
139
    @Autowired
140
    protected void setTermNodeDao(ITermNodeDao featureNodeDao) {
141
        this.termNodeDao = featureNodeDao;
142
    }
143

    
144
    @Autowired
145
    protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
146
        this.vocabularyDao = vocabularyDao;
147
    }
148

    
149
    @Autowired
150
    protected void setDefinedTermDao(IDefinedTermDao definedTermDao) {
151
        this.definedTermDao = definedTermDao;
152
    }
153

    
154
    @Autowired
155
    protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao) {
156
        this.statisticalMeasurementValueDao = statisticalMeasurementValueDao;
157
    }
158

    
159
    @Autowired
160
    protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao) {
161
        this.descriptionElementDao = descriptionElementDao;
162
    }
163

    
164
    @Autowired
165
    protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator) {
166
        this.naturalLanguageGenerator = naturalLanguageGenerator;
167
    }
168

    
169
    @Autowired
170
    protected void setTaxonDao(ITaxonDao taxonDao) {
171
        this.taxonDao = taxonDao;
172
    }
173

    
174
    @Autowired
175
    protected void setTaxonNodeDao(ITaxonNodeDao taxonNodeDao) {
176
        this.taxonNodeDao = taxonNodeDao;
177
    }
178

    
179
    @Autowired
180
    protected void setDataSetDao(IDescriptiveDataSetDao dataSetDao) {
181
        this.dataSetDao = dataSetDao;
182
    }
183

    
184
    public DescriptionServiceImpl() {
185
        logger.debug("Load DescriptionService Bean");
186
    }
187

    
188
    @Override
189
    @Transactional(readOnly = false)
190
    public UpdateResult updateCaches(Class<? extends DescriptionBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DescriptionBase> cacheStrategy, IProgressMonitor monitor) {
191
        if (clazz == null){
192
            clazz = DescriptionBase.class;
193
        }
194
        return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);
195
    }
196

    
197
    @Override
198
    public TermVocabulary<Feature> getDefaultFeatureVocabulary(){
199
        String uuidFeature = "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
200
        UUID featureUuid = UUID.fromString(uuidFeature);
201
        return vocabularyDao.findByUuid(featureUuid);
202
    }
203

    
204
    @Override
205
    @Autowired
206
    protected void setDao(IDescriptionDao dao) {
207
        this.dao = dao;
208
    }
209

    
210
    @Override
211
    public long count(Class<? extends DescriptionBase> type, Boolean hasImages, Boolean hasText,Set<Feature> feature) {
212
        return dao.countDescriptions(type, hasImages, hasText, feature);
213
    }
214

    
215
    @Override
216
    public <T extends DescriptionElementBase> Pager<T> pageDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
217
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
218

    
219
        List<T> results = listDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
220
        return new DefaultPagerImpl<>(pageNumber, Integer.valueOf(results.size()).longValue(), pageSize, results);
221
    }
222

    
223
    @Override
224
    @Deprecated
225
    public <T extends DescriptionElementBase> Pager<T> getDescriptionElements(DescriptionBase description,
226
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
227
        return pageDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
228
    }
229

    
230
    @Override
231
    public <T extends DescriptionElementBase> List<T> listDescriptionElements(DescriptionBase description,
232
            Class<? extends DescriptionBase> descriptionType, Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber,
233
            List<String> propertyPaths) {
234

    
235
        long numberOfResults = dao.countDescriptionElements(description, descriptionType, features, type);
236
        List<T> results = new ArrayList<T>();
237
        if(AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)) {
238
            results = dao.getDescriptionElements(description, descriptionType, features, type, pageSize, pageNumber, propertyPaths);
239
        }
240
        return results;
241
    }
242

    
243
    @Override
244
    @Deprecated
245
    public <T extends DescriptionElementBase> List<T> listDescriptionElements(DescriptionBase description,
246
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
247

    
248
        return listDescriptionElements(description, null, features, type, pageSize, pageNumber, propertyPaths);
249
    }
250

    
251
    @Override
252
    public Pager<Annotation> getDescriptionElementAnnotations(DescriptionElementBase annotatedObj, MarkerType status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
253
        long numberOfResults = descriptionElementDao.countAnnotations(annotatedObj, status);
254

    
255
        List<Annotation> results = new ArrayList<>();
256
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
257
            results = descriptionElementDao.getAnnotations(annotatedObj, status, pageSize, pageNumber, orderHints, propertyPaths);
258
        }
259

    
260
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
261
    }
262

    
263

    
264
    @Override
265
    public Pager<Media> getMedia(DescriptionElementBase descriptionElement,	Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
266
        Long numberOfResults = descriptionElementDao.countMedia(descriptionElement);
267

    
268
        List<Media> results = new ArrayList<Media>();
269
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
270
            results = descriptionElementDao.getMedia(descriptionElement, pageSize, pageNumber, propertyPaths);
271
        }
272

    
273
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
274
    }
275

    
276
    @Override
277
    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
278
        Set<MarkerType> markerTypes = null;
279
        Set<DescriptionType> descriptionTypes = null;
280
        return pageTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, descriptionTypes, pageSize, pageNumber, propertyPaths);
281
    }
282

    
283
    @Override
284
    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
285
        Set<MarkerType> markerTypes = null;
286
        Set<DescriptionType> descriptionTypes = null;
287
        return listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, descriptionTypes, pageSize, pageNumber, propertyPaths);
288
    }
289

    
290
    @Override
291
    public Pager<TaxonDescription> pageTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Set<DescriptionType> descriptionTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
292
        long numberOfResults = dao.countTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, descriptionTypes);
293

    
294
        List<TaxonDescription> results = new ArrayList<>();
295
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
296
            results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, descriptionTypes, pageSize, pageNumber, propertyPaths);
297
        }
298

    
299
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
300
    }
301

    
302
    @Override
303
    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScope, Set<MarkerType> markerTypes, Set<DescriptionType> descriptionTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
304
        List<TaxonDescription> results = dao.listTaxonDescriptions(taxon, scopes, geographicalScope, markerTypes, descriptionTypes, pageSize, pageNumber, propertyPaths);
305
        return results;
306
    }
307

    
308

    
309
    @Override
310
    public List<Media> listTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths){
311
        return this.dao.listTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes, pageSize, pageNumber, propertyPaths);
312
    }
313

    
314
    @Override
315
    public int countTaxonDescriptionMedia(UUID taxonUuid, boolean limitToGalleries, Set<MarkerType> markerTypes){
316
        return this.dao.countTaxonDescriptionMedia(taxonUuid, limitToGalleries, markerTypes);
317
    }
318

    
319
    @Override
320
    public Pager<TaxonNameDescription> getTaxonNameDescriptions(TaxonName name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
321
        long numberOfResults = dao.countTaxonNameDescriptions(name);
322

    
323
        List<TaxonNameDescription> results = new ArrayList<>();
324
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
325
            results = dao.getTaxonNameDescriptions(name, pageSize, pageNumber,propertyPaths);
326
        }
327

    
328
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
329
    }
330

    
331

    
332
    @Override
333
    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) {
334
        long numberOfResults = dao.countDescriptions(type, hasImages, hasText, feature);
335

    
336
        @SuppressWarnings("rawtypes")
337
        List<DescriptionBase> results = new ArrayList<>();
338
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
339
            results = dao.listDescriptions(type, hasImages, hasText, feature, pageSize, pageNumber,orderHints,propertyPaths);
340
        }
341

    
342
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
343
    }
344

    
345
    /**
346
     * FIXME Candidate for harmonization
347
     * Rename: searchByDistribution
348
     */
349
    @Override
350
    public Pager<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm presence,	Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
351
        long numberOfResults = dao.countDescriptionByDistribution(namedAreas, presence);
352

    
353
        List<TaxonDescription> results = new ArrayList<>();
354
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
355
            results = dao.searchDescriptionByDistribution(namedAreas, presence, pageSize, pageNumber,orderHints,propertyPaths);
356
        }
357

    
358
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
359
    }
360

    
361
    /**
362
     * FIXME Candidate for harmonization
363
     * move: descriptionElementService.search
364
     */
365
    @Override
366
//    public Pager<T> searchElements(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
367
    public <S extends DescriptionElementBase> Pager<S> searchElements(Class<S> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
368
        long numberOfResults = descriptionElementDao.count(clazz, queryString);
369

    
370
        List<S> results = new ArrayList<>();
371
        if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
372
            results = (List<S>)descriptionElementDao.search(clazz, queryString, pageSize, pageNumber, orderHints, propertyPaths);
373
        }
374

    
375
        return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
376
    }
377

    
378
    /**
379
     * FIXME Candidate for harmonization
380
     * descriptionElementService.find
381
     */
382
    @Override
383
    public DescriptionElementBase getDescriptionElementByUuid(UUID uuid) {
384
        return descriptionElementDao.findByUuid(uuid);
385
    }
386

    
387
    /**
388
     * FIXME Candidate for harmonization
389
     * descriptionElementService.load
390
     */
391
    @Override
392
    public DescriptionElementBase loadDescriptionElement(UUID uuid,	List<String> propertyPaths) {
393
        return descriptionElementDao.load(uuid, propertyPaths);
394
    }
395

    
396
    /**
397
     * FIXME Candidate for harmonization
398
     * descriptionElementService.save
399
     */
400
    @Override
401
    @Transactional(readOnly = false)
402
    public UUID saveDescriptionElement(DescriptionElementBase descriptionElement) {
403
        return descriptionElementDao.save(descriptionElement).getUuid();
404
    }
405

    
406
    /**
407
     * FIXME Candidate for harmonization
408
     * descriptionElementService.save
409
     */
410
    @Override
411
    @Transactional(readOnly = false)
412
    public Map<UUID, DescriptionElementBase> saveDescriptionElement(Collection<DescriptionElementBase> descriptionElements) {
413
        return descriptionElementDao.saveAll(descriptionElements);
414
    }
415

    
416
    @Override
417
    @Transactional(readOnly = false)
418
    public List<MergeResult<DescriptionBase>> mergeDescriptionElements(Collection<TaxonDistributionDTO> descriptionElements, boolean returnTransientEntity) {
419
        List<MergeResult<DescriptionBase>> mergedObjects = new ArrayList();
420

    
421
        for(TaxonDistributionDTO obj : descriptionElements) {
422
            Iterator<TaxonDescription> iterator = obj.getDescriptionsWrapper().getDescriptions().iterator();
423
            List<DescriptionBase> list = new ArrayList(obj.getDescriptionsWrapper().getDescriptions());
424
          //  Map<UUID, DescriptionBase> map = dao.saveOrUpdateAll(list);
425
//            MergeResult<DescriptionBase> mergeResult = new MergeResult<DescriptionBase>(mergedEntity, newEntities)
426
//            mergedObjects.add(map.values());
427
            while (iterator.hasNext()){
428
                TaxonDescription desc = iterator.next();
429
                mergedObjects.add(dao.merge(desc, returnTransientEntity));
430
            }
431

    
432

    
433
        }
434

    
435
        return mergedObjects;
436
    }
437
//
438
    @Override
439
    @Transactional(readOnly = false)
440
    public UpdateResult mergeDescriptions(Collection<DescriptionBaseDto> descriptions, UUID descriptiveDataSetUuid) {
441
//        List<<DescriptionBase>> mergedObjects = new ArrayList();
442
        UpdateResult result = new UpdateResult();
443
        DescriptiveDataSet dataSet = descriptiveDataSetDao.load(descriptiveDataSetUuid);
444
        Set<DescriptionBase> descriptionsOfDataSet = dataSet.getDescriptions();
445
        HashMap<UUID, DescriptionBase> descriptionSpecimenMap = new HashMap();
446

    
447
        for (DescriptionBase descriptionBase: descriptionsOfDataSet){
448
            if (descriptionBase.getDescribedSpecimenOrObservation() != null){
449
                descriptionSpecimenMap.put(descriptionBase.getDescribedSpecimenOrObservation().getUuid(), descriptionBase);
450
            }
451
        }
452
        MergeResult<DescriptionBase> mergeResult = null;
453
        for(DescriptionBaseDto descDto : descriptions) {
454
            UUID descriptionUUID = descDto.getDescriptionUuid();
455
            DescriptionBase description = load(descriptionUUID);
456
            UUID describedObjectUuid = null;
457
            if (description instanceof SpecimenDescription){
458
                describedObjectUuid = descDto.getSpecimenDto().getUuid();
459
            }else if (description instanceof TaxonDescription){
460
                describedObjectUuid = descDto.getTaxonDto().getUuid();
461
            }else if (description instanceof TaxonNameDescription){
462
                describedObjectUuid = descDto.getNameDto().getUuid();
463
            }
464

    
465
            DescriptionBase descSpecimen = descriptionSpecimenMap.get(describedObjectUuid);
466

    
467
            if (descSpecimen != null ){
468

    
469
//                TODO: elements are Dtos now, no cdm entities, needs to get the value and replace or create new description element
470
                Set<DescriptionElementDto> elements = new HashSet<>();
471
                for (Object element: descDto.getElements()){
472
                    elements.add((DescriptionElementDto)element);
473
                }
474
                DescriptionBase desc = descriptionSpecimenMap.get(describedObjectUuid);
475
//                description.setDescribedSpecimenOrObservation(null);
476
                Set<DescriptionElementBase> descriptionElements = desc.getElements();
477
                for (DescriptionElementDto descElement: elements){
478
                    UUID descElementUuid = descElement.getElementUuid();
479
                    List<DescriptionElementBase> equalUuidsElements = descriptionElements.stream().filter( e -> e.getUuid().equals(descElementUuid)).collect(Collectors.toList());
480
                    eu.etaxonomy.cdm.model.description.Feature feature =  DefinedTermBase.getTermByClassAndUUID(eu.etaxonomy.cdm.model.description.Feature.class, descElement.getFeatureUuid());
481
                    if (feature == null){
482
                        feature = DefinedTermBase.getTermByClassAndUUID(eu.etaxonomy.cdm.model.description.Character.class, descElement.getFeatureUuid());
483
                    }
484
                    if (equalUuidsElements.size() == 0){
485
                        if (descElement instanceof CategoricalDataDto){
486

    
487
                            CategoricalData elementBase = CategoricalData.NewInstance(feature);
488
                            List<StateDataDto> stateDtos = ((CategoricalDataDto)descElement).getStates();
489
                            for (StateDataDto dataDto: stateDtos){
490
                                //create new statedata
491
                                State newState = DefinedTermBase.getTermByClassAndUUID(State.class, dataDto.getState().getUuid());
492
                                StateData newStateData = StateData.NewInstance(newState);
493
                                elementBase.addStateData(newStateData);
494
                            }
495
                            desc.addElement(elementBase);
496
                        }
497
                        if (descElement instanceof QuantitativeDataDto){
498

    
499
                            QuantitativeData data = QuantitativeData.NewInstance(feature);
500

    
501
                            Set<StatisticalMeasurementValue> statisticalValues = new HashSet<>();
502
                            Set<StatisticalMeasurementValueDto> valueDtos = ((QuantitativeDataDto)descElement).getValues();
503
                            data.getStatisticalValues().clear();
504
                            for (StatisticalMeasurementValueDto dataDto: valueDtos){
505
                                //create new statedata
506
                                StatisticalMeasurementValue newStatisticalMeasurement = StatisticalMeasurementValue.NewInstance(DefinedTermBase.getTermByClassAndUUID(StatisticalMeasure.class, dataDto.getType().getUuid()), dataDto.getValue());
507
                                statisticalValues.add(newStatisticalMeasurement);
508
                                data.addStatisticalValue(newStatisticalMeasurement);
509
                            }
510

    
511
//                            data.getStatisticalValues().addAll(statisticalValues);
512
                            data = StructuredDescriptionAggregation.handleMissingMinOrMax(data,
513
                                    MissingMinimumMode.MinToZero, MissingMaximumMode.MaxToMin);
514
                            desc.addElement(data);
515
                        }
516

    
517
                        //create new element
518
                    }else{
519
                        DescriptionElementBase elementBase = equalUuidsElements.get(0);
520
                        if (elementBase.isInstanceOf(CategoricalData.class)){
521
                            CategoricalData data = HibernateProxyHelper.deproxy(elementBase, CategoricalData.class);
522
                            List<StateData> states = new ArrayList<>(data.getStateData());
523
                            List<StateDataDto> stateDtos = ((CategoricalDataDto)descElement).getStates();
524
                            data.getStateData().clear();
525
                            for (StateDataDto dataDto: stateDtos){
526
                                List<StateData> equalUuidsStateData = states.stream().filter( e -> e.getUuid().equals(dataDto.getUuid())).collect(Collectors.toList());
527
//                                if (equalUuidsStateData.size() == 1){
528
//                                    //do nothing because state already exist
529
//                                }else if (equalUuidsStateData.isEmpty()){
530
                                    //create new statedata
531
                                    State newState = DefinedTermBase.getTermByClassAndUUID(State.class, dataDto.getState().getUuid());
532
                                    StateData newStateData = StateData.NewInstance(newState);
533
                                    data.addStateData(newStateData);
534
//                                }
535

    
536

    
537
                            }
538
                          //delete removed state data
539
//                            Set<StateData> toRemove = new HashSet<>();
540
//                            for (StateData stateData:states){
541
////                                List<StateDataDto> equalUuidsStateData = new ArrayList<>();
542
////                                for (StateDataDto dto: stateDtos){
543
////                                    if (dto.getUuid() == stateData.getUuid()){
544
////                                        equalUuidsStateData.add(dto);
545
////                                    }
546
////                                }
547
//                                List<StateDataDto> equalUuidsStateData = stateDtos.stream().filter( e -> e.getUuid() == stateData.getUuid()).collect(Collectors.toList());
548
//                                if (equalUuidsStateData.size() == 0){
549
//                                    toRemove.add(stateData);
550
//                                }
551
//                            }
552
//                            for (StateData remove: toRemove){
553
//                                data.removeStateData(remove);
554
//                            }
555
                        }else if (elementBase.isInstanceOf(QuantitativeData.class)){
556
                            QuantitativeData data = HibernateProxyHelper.deproxy(elementBase, QuantitativeData.class);
557

    
558
                            Set<StatisticalMeasurementValue> statisticalValues = new HashSet<>();
559
                            Set<StatisticalMeasurementValueDto> valueDtos = ((QuantitativeDataDto)descElement).getValues();
560
                            data.getStatisticalValues().clear();
561
                            for (StatisticalMeasurementValueDto dataDto: valueDtos){
562
                                //create new statedata
563
                                StatisticalMeasurementValue newStatisticalMeasurement = StatisticalMeasurementValue.NewInstance(DefinedTermBase.getTermByClassAndUUID(StatisticalMeasure.class, dataDto.getType().getUuid()), dataDto.getValue());
564
                                statisticalValues.add(newStatisticalMeasurement);
565
                                data.addStatisticalValue(newStatisticalMeasurement);
566
                            }
567

    
568
//                            data.getStatisticalValues().addAll(statisticalValues);
569
                            data = StructuredDescriptionAggregation.handleMissingMinOrMax(data,
570
                                    MissingMinimumMode.MinToZero, MissingMaximumMode.MaxToMin);
571

    
572
                        }
573
                    }
574
                }
575
                descriptionSpecimenMap.put(describedObjectUuid, desc);
576
                description = desc;
577
            }
578
            try{
579
                mergeResult = dao.merge(description, true);
580
                result.addUpdatedObject( mergeResult.getMergedEntity());
581
//                if (description instanceof SpecimenDescription){
582
//                    result.addUpdatedObject(mergeResult.getMergedEntity().getDescribedSpecimenOrObservation());
583
//                }else if (description instanceof TaxonDescription){
584
//                    result.addUpdatedObject(((TaxonDescription)mergeResult.getMergedEntity()).getTaxon());
585
//                }else if (description instanceof TaxonNameDescription){
586
//                    result.addUpdatedObject(((TaxonNameDescription)mergeResult.getMergedEntity()).getTaxonName());
587
//                }
588
            }catch(Exception e){
589
                e.printStackTrace();
590
            }
591

    
592
        }
593

    
594
        return result;
595
    }
596

    
597
    /**
598
     * FIXME Candidate for harmonization
599
     * descriptionElementService.delete
600
     */
601
    @Override
602
    public UUID deleteDescriptionElement(DescriptionElementBase descriptionElement) {
603
        return descriptionElementDao.delete(descriptionElement);
604
    }
605

    
606
    @Override
607
    public UUID deleteDescriptionElement(UUID descriptionElementUuid) {
608
        return deleteDescriptionElement(descriptionElementDao.load(descriptionElementUuid));
609
    }
610

    
611
    @Override
612
    @Transactional(readOnly = false)
613
    public DeleteResult deleteDescription(DescriptionBase description) {
614

    
615
        DeleteResult deleteResult = new DeleteResult();
616
        if (description == null){
617
            return deleteResult;
618
        }
619
        description = load(description.getId(), Arrays.asList("descriptiveDataSets"));
620
        //avoid lazy init exception
621

    
622
        deleteResult = isDeletable(description.getUuid());
623
        if (deleteResult.getRelatedObjects() != null && deleteResult.getRelatedObjects().size() == 1){
624
            Iterator<CdmBase> relObjects = deleteResult.getRelatedObjects().iterator();
625
            CdmBase next = relObjects.next();
626
            if (next instanceof CdmLinkSource){
627
                CdmLinkSource source = (CdmLinkSource)next;
628
                ICdmTarget target = source.getTarget();
629

    
630

    
631
            }
632
        }
633
        if (deleteResult.isOk() ){
634
        	if (description instanceof TaxonDescription){
635
        		TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
636
        		Taxon tax = taxDescription.getTaxon();
637
        		tax.removeDescription(taxDescription, true);
638
                deleteResult.addUpdatedObject(tax);
639
        	}
640
        	else if (HibernateProxyHelper.isInstanceOf(description, SpecimenDescription.class)){
641
        	    SpecimenDescription specimenDescription = HibernateProxyHelper.deproxy(description, SpecimenDescription.class);
642
        	    SpecimenOrObservationBase<?> specimen = specimenDescription.getDescribedSpecimenOrObservation();
643
        	    specimen.removeDescription(specimenDescription);
644
        	    deleteResult.addUpdatedObject(specimen);
645
        	}
646

    
647
        	Set<DescriptiveDataSet> descriptiveDataSets = description.getDescriptiveDataSets();
648
        	for (Iterator<DescriptiveDataSet> iterator = descriptiveDataSets.iterator(); iterator.hasNext();) {
649
        	    iterator.next().removeDescription(description);
650
            }
651

    
652
        	dao.delete(description);
653
        	deleteResult.addDeletedObject(description);
654
        	deleteResult.setCdmEntity(description);
655
        }else{
656
            logger.info(deleteResult.getExceptions().toString());
657
        }
658

    
659
        return deleteResult;
660
    }
661

    
662
    @Override
663
    @Transactional(readOnly = false)
664
    public DeleteResult deleteDescription(UUID descriptionUuid) {
665
        return deleteDescription(dao.load(descriptionUuid));
666
    }
667

    
668
    @Override
669
    public DeleteResult isDeletable(UUID descriptionUuid){
670
        DeleteResult result = new DeleteResult();
671
        DescriptionBase<?> description = this.load(descriptionUuid);
672
        Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(description);
673

    
674
        if (references == null || references.isEmpty()){
675
            return result;
676
        }
677
        for (CdmBase ref: references){
678
            String message = null;
679
            if (description instanceof TaxonDescription && ref instanceof Taxon && ((TaxonDescription)description).getTaxon().equals(ref)){
680
                continue;
681
            } else if (description instanceof TaxonNameDescription && ref instanceof TaxonName && ((TaxonNameDescription)description).getTaxonName().equals(ref)){
682
                continue;
683
            } else if (description instanceof SpecimenDescription && ref instanceof SpecimenOrObservationBase && ((SpecimenDescription)description).getDescribedSpecimenOrObservation().equals(ref)){
684
                continue;
685
            } else if (ref instanceof DescriptionElementBase){
686
                continue;
687
            }else {
688
                message = "The description can't be completely deleted because it is referenced by " + ref.getUserFriendlyTypeName() ;
689
                result.setAbort();
690
            }
691
            if (message != null){
692
                result.addException(new ReferencedObjectUndeletableException(message));
693
                result.addRelatedObject(ref);
694
            }
695
        }
696

    
697
        return result;
698
    }
699

    
700
    @Override
701
    public TermVocabulary<Feature> getFeatureVocabulary(UUID uuid) {
702
        return vocabularyDao.findByUuid(uuid);
703
    }
704

    
705
    @Override
706
    @Deprecated
707
    public <T extends DescriptionElementBase> List<T> getDescriptionElementsForTaxon(
708
            Taxon taxon, Set<Feature> features,
709
            Class<T> type, Integer pageSize,
710
            Integer pageNumber, List<String> propertyPaths) {
711
        return listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
712
    }
713

    
714
    @Override
715
    public <T extends DescriptionElementBase> List<T> listDescriptionElementsForTaxon(
716
            Taxon taxon, Set<Feature> features,
717
            Class<T> type, Integer pageSize,
718
            Integer pageNumber, List<String> propertyPaths) {
719
        return dao.getDescriptionElementForTaxon(taxon.getUuid(), features, type, pageSize, pageNumber, propertyPaths);
720
    }
721

    
722
    @Override
723
    public <T extends DescriptionElementBase> Pager<T> pageDescriptionElementsForTaxon(
724
            Taxon taxon, Set<Feature> features,
725
            Class<T> type, Integer pageSize,
726
            Integer pageNumber, List<String> propertyPaths) {
727
        if (logger.isDebugEnabled()){logger.debug(" get count ...");}
728
        Long count = dao.countDescriptionElementForTaxon(taxon.getUuid(), features, type);
729
        List<T> descriptionElements;
730
        if(AbstractPagerImpl.hasResultsInRange(count, pageNumber, pageSize)){ // no point checking again
731
            if (logger.isDebugEnabled()){logger.debug(" get list ...");}
732
            descriptionElements = listDescriptionElementsForTaxon(taxon, features, type, pageSize, pageNumber, propertyPaths);
733
        } else {
734
            descriptionElements = new ArrayList<T>(0);
735
        }
736
        if (logger.isDebugEnabled()){logger.debug(" service - DONE ...");}
737
        return new DefaultPagerImpl<T>(pageNumber, count, pageSize, descriptionElements);
738
    }
739

    
740
    @Override
741
    public String generateNaturalLanguageDescription(TermTree featureTree,
742
            TaxonDescription description, List<Language> preferredLanguages, String separator) {
743

    
744
        Language lang = preferredLanguages.size() > 0 ? preferredLanguages.get(0) : Language.DEFAULT();
745

    
746
        description = (TaxonDescription)load(description.getUuid());
747
        featureTree = featureTreeDao.load(featureTree.getUuid());
748

    
749
        StringBuilder naturalLanguageDescription = new StringBuilder();
750

    
751
        MarkerType useMarkerType = (MarkerType) definedTermDao.load(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
752
        boolean isUseDescription = false;
753
        if(!description.getMarkers().isEmpty()) {
754
            for (Marker marker: description.getMarkers()) {
755
                MarkerType markerType = marker.getMarkerType();
756
                if (markerType.equals(useMarkerType)) {
757
                    isUseDescription = true;
758
                }
759

    
760
            }
761
        }
762

    
763
        if(description.hasStructuredData() && !isUseDescription){
764

    
765

    
766
            String lastCategory = null;
767
            String categorySeparator = ". ";
768

    
769
            List<TextData> textDataList;
770
            TextData naturalLanguageDescriptionText = null;
771

    
772
            boolean useMicroFormatQuantitativeDescriptionBuilder = false;
773

    
774
            if(useMicroFormatQuantitativeDescriptionBuilder){
775

    
776
                MicroFormatQuantitativeDescriptionBuilder micro = new MicroFormatQuantitativeDescriptionBuilder();
777
                naturalLanguageGenerator.setQuantitativeDescriptionBuilder(micro);
778
                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(featureTree, (description), lang);
779

    
780
            } else {
781

    
782
                naturalLanguageDescriptionText = naturalLanguageGenerator.generateSingleTextData(
783
                        featureTree,
784
                        (description),
785
                        lang);
786
            }
787

    
788
            return naturalLanguageDescriptionText.getText(lang);
789

    
790
//
791
//			boolean doItBetter = false;
792
//
793
//			for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
794
//				if(textData.getMultilanguageText().size() > 0){
795
//
796
//					if (!textData.getFeature().equals(Feature.UNKNOWN())) {
797
//						String featureLabel = textData.getFeature().getLabel(lang);
798
//
799
//						if(doItBetter){
800
//							/*
801
//							 *  WARNING
802
//							 *  The code lines below are desinged to handle
803
//							 *  a special case where as the feature label contains
804
//							 *  hierarchical information on the features. This code
805
//							 *  exist only as a base for discussion, and is not
806
//							 *  intendet to be used in production.
807
//							 */
808
//							featureLabel = StringUtils.remove(featureLabel, '>');
809
//
810
//							String[] labelTokens = StringUtils.split(featureLabel, '<');
811
//							if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
812
//								if(naturalLanguageDescription.length() > 0){
813
//									naturalLanguageDescription.append(separator);
814
//								}
815
//								naturalLanguageDescription.append(labelTokens[1]);
816
//							} else {
817
//								if(naturalLanguageDescription.length() > 0){
818
//									naturalLanguageDescription.append(categorySeparator);
819
//								}
820
//								naturalLanguageDescription.append(StringUtils.join(labelTokens));
821
//							}
822
//							lastCategory = labelTokens[0];
823
//							// end of demo code
824
//						} else {
825
//							if(naturalLanguageDescription.length() > 0){
826
//								naturalLanguageDescription.append(separator);
827
//							}
828
//							naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
829
//						}
830
//					} else {
831
//						if(naturalLanguageDescription.length() > 0){
832
//							naturalLanguageDescription.append(separator);
833
//						}
834
//					}
835
//					String text = textData.getMultilanguageText().values().iterator().next().getText();
836
//					naturalLanguageDescription.append(text);
837
//
838
//				}
839
//			}
840

    
841
        }
842
        else if (isUseDescription) {
843
            //AT: Left Blank in case we need to generate a Natural language text string.
844
        }
845
        return naturalLanguageDescription.toString();
846
    }
847

    
848

    
849
    @Override
850
    public boolean hasStructuredData(DescriptionBase<?> description) {
851
        return load(description.getUuid()).hasStructuredData();
852
    }
853

    
854

    
855
    @Override
856
   // @Transactional(readOnly = false)
857
    public UpdateResult moveDescriptionElementsToDescription(
858
            Collection<DescriptionElementBase> descriptionElements,
859
            DescriptionBase targetDescription,
860
            boolean isCopy,
861
            boolean setNameInSource) {
862

    
863
        UpdateResult result = new UpdateResult();
864
        if (descriptionElements.isEmpty() || descriptionElements.iterator().next() == null){
865
            result.setAbort();
866
            return result;
867
        }
868

    
869

    
870
        if (! isCopy && descriptionElements == descriptionElements.iterator().next().getInDescription().getElements()){
871
            //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
872
            descriptionElements = new HashSet<DescriptionElementBase>(descriptionElements);
873
//			descriptionElementsTmp.addAll(descriptionElements);
874
//			descriptionElements = descriptionElementsTmp;
875
        }
876
        for (DescriptionElementBase element : descriptionElements){
877
            DescriptionBase<?> description = element.getInDescription();
878
            description = HibernateProxyHelper.deproxy(dao.load(description.getUuid()));
879
            Taxon taxon;
880
            TaxonName name = null;
881
            if (description instanceof TaxonDescription){
882
                TaxonDescription taxonDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
883
                if (taxonDescription.getTaxon() != null){
884
                    taxon = (Taxon) taxonDao.load(taxonDescription.getTaxon().getUuid());
885
                    name = taxon.getName();
886
                }
887

    
888

    
889
            }
890
            try {
891
                DescriptionElementBase newElement = element.clone();
892
                if (setNameInSource) {
893
                    for (DescriptionElementSource source: newElement.getSources()){
894
                            if (source.getNameUsedInSource() == null){
895
                                source.setNameUsedInSource(name);
896
                            }
897
                        }
898

    
899
                }
900
                targetDescription.addElement(newElement);
901
            } catch (CloneNotSupportedException e) {
902
                throw new RuntimeException ("Clone not yet implemented for class " + element.getClass().getName(), e);
903
            }
904
            if (! isCopy){
905
                description.removeElement(element);
906
                dao.saveOrUpdate(description);
907
                result.addUpdatedObject(description);
908
//                if (description.getElements().isEmpty()){
909
//                   if (description instanceof TaxonDescription){
910
//                       TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
911
//                       if (taxDescription.getTaxon() != null){
912
//                           taxDescription.getTaxon().removeDescription((TaxonDescription)description);
913
//                       }
914
//                   }
915
//                    dao.delete(description);
916
//
917
//                }//else{
918
//                    dao.saveOrUpdate(description);
919
//                    result.addUpdatedObject(description);
920
//                }
921
            }
922

    
923

    
924
        }
925
        dao.saveOrUpdate(targetDescription);
926
        result.addUpdatedObject(targetDescription);
927
        if (targetDescription instanceof TaxonDescription){
928
            result.addUpdatedObject(((TaxonDescription)targetDescription).getTaxon());
929
        }
930
        return result;
931
    }
932

    
933
    @Override
934
    @Transactional(readOnly = false)
935
    public UpdateResult moveDescriptionElementsToDescription(
936
            Set<UUID> descriptionElementUUIDs,
937
            UUID targetDescriptionUuid,
938
            boolean isCopy, boolean setNameInSource) {
939
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
940
        for(UUID deUuid : descriptionElementUUIDs) {
941
            DescriptionElementBase element = descriptionElementDao.load(deUuid);
942
            if (element != null){
943
                descriptionElements.add(element);
944
            }
945
        }
946
        DescriptionBase targetDescription = dao.load(targetDescriptionUuid);
947

    
948
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy, setNameInSource);
949
    }
950

    
951
    @Override
952
    @Transactional(readOnly = false)
953
    public UpdateResult moveDescriptionElementsToDescription(
954
            Set<UUID> descriptionElementUUIDs,
955
            DescriptionBase targetDescription,
956
            boolean isCopy, boolean setNameInSource) {
957
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
958
        for(UUID deUuid : descriptionElementUUIDs) {
959
            DescriptionElementBase element = descriptionElementDao.load(deUuid);
960
            if (element != null){
961
                descriptionElements.add(element);
962
            }
963
        }
964
        DescriptionBase newTargetDescription;
965
        if (targetDescription.isPersited()){
966
            newTargetDescription = dao.load(targetDescription.getUuid());
967
        }else{
968
            if (targetDescription instanceof TaxonDescription){
969
                Taxon taxon = (Taxon)taxonDao.load(((TaxonDescription)targetDescription).getTaxon().getUuid());
970

    
971
                newTargetDescription = TaxonDescription.NewInstance(taxon, targetDescription.isImageGallery());
972

    
973
            }else if (targetDescription instanceof TaxonNameDescription){
974
                TaxonName name = nameDao.load(((TaxonNameDescription)targetDescription).getTaxonName().getUuid());
975
                newTargetDescription = TaxonNameDescription.NewInstance(name);
976
            }else {
977
                SpecimenOrObservationBase specimen = occurrenceDao.load(((SpecimenDescription)targetDescription).getDescribedSpecimenOrObservation().getUuid());
978
                newTargetDescription = SpecimenDescription.NewInstance(specimen);
979
            }
980

    
981
            newTargetDescription.addSources(targetDescription.getSources());
982
            newTargetDescription.setTitleCache(targetDescription.getTitleCache(), targetDescription.isProtectedTitleCache());
983

    
984
        }
985
        return moveDescriptionElementsToDescription(descriptionElements, newTargetDescription, isCopy, setNameInSource);
986
    }
987

    
988

    
989
    @Override
990
    @Transactional(readOnly = false)
991
    public UpdateResult moveDescriptionElementsToDescription(
992
            Set<UUID> descriptionElementUUIDs,
993
            UUID targetTaxonUuid,
994
            String moveMessage,
995
            boolean isCopy, boolean setNameInSource) {
996
        Taxon targetTaxon = CdmBase.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
997
        DescriptionBase targetDescription = TaxonDescription.NewInstance(targetTaxon);
998
        targetDescription.setTitleCache(moveMessage, true);
999
        Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
1000
        annotation.setAnnotationType(AnnotationType.TECHNICAL());
1001
        targetDescription.addAnnotation(annotation);
1002

    
1003
        targetDescription = dao.save(targetDescription);
1004
        Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
1005
        for(UUID deUuid : descriptionElementUUIDs) {
1006
            descriptionElements.add(descriptionElementDao.load(deUuid));
1007
        }
1008

    
1009
        return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy, setNameInSource);
1010
    }
1011

    
1012
    @Override
1013
    public Pager<TermDto> pageNamedAreasInUse(boolean includeAllParents, Integer pageSize,
1014
            Integer pageIndex){
1015
        List<TermDto> results = dao.listNamedAreasInUse(includeAllParents, null, null);
1016
        List<TermDto> subList = PagerUtils.pageList(results, pageIndex, pageSize);
1017
        return new DefaultPagerImpl<TermDto>(pageIndex, results.size(), pageSize, subList);
1018
    }
1019

    
1020

    
1021
    @Override
1022
    @Transactional(readOnly = false)
1023
    public UpdateResult moveTaxonDescriptions(Taxon sourceTaxon, Taxon targetTaxon, boolean setNameInSource) {
1024
        List<TaxonDescription> descriptions = new ArrayList<>(sourceTaxon.getDescriptions());
1025
        UpdateResult result = new UpdateResult();
1026
        result.addUpdatedObject(sourceTaxon);
1027
        result.addUpdatedObject(targetTaxon);
1028
        for(TaxonDescription description : descriptions){
1029
            targetTaxon.addDescription(prepareDescriptionForMove(description, sourceTaxon, setNameInSource));
1030
        }
1031
        return result;
1032
    }
1033

    
1034
    private TaxonDescription prepareDescriptionForMove(TaxonDescription description, Taxon sourceTaxon, boolean setNameInSource){
1035
        String moveMessage = String.format("Description moved from %s", sourceTaxon);
1036
        if(description.isProtectedTitleCache()){
1037
            String separator = "";
1038
            if(!StringUtils.isBlank(description.getTitleCache())){
1039
                separator = " - ";
1040
            }
1041
            description.setTitleCache(description.getTitleCache() + separator + moveMessage, true);
1042
        }
1043
        else{
1044
            description.setTitleCache(moveMessage, true);
1045
        }
1046
        Annotation annotation = Annotation.NewInstance(moveMessage, Language.getDefaultLanguage());
1047
        annotation.setAnnotationType(AnnotationType.TECHNICAL());
1048
        description.addAnnotation(annotation);
1049
        if(setNameInSource){
1050
            for (DescriptionElementBase element: description.getElements()){
1051
                for (DescriptionElementSource source: element.getSources()){
1052
                    if (source.getNameUsedInSource() == null){
1053
                        source.setNameUsedInSource(sourceTaxon.getName());
1054
                    }
1055
                }
1056
            }
1057
        }
1058
        return description;
1059
    }
1060

    
1061
    @Override
1062
    @Transactional(readOnly = false)
1063
    public UpdateResult moveTaxonDescriptions(UUID sourceTaxonUuid, UUID targetTaxonUuid, boolean setNameInSource) {
1064
        Taxon sourceTaxon = HibernateProxyHelper.deproxy(taxonDao.load(sourceTaxonUuid), Taxon.class);
1065
        Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
1066
        return moveTaxonDescriptions(sourceTaxon, targetTaxon, setNameInSource);
1067

    
1068
    }
1069

    
1070
    @Override
1071
    @Transactional(readOnly = false)
1072
    public UpdateResult moveTaxonDescription(UUID descriptionUuid, UUID targetTaxonUuid, boolean setNameInSource){
1073
        TaxonDescription description = HibernateProxyHelper.deproxy(dao.load(descriptionUuid), TaxonDescription.class);
1074
        Taxon targetTaxon = HibernateProxyHelper.deproxy(taxonDao.load(targetTaxonUuid), Taxon.class);
1075
        Taxon sourceTaxon = description.getTaxon();
1076
        UpdateResult result = new UpdateResult();
1077
        result.addUpdatedObject(sourceTaxon);
1078
        result.addUpdatedObject(targetTaxon);
1079

    
1080
        targetTaxon.addDescription(prepareDescriptionForMove(description, sourceTaxon, setNameInSource));
1081
        return result;
1082

    
1083
    }
1084

    
1085
    @Override
1086
    public DescriptionBaseDto loadDto(UUID descriptionUuid) {
1087
        String sqlSelect =  DescriptionBaseDto.getDescriptionBaseDtoSelect();
1088
        Query query =  getSession().createQuery(sqlSelect);
1089
        query.setParameter("uuid", descriptionUuid);
1090

    
1091
        @SuppressWarnings("unchecked")
1092
        List<Object[]> result = query.list();
1093

    
1094
        List<DescriptionBaseDto> list = DescriptionBaseDto.descriptionBaseDtoListFrom(result);
1095

    
1096
        if (list.size()== 1){
1097
            return list.get(0);
1098
        }else{
1099
            return null;
1100
        }
1101

    
1102
    }
1103

    
1104
    @Override
1105
    public List<DescriptionBaseDto> loadDtosForTaxon(UUID taxonUuid) {
1106
        String sqlSelect =  DescriptionBaseDto.getDescriptionBaseDtoForTaxonSelect(taxonUuid);
1107
        Query query =  getSession().createQuery(sqlSelect);
1108

    
1109
        @SuppressWarnings("unchecked")
1110
        List<Object[]> result = query.list();
1111

    
1112
        List<DescriptionBaseDto> list = DescriptionBaseDto.descriptionBaseDtoListFrom(result);
1113

    
1114
        return list;
1115

    
1116
    }
1117

    
1118

    
1119
}
(11-11/97)