2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.api
.service
;
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
;
20 import java
.util
.UUID
;
21 import java
.util
.stream
.Collectors
;
23 import org
.apache
.commons
.lang
.StringUtils
;
24 import org
.apache
.logging
.log4j
.LogManager
;
25 import org
.apache
.logging
.log4j
.Logger
;
26 import org
.hibernate
.query
.Query
;
27 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
28 import org
.springframework
.stereotype
.Service
;
29 import org
.springframework
.transaction
.annotation
.Transactional
;
31 import eu
.etaxonomy
.cdm
.api
.service
.description
.MissingMaximumMode
;
32 import eu
.etaxonomy
.cdm
.api
.service
.description
.MissingMinimumMode
;
33 import eu
.etaxonomy
.cdm
.api
.service
.description
.StructuredDescriptionAggregation
;
34 import eu
.etaxonomy
.cdm
.api
.service
.dto
.CategoricalDataDto
;
35 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DescriptionBaseDto
;
36 import eu
.etaxonomy
.cdm
.api
.service
.dto
.DescriptionElementDto
;
37 import eu
.etaxonomy
.cdm
.api
.service
.dto
.QuantitativeDataDto
;
38 import eu
.etaxonomy
.cdm
.api
.service
.dto
.StateDataDto
;
39 import eu
.etaxonomy
.cdm
.api
.service
.dto
.StatisticalMeasurementValueDto
;
40 import eu
.etaxonomy
.cdm
.api
.service
.dto
.TaxonDistributionDTO
;
41 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
42 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
43 import eu
.etaxonomy
.cdm
.api
.service
.pager
.PagerUtils
;
44 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.AbstractPagerImpl
;
45 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
46 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
47 import eu
.etaxonomy
.cdm
.format
.description
.MicroFormatQuantitativeDescriptionBuilder
;
48 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
49 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
50 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
51 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
52 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
53 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
54 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
55 import eu
.etaxonomy
.cdm
.model
.description
.CategoricalData
;
56 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
57 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
58 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
59 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionType
;
60 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveDataSet
;
61 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
62 import eu
.etaxonomy
.cdm
.model
.description
.MeasurementUnit
;
63 import eu
.etaxonomy
.cdm
.model
.description
.PresenceAbsenceTerm
;
64 import eu
.etaxonomy
.cdm
.model
.description
.QuantitativeData
;
65 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
66 import eu
.etaxonomy
.cdm
.model
.description
.StateData
;
67 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasure
;
68 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasurementValue
;
69 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
70 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
71 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
72 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
73 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
74 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
75 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
76 import eu
.etaxonomy
.cdm
.model
.reference
.CdmLinkSource
;
77 import eu
.etaxonomy
.cdm
.model
.reference
.ICdmTarget
;
78 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
79 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTerm
;
80 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTermBase
;
81 import eu
.etaxonomy
.cdm
.model
.term
.TermTree
;
82 import eu
.etaxonomy
.cdm
.model
.term
.TermVocabulary
;
83 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionDao
;
84 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionElementDao
;
85 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptiveDataSetDao
;
86 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IStatisticalMeasurementValueDao
;
87 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
88 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
89 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
90 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonNodeDao
;
91 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.IDefinedTermDao
;
92 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.ITermNodeDao
;
93 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.ITermTreeDao
;
94 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.ITermVocabularyDao
;
95 import eu
.etaxonomy
.cdm
.persistence
.dto
.FeatureDto
;
96 import eu
.etaxonomy
.cdm
.persistence
.dto
.MergeResult
;
97 import eu
.etaxonomy
.cdm
.persistence
.dto
.SortableTaxonNodeQueryResult
;
98 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
99 import eu
.etaxonomy
.cdm
.persistence
.dto
.TermDto
;
100 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
101 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
105 * @author a.kohlbecker
110 @Transactional(readOnly
= true)
111 public class DescriptionServiceImpl
112 extends IdentifiableServiceBase
<DescriptionBase
,IDescriptionDao
>
113 implements IDescriptionService
{
115 private static final Logger logger
= LogManager
.getLogger();
117 protected IDescriptionElementDao descriptionElementDao
;
118 protected ITermTreeDao featureTreeDao
;
119 protected IDescriptiveDataSetDao descriptiveDataSetDao
;
120 protected ITermNodeDao termNodeDao
;
121 protected ITermVocabularyDao vocabularyDao
;
122 protected IDefinedTermDao definedTermDao
;
123 protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao
;
124 protected ITaxonDao taxonDao
;
125 protected ITaxonNameDao nameDao
;
126 protected IOccurrenceDao occurrenceDao
;
127 protected ITaxonNodeDao taxonNodeDao
;
128 protected IDescriptiveDataSetDao dataSetDao
;
129 protected ITermService termService
;
131 //TODO change to Interface
132 private NaturalLanguageGenerator naturalLanguageGenerator
;
135 protected void setFeatureTreeDao(ITermTreeDao featureTreeDao
) {
136 this.featureTreeDao
= featureTreeDao
;
140 protected void setDescriptiveDataSetDao(IDescriptiveDataSetDao descriptiveDataSetDao
) {
141 this.descriptiveDataSetDao
= descriptiveDataSetDao
;
145 protected void setTermNodeDao(ITermNodeDao featureNodeDao
) {
146 this.termNodeDao
= featureNodeDao
;
150 protected void setVocabularyDao(ITermVocabularyDao vocabularyDao
) {
151 this.vocabularyDao
= vocabularyDao
;
155 protected void setDefinedTermDao(IDefinedTermDao definedTermDao
) {
156 this.definedTermDao
= definedTermDao
;
160 protected void setTermService(ITermService definedTermService
) {
161 this.termService
= definedTermService
;
166 protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao
) {
167 this.statisticalMeasurementValueDao
= statisticalMeasurementValueDao
;
171 protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao
) {
172 this.descriptionElementDao
= descriptionElementDao
;
176 protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator
) {
177 this.naturalLanguageGenerator
= naturalLanguageGenerator
;
181 protected void setTaxonDao(ITaxonDao taxonDao
) {
182 this.taxonDao
= taxonDao
;
186 protected void setTaxonNodeDao(ITaxonNodeDao taxonNodeDao
) {
187 this.taxonNodeDao
= taxonNodeDao
;
191 protected void setDataSetDao(IDescriptiveDataSetDao dataSetDao
) {
192 this.dataSetDao
= dataSetDao
;
195 public DescriptionServiceImpl() {
196 logger
.debug("Load DescriptionService Bean");
200 @Transactional(readOnly
= false)
201 public UpdateResult
updateCaches(Class
<?
extends DescriptionBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<DescriptionBase
> cacheStrategy
, IProgressMonitor monitor
) {
203 clazz
= DescriptionBase
.class;
205 return super.updateCachesImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
209 public TermVocabulary
<Feature
> getDefaultFeatureVocabulary(){
210 String uuidFeature
= "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
211 UUID featureUuid
= UUID
.fromString(uuidFeature
);
212 return vocabularyDao
.findByUuid(featureUuid
);
217 protected void setDao(IDescriptionDao dao
) {
222 public long count(Class
<?
extends DescriptionBase
> type
, Boolean hasImages
, Boolean hasText
,Set
<Feature
> feature
) {
223 return dao
.countDescriptions(type
, hasImages
, hasText
, feature
);
227 public <T
extends DescriptionElementBase
> Pager
<T
> pageDescriptionElements(DescriptionBase description
, Class
<?
extends DescriptionBase
> descriptionType
,
228 Set
<Feature
> features
, Class
<T
> type
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
230 List
<T
> results
= listDescriptionElements(description
, descriptionType
, features
, type
, pageSize
, pageNumber
, propertyPaths
);
231 return new DefaultPagerImpl
<>(pageNumber
, Integer
.valueOf(results
.size()).longValue(), pageSize
, results
);
236 public <T
extends DescriptionElementBase
> Pager
<T
> getDescriptionElements(DescriptionBase description
,
237 Set
<Feature
> features
, Class
<T
> type
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
238 return pageDescriptionElements(description
, null, features
, type
, pageSize
, pageNumber
, propertyPaths
);
242 public <T
extends DescriptionElementBase
> List
<T
> listDescriptionElements(DescriptionBase description
,
243 Class
<?
extends DescriptionBase
> descriptionType
, Set
<Feature
> features
, Class
<T
> type
, Integer pageSize
, Integer pageNumber
,
244 List
<String
> propertyPaths
) {
246 long numberOfResults
= dao
.countDescriptionElements(description
, descriptionType
, features
, type
);
247 List
<T
> results
= new ArrayList
<T
>();
248 if(AbstractPagerImpl
.hasResultsInRange(numberOfResults
, pageNumber
, pageSize
)) {
249 results
= dao
.getDescriptionElements(description
, descriptionType
, features
, type
, pageSize
, pageNumber
, propertyPaths
);
256 public <T
extends DescriptionElementBase
> List
<T
> listDescriptionElements(DescriptionBase description
,
257 Set
<Feature
> features
, Class
<T
> type
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
259 return listDescriptionElements(description
, null, features
, type
, pageSize
, pageNumber
, propertyPaths
);
263 public Pager
<Media
> getMedia(DescriptionElementBase descriptionElement
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
264 Long numberOfResults
= descriptionElementDao
.countMedia(descriptionElement
);
266 List
<Media
> results
= new ArrayList
<>();
267 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
268 results
= descriptionElementDao
.getMedia(descriptionElement
, pageSize
, pageNumber
, propertyPaths
);
271 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
275 public Pager
<TaxonDescription
> pageTaxonDescriptions(Taxon taxon
, Set
<DefinedTerm
> scopes
, Set
<NamedArea
> geographicalScope
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
276 Set
<MarkerType
> markerTypes
= null;
277 Set
<DescriptionType
> descriptionTypes
= null;
278 return pageTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
282 public List
<TaxonDescription
> listTaxonDescriptions(Taxon taxon
, Set
<DefinedTerm
> scopes
, Set
<NamedArea
> geographicalScope
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
283 Set
<MarkerType
> markerTypes
= null;
284 Set
<DescriptionType
> descriptionTypes
= null;
285 return listTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
289 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
) {
290 long numberOfResults
= dao
.countTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
);
292 List
<TaxonDescription
> results
= new ArrayList
<>();
293 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
294 results
= dao
.listTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
297 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
301 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
) {
302 List
<TaxonDescription
> results
= dao
.listTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
308 public List
<Media
> listTaxonDescriptionMedia(UUID taxonUuid
, boolean limitToGalleries
, Set
<MarkerType
> markerTypes
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
){
309 return this.dao
.listTaxonDescriptionMedia(taxonUuid
, limitToGalleries
, markerTypes
, pageSize
, pageNumber
, propertyPaths
);
313 public int countTaxonDescriptionMedia(UUID taxonUuid
, boolean limitToGalleries
, Set
<MarkerType
> markerTypes
){
314 return this.dao
.countTaxonDescriptionMedia(taxonUuid
, limitToGalleries
, markerTypes
);
318 public Pager
<TaxonNameDescription
> getTaxonNameDescriptions(TaxonName name
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
319 long numberOfResults
= dao
.countTaxonNameDescriptions(name
);
321 List
<TaxonNameDescription
> results
= new ArrayList
<>();
322 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
323 results
= dao
.getTaxonNameDescriptions(name
, pageSize
, pageNumber
,propertyPaths
);
326 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
331 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
) {
332 long numberOfResults
= dao
.countDescriptions(type
, hasImages
, hasText
, feature
);
334 @SuppressWarnings("rawtypes")
335 List
<DescriptionBase
> results
= new ArrayList
<>();
336 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
337 results
= dao
.listDescriptions(type
, hasImages
, hasText
, feature
, pageSize
, pageNumber
,orderHints
,propertyPaths
);
340 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
344 * FIXME Candidate for harmonization
345 * Rename: searchByDistribution
348 public Pager
<TaxonDescription
> searchDescriptionByDistribution(Set
<NamedArea
> namedAreas
, PresenceAbsenceTerm presence
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
349 long numberOfResults
= dao
.countDescriptionByDistribution(namedAreas
, presence
);
351 List
<TaxonDescription
> results
= new ArrayList
<>();
352 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
353 results
= dao
.searchDescriptionByDistribution(namedAreas
, presence
, pageSize
, pageNumber
,orderHints
,propertyPaths
);
356 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
360 * FIXME Candidate for harmonization
361 * move: descriptionElementService.search
364 // public Pager<T> searchElements(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
365 public <S
extends DescriptionElementBase
> Pager
<S
> searchElements(Class
<S
> clazz
, String queryString
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
366 long numberOfResults
= descriptionElementDao
.count(clazz
, queryString
);
368 List
<S
> results
= new ArrayList
<>();
369 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
370 results
= (List
<S
>)descriptionElementDao
.search(clazz
, queryString
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
373 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
377 @Transactional(readOnly
= false)
378 public List
<MergeResult
<DescriptionBase
>> mergeDescriptionElements(Collection
<TaxonDistributionDTO
> descriptionElements
, boolean returnTransientEntity
) {
379 List
<MergeResult
<DescriptionBase
>> mergedObjects
= new ArrayList
<>();
381 for(TaxonDistributionDTO obj
: descriptionElements
) {
382 Iterator
<TaxonDescription
> iterator
= obj
.getDescriptionsWrapper().getDescriptions().iterator();
383 List
<DescriptionBase
> list
= new ArrayList(obj
.getDescriptionsWrapper().getDescriptions());
384 // Map<UUID, DescriptionBase> map = dao.saveOrUpdateAll(list);
385 // MergeResult<DescriptionBase> mergeResult = new MergeResult<DescriptionBase>(mergedEntity, newEntities)
386 // mergedObjects.add(map.values());
387 while (iterator
.hasNext()){
388 TaxonDescription desc
= iterator
.next();
389 mergedObjects
.add(dao
.merge(desc
, returnTransientEntity
));
393 return mergedObjects
;
397 @Transactional(readOnly
= false)
398 public UpdateResult
mergeDescriptions(Collection
<DescriptionBaseDto
> descriptions
, UUID descriptiveDataSetUuid
) {
400 UpdateResult result
= new UpdateResult();
401 DescriptiveDataSet dataSet
= descriptiveDataSetDao
.load(descriptiveDataSetUuid
);
402 Set
<DescriptionBase
> descriptionsOfDataSet
= dataSet
.getDescriptions();
403 HashMap
<UUID
, Set
<DescriptionBase
>> descriptionSpecimenMap
= new HashMap
<>();
404 Set
<DescriptionBase
> specimenDescriptions
;
405 for (DescriptionBase
<?
> descriptionBase
: descriptionsOfDataSet
){
406 if (descriptionBase
.getDescribedSpecimenOrObservation() != null){
407 specimenDescriptions
= descriptionSpecimenMap
.get(descriptionBase
.getDescribedSpecimenOrObservation().getUuid());
408 if (specimenDescriptions
== null){
409 specimenDescriptions
= new HashSet
<>();
411 specimenDescriptions
.add(descriptionBase
);
412 descriptionSpecimenMap
.put(descriptionBase
.getDescribedSpecimenOrObservation().getUuid(), specimenDescriptions
);
414 if (descriptionBase
instanceof TaxonDescription
){
415 specimenDescriptions
= descriptionSpecimenMap
.get(((TaxonDescription
)descriptionBase
).getTaxon().getUuid());
416 if (specimenDescriptions
== null){
417 specimenDescriptions
= new HashSet
<>();
419 specimenDescriptions
.add(descriptionBase
);
420 descriptionSpecimenMap
.put(((TaxonDescription
)descriptionBase
).getTaxon().getUuid(), specimenDescriptions
);
422 if (descriptionBase
instanceof TaxonNameDescription
){
423 specimenDescriptions
= descriptionSpecimenMap
.get(((TaxonNameDescription
)descriptionBase
).getTaxonName().getUuid());
424 if (specimenDescriptions
== null){
425 specimenDescriptions
= new HashSet
<>();
427 specimenDescriptions
.add(descriptionBase
);
428 descriptionSpecimenMap
.put(((TaxonNameDescription
)descriptionBase
).getTaxonName().getUuid(), specimenDescriptions
);
431 MergeResult
<DescriptionBase
> mergeResult
= null;
432 for(DescriptionBaseDto descDto
: descriptions
) {
434 UUID descriptionUUID
= descDto
.getDescriptionUuid();
435 DescriptionBase
<?
> description
= load(descriptionUUID
);
437 UUID describedObjectUuid
= null;
438 if (description
instanceof SpecimenDescription
){
439 describedObjectUuid
= descDto
.getSpecimenDto().getUuid();
440 }else if (description
instanceof TaxonDescription
){
441 describedObjectUuid
= descDto
.getTaxonDto().getUuid();
442 }else if (description
instanceof TaxonNameDescription
){
443 describedObjectUuid
= descDto
.getNameDto().getUuid();
446 Set
<DescriptionBase
> descSpecimen
= descriptionSpecimenMap
.get(describedObjectUuid
);
448 if (descSpecimen
!= null ){
450 // TODO: elements are Dtos now, no cdm entities, needs to get the value and replace or create new description element
451 Set
<DescriptionElementDto
> elements
= new HashSet
<>();
452 for (Object element
: descDto
.getElements()){
453 elements
.add((DescriptionElementDto
)element
);
456 DescriptionBase
<?
> desc
= null;
457 for (DescriptionBase
<?
> tempDesc
: descSpecimen
){
458 if (tempDesc
.getUuid().equals(descDto
.getDescriptionUuid())){
464 Set
<DescriptionElementBase
> removeElements
= new HashSet
<>();
465 Set
<DescriptionElementBase
> descriptionElements
= desc
.getElements();
466 for (DescriptionElementBase elementBase
: descriptionElements
){
467 UUID descElementUuid
= elementBase
.getUuid();
468 if (descElementUuid
!= null){
469 List
<DescriptionElementDto
> equalUuidsElements
= elements
.stream().filter( e
-> e
!= null && e
.getElementUuid() != null && e
.getElementUuid().equals(descElementUuid
)).collect(Collectors
.toList());
470 if (equalUuidsElements
.size() == 0 || (equalUuidsElements
.size() == 1 && equalUuidsElements
.get(0)instanceof QuantitativeDataDto
&& ((QuantitativeDataDto
)equalUuidsElements
.get(0)).getValues().isEmpty())){
471 removeElements
.add(elementBase
);
475 if (!removeElements
.isEmpty()){
476 for (DescriptionElementBase el
: removeElements
){
477 desc
.removeElement(el
);
481 // description.setDescribedSpecimenOrObservation(null);
483 for (DescriptionElementDto descElement
: elements
){
484 if (descElement
== null){
487 UUID descElementUuid
= descElement
.getElementUuid();
488 if (descElement
instanceof CategoricalDataDto
&& ((CategoricalDataDto
)descElement
).getStates().isEmpty() || descElement
instanceof QuantitativeDataDto
&& ((QuantitativeDataDto
)descElement
).getValues().isEmpty()){
491 List
<DescriptionElementBase
> equalUuidsElements
= descriptionElements
.stream().filter( e
-> e
.getUuid().equals(descElementUuid
)).collect(Collectors
.toList());
492 Feature feature
= DefinedTermBase
.getTermByUUID(descElement
.getFeatureUuid(), Feature
.class);
494 if (equalUuidsElements
.size() == 0){
495 if (descElement
instanceof CategoricalDataDto
){
497 CategoricalData elementBase
= CategoricalData
.NewInstance(feature
);
498 List
<StateDataDto
> stateDtos
= ((CategoricalDataDto
)descElement
).getStates();
499 for (StateDataDto dataDto
: stateDtos
){
500 //create new statedata
501 DefinedTermBase
<?
> newState
= DefinedTermBase
.getTermByUUID(dataDto
.getState().getUuid(), DefinedTermBase
.class);
502 StateData newStateData
= StateData
.NewInstance(newState
);
503 elementBase
.addStateData(newStateData
);
505 desc
.addElement(elementBase
);
507 if (descElement
instanceof QuantitativeDataDto
){
509 QuantitativeData data
= QuantitativeData
.NewInstance(feature
);
510 if (((QuantitativeDataDto
) descElement
).getMeasurementUnit() != null){
511 MeasurementUnit unit
= DefinedTermBase
.getTermByClassAndUUID(MeasurementUnit
.class, ((QuantitativeDataDto
) descElement
).getMeasurementUnit().getUuid());
514 Set
<StatisticalMeasurementValue
> statisticalValues
= new HashSet
<>();
515 Set
<StatisticalMeasurementValueDto
> valueDtos
= ((QuantitativeDataDto
)descElement
).getValues();
516 data
.getStatisticalValues().clear();
517 for (StatisticalMeasurementValueDto dataDto
: valueDtos
){
518 //create new statedata
519 StatisticalMeasure sm
= DefinedTermBase
.getTermByClassAndUUID(StatisticalMeasure
.class, dataDto
.getType().getUuid());
520 StatisticalMeasurementValue newStatisticalMeasurement
= StatisticalMeasurementValue
.NewInstance(sm
, dataDto
.getValue());
521 statisticalValues
.add(newStatisticalMeasurement
);
522 data
.addStatisticalValue(newStatisticalMeasurement
);
525 // data.getStatisticalValues().addAll(statisticalValues);
526 data
= StructuredDescriptionAggregation
.handleMissingMinOrMax(data
,
527 MissingMinimumMode
.MinToZero
, MissingMaximumMode
.MaxToMin
);
528 desc
.addElement(data
);
533 DescriptionElementBase elementBase
= equalUuidsElements
.get(0);
534 if (elementBase
.isInstanceOf(CategoricalData
.class)){
535 CategoricalData data
= HibernateProxyHelper
.deproxy(elementBase
, CategoricalData
.class);
536 List
<StateData
> states
= new ArrayList
<>(data
.getStateData());
537 List
<StateDataDto
> stateDtos
= ((CategoricalDataDto
)descElement
).getStates();
539 data
.getStateData().clear();
540 if (stateDtos
.isEmpty()){
541 desc
.removeElement(data
);
543 for (StateDataDto dataDto
: stateDtos
){
544 DefinedTermBase
<?
> newState
= DefinedTermBase
.getTermByUUID(dataDto
.getState().getUuid(), DefinedTermBase
.class);
545 StateData newStateData
= StateData
.NewInstance(newState
);
546 data
.addStateData(newStateData
);
549 }else if (elementBase
.isInstanceOf(QuantitativeData
.class)){
550 QuantitativeData data
= HibernateProxyHelper
.deproxy(elementBase
, QuantitativeData
.class);
552 Set
<StatisticalMeasurementValue
> statisticalValues
= new HashSet
<>();
553 if (((QuantitativeDataDto
) descElement
).getMeasurementUnit() != null){
554 MeasurementUnit unit
= DefinedTermBase
.getTermByClassAndUUID(MeasurementUnit
.class, ((QuantitativeDataDto
) descElement
).getMeasurementUnit().getUuid());
555 if (data
.getUnit() == null || (data
.getUnit() != null && !data
.getUnit().equals(unit
))){
559 Set
<StatisticalMeasurementValueDto
> valueDtos
= ((QuantitativeDataDto
)descElement
).getValues();
560 data
.getStatisticalValues().clear();
561 if (valueDtos
.isEmpty()){
562 desc
.removeElement(data
);
564 for (StatisticalMeasurementValueDto dataDto
: valueDtos
){
565 //create new statedata
566 StatisticalMeasure statMeasure
= DefinedTermBase
.getTermByClassAndUUID(StatisticalMeasure
.class, dataDto
.getType().getUuid());
568 StatisticalMeasurementValue newStatisticalMeasurement
= StatisticalMeasurementValue
.NewInstance(statMeasure
, dataDto
.getValue());
569 statisticalValues
.add(newStatisticalMeasurement
);
570 data
.addStatisticalValue(newStatisticalMeasurement
);
573 // data.getStatisticalValues().addAll(statisticalValues);
574 data
= StructuredDescriptionAggregation
.handleMissingMinOrMax(data
,
575 MissingMinimumMode
.MinToZero
, MissingMaximumMode
.MaxToMin
);
580 //remove deleted elements
584 descriptionSpecimenMap
.get(describedObjectUuid
).add(desc
);
589 if (description
!= null){
590 mergeResult
= dao
.merge(description
, true);
591 result
.addUpdatedObject( mergeResult
.getMergedEntity());
594 // if (description instanceof SpecimenDescription){
595 // result.addUpdatedObject(mergeResult.getMergedEntity().getDescribedSpecimenOrObservation());
596 // }else if (description instanceof TaxonDescription){
597 // result.addUpdatedObject(((TaxonDescription)mergeResult.getMergedEntity()).getTaxon());
598 // }else if (description instanceof TaxonNameDescription){
599 // result.addUpdatedObject(((TaxonNameDescription)mergeResult.getMergedEntity()).getTaxonName());
611 @Transactional(readOnly
= false)
612 public DeleteResult
deleteDescription(DescriptionBase
<?
> description
) {
614 DeleteResult deleteResult
= new DeleteResult();
615 if (description
== null){
618 //avoid lazy init exception
619 description
= load(description
.getId(), Arrays
.asList("descriptiveDataSets"));
621 deleteResult
= isDeletable(description
.getUuid());
622 if (deleteResult
.getRelatedObjects() != null && deleteResult
.getRelatedObjects().size() == 1){
623 Iterator
<CdmBase
> relObjects
= deleteResult
.getRelatedObjects().iterator();
624 CdmBase next
= relObjects
.next();
625 if (next
instanceof CdmLinkSource
){
626 CdmLinkSource source
= (CdmLinkSource
)next
;
627 ICdmTarget target
= source
.getTarget();
632 if (deleteResult
.isOk() ){
633 CdmBase
.deproxy(description
);
634 if (description
instanceof TaxonDescription
){
635 TaxonDescription taxDescription
= (TaxonDescription
)description
;
636 Taxon tax
= taxDescription
.getTaxon();
638 tax
.removeDescription(taxDescription
, true);
639 deleteResult
.addUpdatedObject(tax
);
642 else if (description
instanceof SpecimenDescription
){
643 SpecimenDescription specimenDescription
= (SpecimenDescription
)description
;
644 SpecimenOrObservationBase
<?
> specimen
= specimenDescription
.getDescribedSpecimenOrObservation();
645 if (specimen
!= null){
646 specimen
.removeDescription(specimenDescription
);
647 deleteResult
.addUpdatedObject(specimen
);
651 for (DescriptiveDataSet dataset
: description
.getDescriptiveDataSets()) {
652 dataset
.removeDescription(description
);
655 dao
.delete(description
);
656 deleteResult
.addDeletedObject(description
);
657 deleteResult
.setCdmEntity(description
);
659 logger
.info(deleteResult
.getExceptions().toString());
666 @Transactional(readOnly
= false)
667 public DeleteResult
deleteDescription(UUID descriptionUuid
) {
668 return deleteDescription(dao
.load(descriptionUuid
));
674 public DeleteResult
isDeletable(UUID descriptionUuid
){
675 DeleteResult result
= new DeleteResult();
676 DescriptionBase
<?
> description
= this.load(descriptionUuid
);
677 Set
<CdmBase
> references
= commonService
.getReferencingObjectsForDeletion(description
);
679 if (references
== null || references
.isEmpty()){
682 for (CdmBase ref
: references
){
683 if (description
instanceof TaxonDescription
&& ref
instanceof Taxon
&& ref
.equals(((TaxonDescription
)description
).getTaxon())){
685 } else if (description
instanceof TaxonNameDescription
&& ref
instanceof TaxonName
&& ref
.equals(((TaxonNameDescription
)description
).getTaxonName())){
687 } else if (description
instanceof SpecimenDescription
&& ref
instanceof SpecimenOrObservationBase
&& ref
.equals(((SpecimenDescription
)description
).getDescribedSpecimenOrObservation())){
689 } else if (ref
instanceof DescriptionElementBase
){
691 } else if (ref
instanceof CdmLinkSource
&& ((CdmLinkSource
)ref
).hasNoTarget()) {
692 continue; //maybe only workaround #9801
694 String message
= "The description can't be completely deleted because it is referenced by " + ref
.getUserFriendlyTypeName() ;
696 result
.addException(new ReferencedObjectUndeletableException(message
));
697 result
.addRelatedObject(ref
);
706 public <T
extends DescriptionElementBase
> List
<T
> getDescriptionElementsForTaxon(
707 Taxon taxon
, Set
<Feature
> features
,
708 Class
<T
> type
, Integer pageSize
,
709 Integer pageNumber
, List
<String
> propertyPaths
) {
710 return listDescriptionElementsForTaxon(taxon
, features
, type
, pageSize
, pageNumber
, propertyPaths
);
714 public <T
extends DescriptionElementBase
> List
<T
> listDescriptionElementsForTaxon(
715 Taxon taxon
, Set
<Feature
> features
,
716 Class
<T
> type
, Integer pageSize
,
717 Integer pageNumber
, List
<String
> propertyPaths
) {
718 return dao
.getDescriptionElementForTaxon(taxon
.getUuid(), features
, type
, pageSize
, pageNumber
, propertyPaths
);
722 public <T
extends DescriptionElementBase
> Pager
<T
> pageDescriptionElementsForTaxon(
723 Taxon taxon
, Set
<Feature
> features
,
724 Class
<T
> type
, Integer pageSize
,
725 Integer pageNumber
, List
<String
> propertyPaths
) {
726 if (logger
.isDebugEnabled()){logger
.debug(" get count ...");}
727 Long count
= dao
.countDescriptionElementForTaxon(taxon
.getUuid(), features
, type
);
728 List
<T
> descriptionElements
;
729 if(AbstractPagerImpl
.hasResultsInRange(count
, pageNumber
, pageSize
)){ // no point checking again
730 if (logger
.isDebugEnabled()){logger
.debug(" get list ...");}
731 descriptionElements
= listDescriptionElementsForTaxon(taxon
, features
, type
, pageSize
, pageNumber
, propertyPaths
);
733 descriptionElements
= new ArrayList
<T
>(0);
735 if (logger
.isDebugEnabled()){logger
.debug(" service - DONE ...");}
736 return new DefaultPagerImpl
<T
>(pageNumber
, count
, pageSize
, descriptionElements
);
740 public String
generateNaturalLanguageDescription(TermTree featureTree
,
741 TaxonDescription description
, List
<Language
> preferredLanguages
, String separator
) {
743 Language lang
= preferredLanguages
.size() > 0 ? preferredLanguages
.get(0) : Language
.DEFAULT();
745 description
= (TaxonDescription
)load(description
.getUuid());
746 featureTree
= featureTreeDao
.load(featureTree
.getUuid());
748 StringBuilder naturalLanguageDescription
= new StringBuilder();
750 MarkerType useMarkerType
= (MarkerType
) definedTermDao
.load(UUID
.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
751 boolean isUseDescription
= false;
752 if(!description
.getMarkers().isEmpty()) {
753 for (Marker marker
: description
.getMarkers()) {
754 MarkerType markerType
= marker
.getMarkerType();
755 if (markerType
.equals(useMarkerType
)) {
756 isUseDescription
= true;
762 if(description
.hasStructuredData() && !isUseDescription
){
765 String lastCategory
= null;
766 String categorySeparator
= ". ";
768 List
<TextData
> textDataList
;
769 TextData naturalLanguageDescriptionText
= null;
771 boolean useMicroFormatQuantitativeDescriptionBuilder
= false;
773 if(useMicroFormatQuantitativeDescriptionBuilder
){
775 MicroFormatQuantitativeDescriptionBuilder micro
= new MicroFormatQuantitativeDescriptionBuilder();
776 naturalLanguageGenerator
.setQuantitativeDescriptionBuilder(micro
);
777 naturalLanguageDescriptionText
= naturalLanguageGenerator
.generateSingleTextData(featureTree
, (description
), lang
);
781 naturalLanguageDescriptionText
= naturalLanguageGenerator
.generateSingleTextData(
787 return naturalLanguageDescriptionText
.getText(lang
);
790 // boolean doItBetter = false;
792 // for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
793 // if(textData.getMultilanguageText().size() > 0){
795 // if (!textData.getFeature().equals(Feature.UNKNOWN())) {
796 // String featureLabel = textData.getFeature().getLabel(lang);
801 // * The code lines below are desinged to handle
802 // * a special case where as the feature label contains
803 // * hierarchical information on the features. This code
804 // * exist only as a base for discussion, and is not
805 // * intendet to be used in production.
807 // featureLabel = StringUtils.remove(featureLabel, '>');
809 // String[] labelTokens = StringUtils.split(featureLabel, '<');
810 // if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
811 // if(naturalLanguageDescription.length() > 0){
812 // naturalLanguageDescription.append(separator);
814 // naturalLanguageDescription.append(labelTokens[1]);
816 // if(naturalLanguageDescription.length() > 0){
817 // naturalLanguageDescription.append(categorySeparator);
819 // naturalLanguageDescription.append(StringUtils.join(labelTokens));
821 // lastCategory = labelTokens[0];
822 // // end of demo code
824 // if(naturalLanguageDescription.length() > 0){
825 // naturalLanguageDescription.append(separator);
827 // naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
830 // if(naturalLanguageDescription.length() > 0){
831 // naturalLanguageDescription.append(separator);
834 // String text = textData.getMultilanguageText().values().iterator().next().getText();
835 // naturalLanguageDescription.append(text);
841 else if (isUseDescription
) {
842 //AT: Left Blank in case we need to generate a Natural language text string.
844 return naturalLanguageDescription
.toString();
849 public boolean hasStructuredData(DescriptionBase
<?
> description
) {
850 return load(description
.getUuid()).hasStructuredData();
855 // @Transactional(readOnly = false)
856 public UpdateResult
moveDescriptionElementsToDescription(
857 Collection
<DescriptionElementBase
> descriptionElements
,
858 DescriptionBase targetDescription
,
860 boolean setNameInSource
) {
862 UpdateResult result
= new UpdateResult();
863 if (descriptionElements
.isEmpty() || descriptionElements
.iterator().next() == null){
869 if (! isCopy
&& descriptionElements
== descriptionElements
.iterator().next().getInDescription().getElements()){
870 //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
871 descriptionElements
= new HashSet
<DescriptionElementBase
>(descriptionElements
);
872 // descriptionElementsTmp.addAll(descriptionElements);
873 // descriptionElements = descriptionElementsTmp;
875 for (DescriptionElementBase element
: descriptionElements
){
876 DescriptionBase
<?
> description
= element
.getInDescription();
877 description
= HibernateProxyHelper
.deproxy(dao
.load(description
.getUuid()));
879 TaxonName name
= null;
880 if (description
instanceof TaxonDescription
){
881 TaxonDescription taxonDescription
= HibernateProxyHelper
.deproxy(description
, TaxonDescription
.class);
882 if (taxonDescription
.getTaxon() != null){
883 taxon
= (Taxon
) taxonDao
.load(taxonDescription
.getTaxon().getUuid());
884 name
= taxon
.getName();
889 DescriptionElementBase newElement
= element
.clone();
890 if (setNameInSource
) {
891 for (DescriptionElementSource source
: newElement
.getSources()){
892 if (source
.getNameUsedInSource() == null){
893 source
.setNameUsedInSource(name
);
898 targetDescription
.addElement(newElement
);
900 description
.removeElement(element
);
901 dao
.saveOrUpdate(description
);
902 result
.addUpdatedObject(description
);
903 // if (description.getElements().isEmpty()){
904 // if (description instanceof TaxonDescription){
905 // TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
906 // if (taxDescription.getTaxon() != null){
907 // taxDescription.getTaxon().removeDescription((TaxonDescription)description);
910 // dao.delete(description);
913 // dao.saveOrUpdate(description);
914 // result.addUpdatedObject(description);
920 dao
.saveOrUpdate(targetDescription
);
921 result
.addUpdatedObject(targetDescription
);
922 if (targetDescription
instanceof TaxonDescription
){
923 result
.addUpdatedObject(((TaxonDescription
)targetDescription
).getTaxon());
929 @Transactional(readOnly
= false)
930 public UpdateResult
moveDescriptionElementsToDescription(
931 Set
<UUID
> descriptionElementUUIDs
,
932 UUID targetDescriptionUuid
,
933 boolean isCopy
, boolean setNameInSource
) {
934 Set
<DescriptionElementBase
> descriptionElements
= new HashSet
<DescriptionElementBase
>();
935 for(UUID deUuid
: descriptionElementUUIDs
) {
936 DescriptionElementBase element
= descriptionElementDao
.load(deUuid
);
937 if (element
!= null){
938 descriptionElements
.add(element
);
941 DescriptionBase targetDescription
= dao
.load(targetDescriptionUuid
);
943 return moveDescriptionElementsToDescription(descriptionElements
, targetDescription
, isCopy
, setNameInSource
);
947 @Transactional(readOnly
= false)
948 public UpdateResult
moveDescriptionElementsToDescription(
949 Set
<UUID
> descriptionElementUUIDs
,
950 DescriptionBase targetDescription
,
951 boolean isCopy
, boolean setNameInSource
) {
952 Set
<DescriptionElementBase
> descriptionElements
= new HashSet
<DescriptionElementBase
>();
953 for(UUID deUuid
: descriptionElementUUIDs
) {
954 DescriptionElementBase element
= descriptionElementDao
.load(deUuid
);
955 if (element
!= null){
956 descriptionElements
.add(element
);
959 DescriptionBase newTargetDescription
;
960 if (targetDescription
.isPersited()){
961 newTargetDescription
= dao
.load(targetDescription
.getUuid());
963 if (targetDescription
instanceof TaxonDescription
){
964 Taxon taxon
= (Taxon
)taxonDao
.load(((TaxonDescription
)targetDescription
).getTaxon().getUuid());
966 newTargetDescription
= TaxonDescription
.NewInstance(taxon
, targetDescription
.isImageGallery());
968 }else if (targetDescription
instanceof TaxonNameDescription
){
969 TaxonName name
= nameDao
.load(((TaxonNameDescription
)targetDescription
).getTaxonName().getUuid());
970 newTargetDescription
= TaxonNameDescription
.NewInstance(name
);
972 SpecimenOrObservationBase specimen
= occurrenceDao
.load(((SpecimenDescription
)targetDescription
).getDescribedSpecimenOrObservation().getUuid());
973 newTargetDescription
= SpecimenDescription
.NewInstance(specimen
);
976 newTargetDescription
.addSources(targetDescription
.getSources());
977 newTargetDescription
.setTitleCache(targetDescription
.getTitleCache(), targetDescription
.isProtectedTitleCache());
980 return moveDescriptionElementsToDescription(descriptionElements
, newTargetDescription
, isCopy
, setNameInSource
);
985 @Transactional(readOnly
= false)
986 public UpdateResult
moveDescriptionElementsToDescription(
987 Set
<UUID
> descriptionElementUUIDs
,
988 UUID targetTaxonUuid
,
990 boolean isCopy
, boolean setNameInSource
) {
991 Taxon targetTaxon
= CdmBase
.deproxy(taxonDao
.load(targetTaxonUuid
), Taxon
.class);
992 DescriptionBase targetDescription
= TaxonDescription
.NewInstance(targetTaxon
);
993 targetDescription
.setTitleCache(moveMessage
, true);
994 Annotation annotation
= Annotation
.NewInstance(moveMessage
, Language
.getDefaultLanguage());
995 annotation
.setAnnotationType(AnnotationType
.TECHNICAL());
996 targetDescription
.addAnnotation(annotation
);
998 targetDescription
= dao
.save(targetDescription
);
999 Set
<DescriptionElementBase
> descriptionElements
= new HashSet
<DescriptionElementBase
>();
1000 for(UUID deUuid
: descriptionElementUUIDs
) {
1001 descriptionElements
.add(descriptionElementDao
.load(deUuid
));
1004 return moveDescriptionElementsToDescription(descriptionElements
, targetDescription
, isCopy
, setNameInSource
);
1008 public Pager
<TermDto
> pageNamedAreasInUse(boolean includeAllParents
, Integer pageSize
,
1010 List
<TermDto
> results
= dao
.listNamedAreasInUse(includeAllParents
, null, null);
1011 List
<TermDto
> subList
= PagerUtils
.pageList(results
, pageIndex
, pageSize
);
1012 return new DefaultPagerImpl
<TermDto
>(pageIndex
, results
.size(), pageSize
, subList
);
1017 @Transactional(readOnly
= false)
1018 public UpdateResult
moveTaxonDescriptions(Taxon sourceTaxon
, Taxon targetTaxon
, boolean setNameInSource
) {
1019 List
<TaxonDescription
> descriptions
= new ArrayList
<>(sourceTaxon
.getDescriptions());
1020 UpdateResult result
= new UpdateResult();
1021 result
.addUpdatedObject(sourceTaxon
);
1022 result
.addUpdatedObject(targetTaxon
);
1023 for(TaxonDescription description
: descriptions
){
1024 targetTaxon
.addDescription(prepareDescriptionForMove(description
, sourceTaxon
, setNameInSource
));
1029 private TaxonDescription
prepareDescriptionForMove(TaxonDescription description
, Taxon sourceTaxon
, boolean setNameInSource
){
1030 String moveMessage
= String
.format("Description moved from %s", sourceTaxon
);
1031 if(description
.isProtectedTitleCache()){
1032 String separator
= "";
1033 if(!StringUtils
.isBlank(description
.getTitleCache())){
1036 description
.setTitleCache(description
.getTitleCache() + separator
+ moveMessage
, true);
1039 description
.setTitleCache(moveMessage
, true);
1041 Annotation annotation
= Annotation
.NewInstance(moveMessage
, Language
.getDefaultLanguage());
1042 annotation
.setAnnotationType(AnnotationType
.TECHNICAL());
1043 description
.addAnnotation(annotation
);
1044 if(setNameInSource
){
1045 for (DescriptionElementBase element
: description
.getElements()){
1046 for (DescriptionElementSource source
: element
.getSources()){
1047 if (source
.getNameUsedInSource() == null){
1048 source
.setNameUsedInSource(sourceTaxon
.getName());
1057 @Transactional(readOnly
= false)
1058 public UpdateResult
moveTaxonDescriptions(UUID sourceTaxonUuid
, UUID targetTaxonUuid
, boolean setNameInSource
) {
1059 Taxon sourceTaxon
= HibernateProxyHelper
.deproxy(taxonDao
.load(sourceTaxonUuid
), Taxon
.class);
1060 Taxon targetTaxon
= HibernateProxyHelper
.deproxy(taxonDao
.load(targetTaxonUuid
), Taxon
.class);
1061 return moveTaxonDescriptions(sourceTaxon
, targetTaxon
, setNameInSource
);
1066 @Transactional(readOnly
= false)
1067 public UpdateResult
moveTaxonDescription(UUID descriptionUuid
, UUID targetTaxonUuid
, boolean setNameInSource
){
1068 TaxonDescription description
= HibernateProxyHelper
.deproxy(dao
.load(descriptionUuid
), TaxonDescription
.class);
1069 Taxon targetTaxon
= HibernateProxyHelper
.deproxy(taxonDao
.load(targetTaxonUuid
), Taxon
.class);
1070 Taxon sourceTaxon
= description
.getTaxon();
1071 UpdateResult result
= new UpdateResult();
1072 result
.addUpdatedObject(sourceTaxon
);
1073 result
.addUpdatedObject(targetTaxon
);
1075 targetTaxon
.addDescription(prepareDescriptionForMove(description
, sourceTaxon
, setNameInSource
));
1080 // FIXME Query should not be used in service layer
1082 public DescriptionBaseDto
loadDto(UUID descriptionUuid
) {
1083 String sqlSelect
= DescriptionBaseDto
.getDescriptionBaseDtoSelect();
1084 Query
<Object
[]> query
= getSession().createQuery(sqlSelect
, Object
[].class);
1085 List
<UUID
> uuids
= new ArrayList
<>();
1086 uuids
.add(descriptionUuid
);
1087 query
.setParameterList("uuid", uuids
);
1089 List
<Object
[]> result
= query
.list();
1091 List
<DescriptionBaseDto
> list
= DescriptionBaseDto
.descriptionBaseDtoListFrom(result
);
1093 if (list
.size()== 1){
1094 DescriptionBaseDto dto
= list
.get(0);
1095 //get categorical data
1096 sqlSelect
= CategoricalDataDto
.getCategoricalDtoSelect();
1097 query
= getSession().createQuery(sqlSelect
);
1098 query
.setParameter("uuid", descriptionUuid
);
1099 @SuppressWarnings("unchecked")
1100 List
<Object
[]> resultCat
= query
.list();
1101 List
<CategoricalDataDto
> listCategorical
= CategoricalDataDto
.categoricalDataDtoListFrom(resultCat
);
1103 List
<UUID
> featureUuids
= new ArrayList
<>();
1104 for (CategoricalDataDto catDto
: listCategorical
){
1105 featureUuids
.add(catDto
.getFeatureUuid());
1107 Map
<UUID
, TermDto
> featureDtos
= termService
.findFeatureByUUIDsAsDtos(featureUuids
);
1108 for (CategoricalDataDto catDto
: listCategorical
){
1109 FeatureDto featuredto
= (FeatureDto
)featureDtos
.get(catDto
.getFeatureUuid());
1110 catDto
.setFeatureDto(featuredto
);
1112 dto
.getElements().addAll(listCategorical
);
1113 //get quantitative data
1114 sqlSelect
= QuantitativeDataDto
.getQuantitativeDataDtoSelect();
1115 query
= getSession().createQuery(sqlSelect
);
1116 query
.setParameter("uuid", descriptionUuid
);
1117 @SuppressWarnings("unchecked")
1118 List
<Object
[]> resultQuant
= query
.list();
1119 List
<QuantitativeDataDto
> listQuant
= QuantitativeDataDto
.quantitativeDataDtoListFrom(resultQuant
);
1120 dto
.getElements().addAll(listQuant
);
1127 // FIXME Query should not be used in service layer
1129 public List
<DescriptionBaseDto
> loadDtos(Set
<UUID
> descriptionUuids
) {
1130 String sqlSelect
= DescriptionBaseDto
.getDescriptionBaseDtoSelect();
1131 Query
<Object
[]> query
= getSession().createQuery(sqlSelect
, Object
[].class);
1132 query
.setParameterList("uuid", descriptionUuids
);
1134 List
<Object
[]> result
= query
.list();
1136 List
<DescriptionBaseDto
> list
= DescriptionBaseDto
.descriptionBaseDtoListFrom(result
);
1138 for (DescriptionBaseDto dto
: list
){
1140 //get categorical data
1141 sqlSelect
= CategoricalDataDto
.getCategoricalDtoSelect();
1142 query
= getSession().createQuery(sqlSelect
, Object
[].class);
1143 query
.setParameter("uuid", dto
.getDescriptionUuid());
1144 List
<Object
[]> resultCat
= query
.list();
1145 List
<CategoricalDataDto
> listCategorical
= CategoricalDataDto
.categoricalDataDtoListFrom(resultCat
);
1147 List
<UUID
> featureUuids
= new ArrayList
<>();
1148 for (CategoricalDataDto catDto
: listCategorical
){
1149 featureUuids
.add(catDto
.getFeatureUuid());
1151 Map
<UUID
, TermDto
> featureDtos
= termService
.findFeatureByUUIDsAsDtos(featureUuids
);
1152 for (CategoricalDataDto catDto
: listCategorical
){
1153 FeatureDto featuredto
= (FeatureDto
)featureDtos
.get(catDto
.getFeatureUuid());
1154 catDto
.setFeatureDto(featuredto
);
1156 dto
.getElements().addAll(listCategorical
);
1157 //get quantitative data
1158 sqlSelect
= QuantitativeDataDto
.getQuantitativeDataDtoSelect();
1159 query
= getSession().createQuery(sqlSelect
, Object
[].class);
1160 query
.setParameter("uuid", dto
.getDescriptionUuid());
1161 List
<Object
[]> resultQuant
= query
.list();
1162 List
<QuantitativeDataDto
> listQuant
= QuantitativeDataDto
.quantitativeDataDtoListFrom(resultQuant
);
1163 dto
.getElements().addAll(listQuant
);
1168 // FIXME Query should not be used in service layer
1170 public List
<DescriptionBaseDto
> loadDtosForTaxon(UUID taxonUuid
) {
1171 String sqlSelect
= DescriptionBaseDto
.getDescriptionBaseDtoForTaxonSelect();
1172 Query
<Object
[]> query
= getSession().createQuery(sqlSelect
, Object
[].class);
1173 query
.setParameter("uuid", taxonUuid
);
1175 List
<Object
[]> result
= query
.list();
1176 List
<DescriptionBaseDto
> list
= DescriptionBaseDto
.descriptionBaseDtoListFrom(result
);
1182 public TaxonNodeDto
findTaxonNodeDtoForIndividualAssociation(UUID specimenUuid
, UUID classificationUuid
) {
1183 //get specimen used in description
1184 //get individial associations with this specimen
1185 //get taxon node for the classification
1186 List
<SortableTaxonNodeQueryResult
> result
= dao
.getNodeOfIndividualAssociationForSpecimen(specimenUuid
, classificationUuid
);
1188 if (!result
.isEmpty()){
1189 List
<TaxonNodeDto
> dtos
= taxonNodeDao
.createNodeDtos(result
);
1190 if (dtos
.size() == 1){
1193 logger
.debug("There is more than one taxon associated to the specimen with uuid: " + specimenUuid
+ " return the first in the list");