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
;
19 import java
.util
.UUID
;
20 import java
.util
.stream
.Collectors
;
22 import org
.apache
.commons
.lang3
.StringUtils
;
23 import org
.apache
.logging
.log4j
.LogManager
;
24 import org
.apache
.logging
.log4j
.Logger
;
25 import org
.hibernate
.query
.Query
;
26 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
27 import org
.springframework
.stereotype
.Service
;
28 import org
.springframework
.transaction
.annotation
.Transactional
;
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
.TaxonDistributionDTO
;
34 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
35 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
36 import eu
.etaxonomy
.cdm
.api
.service
.pager
.PagerUtils
;
37 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.AbstractPagerImpl
;
38 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
39 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
40 import eu
.etaxonomy
.cdm
.format
.description
.MicroFormatQuantitativeDescriptionBuilder
;
41 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
42 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
43 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
44 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
45 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
46 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
47 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
48 import eu
.etaxonomy
.cdm
.model
.description
.CategoricalData
;
49 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
50 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
51 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
52 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionType
;
53 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveDataSet
;
54 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
55 import eu
.etaxonomy
.cdm
.model
.description
.IndividualsAssociation
;
56 import eu
.etaxonomy
.cdm
.model
.description
.MeasurementUnit
;
57 import eu
.etaxonomy
.cdm
.model
.description
.QuantitativeData
;
58 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
59 import eu
.etaxonomy
.cdm
.model
.description
.StateData
;
60 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasure
;
61 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasurementValue
;
62 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
63 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
64 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
65 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
66 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
67 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
68 import eu
.etaxonomy
.cdm
.model
.occurrence
.DeterminationEvent
;
69 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
70 import eu
.etaxonomy
.cdm
.model
.reference
.CdmLinkSource
;
71 import eu
.etaxonomy
.cdm
.model
.reference
.ICdmTarget
;
72 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
73 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTerm
;
74 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTermBase
;
75 import eu
.etaxonomy
.cdm
.model
.term
.TermTree
;
76 import eu
.etaxonomy
.cdm
.model
.term
.TermVocabulary
;
77 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionDao
;
78 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionElementDao
;
79 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptiveDataSetDao
;
80 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IStatisticalMeasurementValueDao
;
81 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
82 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
83 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
84 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonNodeDao
;
85 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.IDefinedTermDao
;
86 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.ITermNodeDao
;
87 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.ITermTreeDao
;
88 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.ITermVocabularyDao
;
89 import eu
.etaxonomy
.cdm
.persistence
.dto
.CategoricalDataDto
;
90 import eu
.etaxonomy
.cdm
.persistence
.dto
.DescriptionBaseDto
;
91 import eu
.etaxonomy
.cdm
.persistence
.dto
.DescriptionElementDto
;
92 import eu
.etaxonomy
.cdm
.persistence
.dto
.MergeResult
;
93 import eu
.etaxonomy
.cdm
.persistence
.dto
.QuantitativeDataDto
;
94 import eu
.etaxonomy
.cdm
.persistence
.dto
.SortableTaxonNodeQueryResult
;
95 import eu
.etaxonomy
.cdm
.persistence
.dto
.StateDataDto
;
96 import eu
.etaxonomy
.cdm
.persistence
.dto
.StatisticalMeasurementValueDto
;
97 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
98 import eu
.etaxonomy
.cdm
.persistence
.dto
.TermDto
;
99 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
100 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
104 * @author a.kohlbecker
109 @Transactional(readOnly
= true)
110 public class DescriptionServiceImpl
111 extends IdentifiableServiceBase
<DescriptionBase
,IDescriptionDao
>
112 implements IDescriptionService
{
114 private static final Logger logger
= LogManager
.getLogger();
116 protected IDescriptionElementDao descriptionElementDao
;
117 protected ITermTreeDao featureTreeDao
;
118 protected IDescriptiveDataSetDao descriptiveDataSetDao
;
119 protected ITermNodeDao termNodeDao
;
120 protected ITermVocabularyDao vocabularyDao
;
121 protected IDefinedTermDao definedTermDao
;
122 protected IStatisticalMeasurementValueDao statisticalMeasurementValueDao
;
123 protected ITaxonDao taxonDao
;
124 protected ITaxonNameDao nameDao
;
125 protected IOccurrenceDao occurrenceDao
;
126 protected ITaxonNodeDao taxonNodeDao
;
127 protected IDescriptiveDataSetDao dataSetDao
;
128 protected ITermService termService
;
130 //TODO change to Interface
131 private NaturalLanguageGenerator naturalLanguageGenerator
;
134 protected void setFeatureTreeDao(ITermTreeDao featureTreeDao
) {
135 this.featureTreeDao
= featureTreeDao
;
139 protected void setDescriptiveDataSetDao(IDescriptiveDataSetDao descriptiveDataSetDao
) {
140 this.descriptiveDataSetDao
= descriptiveDataSetDao
;
144 protected void setTermNodeDao(ITermNodeDao featureNodeDao
) {
145 this.termNodeDao
= featureNodeDao
;
149 protected void setVocabularyDao(ITermVocabularyDao vocabularyDao
) {
150 this.vocabularyDao
= vocabularyDao
;
154 protected void setDefinedTermDao(IDefinedTermDao definedTermDao
) {
155 this.definedTermDao
= definedTermDao
;
159 protected void setTermService(ITermService definedTermService
) {
160 this.termService
= definedTermService
;
165 protected void statisticalMeasurementValueDao(IStatisticalMeasurementValueDao statisticalMeasurementValueDao
) {
166 this.statisticalMeasurementValueDao
= statisticalMeasurementValueDao
;
170 protected void setDescriptionElementDao(IDescriptionElementDao descriptionElementDao
) {
171 this.descriptionElementDao
= descriptionElementDao
;
175 protected void setNaturalLanguageGenerator(NaturalLanguageGenerator naturalLanguageGenerator
) {
176 this.naturalLanguageGenerator
= naturalLanguageGenerator
;
180 protected void setTaxonDao(ITaxonDao taxonDao
) {
181 this.taxonDao
= taxonDao
;
185 protected void setTaxonNodeDao(ITaxonNodeDao taxonNodeDao
) {
186 this.taxonNodeDao
= taxonNodeDao
;
190 protected void setDataSetDao(IDescriptiveDataSetDao dataSetDao
) {
191 this.dataSetDao
= dataSetDao
;
194 public DescriptionServiceImpl() {
195 logger
.debug("Load DescriptionService Bean");
199 @Transactional(readOnly
= false)
200 public UpdateResult
updateCaches(Class
<?
extends DescriptionBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<DescriptionBase
> cacheStrategy
, IProgressMonitor monitor
) {
202 clazz
= DescriptionBase
.class;
204 return super.updateCachesImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
208 public TermVocabulary
<Feature
> getDefaultFeatureVocabulary(){
209 String uuidFeature
= "b187d555-f06f-4d65-9e53-da7c93f8eaa8";
210 UUID featureUuid
= UUID
.fromString(uuidFeature
);
211 return vocabularyDao
.findByUuid(featureUuid
);
216 protected void setDao(IDescriptionDao dao
) {
221 public long count(Class
<?
extends DescriptionBase
> type
, Boolean hasImages
, Boolean hasText
,Set
<Feature
> feature
) {
222 return dao
.countDescriptions(type
, hasImages
, hasText
, feature
);
226 public <T
extends DescriptionElementBase
> Pager
<T
> pageDescriptionElements(DescriptionBase description
, Class
<?
extends DescriptionBase
> descriptionType
,
227 Set
<Feature
> features
, Class
<T
> type
, boolean includeUnpublished
,
228 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
230 List
<T
> results
= listDescriptionElements(description
, descriptionType
, features
, type
, includeUnpublished
,
231 pageSize
, pageNumber
, propertyPaths
);
232 return new DefaultPagerImpl
<>(pageNumber
, Integer
.valueOf(results
.size()).longValue(), pageSize
, results
);
236 public <T
extends DescriptionElementBase
> List
<T
> listDescriptionElements(DescriptionBase description
,
237 Class
<?
extends DescriptionBase
> descriptionType
,
238 Set
<Feature
> features
, Class
<T
> type
, boolean includeUnpublished
,
239 Integer pageSize
, Integer pageNumber
,
240 List
<String
> propertyPaths
) {
242 long numberOfResults
= dao
.countDescriptionElements(description
, descriptionType
, features
, type
, includeUnpublished
);
243 List
<T
> results
= new ArrayList
<>();
244 if(AbstractPagerImpl
.hasResultsInRange(numberOfResults
, pageNumber
, pageSize
)) {
245 results
= dao
.getDescriptionElements(description
, descriptionType
, features
, type
, includeUnpublished
, pageSize
, pageNumber
, propertyPaths
);
251 public Pager
<Media
> getMedia(DescriptionElementBase descriptionElement
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
252 Long numberOfResults
= descriptionElementDao
.countMedia(descriptionElement
);
254 List
<Media
> results
= new ArrayList
<>();
255 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
256 results
= descriptionElementDao
.getMedia(descriptionElement
, pageSize
, pageNumber
, propertyPaths
);
259 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
263 public Pager
<TaxonDescription
> pageTaxonDescriptions(Taxon taxon
, Set
<DefinedTerm
> scopes
, Set
<NamedArea
> geographicalScope
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
264 Set
<MarkerType
> markerTypes
= null;
265 Set
<DescriptionType
> descriptionTypes
= null;
266 return pageTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
270 public List
<TaxonDescription
> listTaxonDescriptions(Taxon taxon
, Set
<DefinedTerm
> scopes
, Set
<NamedArea
> geographicalScope
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
271 Set
<MarkerType
> markerTypes
= null;
272 Set
<DescriptionType
> descriptionTypes
= null;
273 return listTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
277 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
) {
278 long numberOfResults
= dao
.countTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
);
280 List
<TaxonDescription
> results
= new ArrayList
<>();
281 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
282 results
= dao
.listTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
285 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
289 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
) {
290 List
<TaxonDescription
> results
= dao
.listTaxonDescriptions(taxon
, scopes
, geographicalScope
, markerTypes
, descriptionTypes
, pageSize
, pageNumber
, propertyPaths
);
296 public List
<Media
> listTaxonDescriptionMedia(UUID taxonUuid
, boolean limitToGalleries
, Set
<MarkerType
> markerTypes
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
){
297 return this.dao
.listTaxonDescriptionMedia(taxonUuid
, limitToGalleries
, markerTypes
, pageSize
, pageNumber
, propertyPaths
);
301 public int countTaxonDescriptionMedia(UUID taxonUuid
, boolean limitToGalleries
, Set
<MarkerType
> markerTypes
){
302 return this.dao
.countTaxonDescriptionMedia(taxonUuid
, limitToGalleries
, markerTypes
);
306 public Pager
<TaxonNameDescription
> getTaxonNameDescriptions(TaxonName name
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
307 long numberOfResults
= dao
.countTaxonNameDescriptions(name
);
309 List
<TaxonNameDescription
> results
= new ArrayList
<>();
310 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
311 results
= dao
.getTaxonNameDescriptions(name
, pageSize
, pageNumber
,propertyPaths
);
314 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
319 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
) {
320 long numberOfResults
= dao
.countDescriptions(type
, hasImages
, hasText
, feature
);
322 @SuppressWarnings("rawtypes")
323 List
<DescriptionBase
> results
= new ArrayList
<>();
324 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
325 results
= dao
.listDescriptions(type
, hasImages
, hasText
, feature
, pageSize
, pageNumber
,orderHints
,propertyPaths
);
328 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
332 * FIXME Candidate for harmonization
333 * move: descriptionElementService.search
336 // public Pager<T> searchElements(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
337 public <S
extends DescriptionElementBase
> Pager
<S
> searchElements(Class
<S
> clazz
, String queryString
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
338 long numberOfResults
= descriptionElementDao
.count(clazz
, queryString
);
340 List
<S
> results
= new ArrayList
<>();
341 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
342 results
= (List
<S
>)descriptionElementDao
.search(clazz
, queryString
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
345 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
349 @Transactional(readOnly
= false)
350 public List
<MergeResult
<DescriptionBase
>> mergeDescriptionElements(Collection
<TaxonDistributionDTO
> descriptionElements
, boolean returnTransientEntity
) {
351 List
<MergeResult
<DescriptionBase
>> mergedObjects
= new ArrayList
<>();
353 for(TaxonDistributionDTO obj
: descriptionElements
) {
354 Iterator
<TaxonDescription
> iterator
= obj
.getDescriptionsWrapper().getDescriptions().iterator();
355 List
<DescriptionBase
> list
= new ArrayList(obj
.getDescriptionsWrapper().getDescriptions());
356 // Map<UUID, DescriptionBase> map = dao.saveOrUpdateAll(list);
357 // MergeResult<DescriptionBase> mergeResult = new MergeResult<DescriptionBase>(mergedEntity, newEntities)
358 // mergedObjects.add(map.values());
359 while (iterator
.hasNext()){
360 TaxonDescription desc
= iterator
.next();
361 mergedObjects
.add(dao
.merge(desc
, returnTransientEntity
));
365 return mergedObjects
;
369 @Transactional(readOnly
= false)
370 public UpdateResult
mergeDescriptions(Collection
<DescriptionBaseDto
> descriptions
, UUID descriptiveDataSetUuid
) {
372 UpdateResult result
= new UpdateResult();
373 DescriptiveDataSet dataSet
= descriptiveDataSetDao
.load(descriptiveDataSetUuid
);
374 Set
<DescriptionBase
> descriptionsOfDataSet
= dataSet
.getDescriptions();
375 HashMap
<UUID
, Set
<DescriptionBase
>> descriptionSpecimenMap
= new HashMap
<>();
376 Set
<DescriptionBase
> specimenDescriptions
;
377 for (DescriptionBase
<?
> descriptionBase
: descriptionsOfDataSet
){
378 if (descriptionBase
.getDescribedSpecimenOrObservation() != null){
379 specimenDescriptions
= descriptionSpecimenMap
.get(descriptionBase
.getDescribedSpecimenOrObservation().getUuid());
380 if (specimenDescriptions
== null){
381 specimenDescriptions
= new HashSet
<>();
383 specimenDescriptions
.add(descriptionBase
);
384 descriptionSpecimenMap
.put(descriptionBase
.getDescribedSpecimenOrObservation().getUuid(), specimenDescriptions
);
386 if (descriptionBase
instanceof TaxonDescription
){
387 specimenDescriptions
= descriptionSpecimenMap
.get(((TaxonDescription
)descriptionBase
).getTaxon().getUuid());
388 if (specimenDescriptions
== null){
389 specimenDescriptions
= new HashSet
<>();
391 specimenDescriptions
.add(descriptionBase
);
392 descriptionSpecimenMap
.put(((TaxonDescription
)descriptionBase
).getTaxon().getUuid(), specimenDescriptions
);
394 if (descriptionBase
instanceof TaxonNameDescription
){
395 specimenDescriptions
= descriptionSpecimenMap
.get(((TaxonNameDescription
)descriptionBase
).getTaxonName().getUuid());
396 if (specimenDescriptions
== null){
397 specimenDescriptions
= new HashSet
<>();
399 specimenDescriptions
.add(descriptionBase
);
400 descriptionSpecimenMap
.put(((TaxonNameDescription
)descriptionBase
).getTaxonName().getUuid(), specimenDescriptions
);
403 MergeResult
<DescriptionBase
> mergeResult
= null;
404 for(DescriptionBaseDto descDto
: descriptions
) {
406 UUID descriptionUUID
= descDto
.getDescriptionUuid();
407 DescriptionBase
<?
> description
= load(descriptionUUID
);
409 UUID describedObjectUuid
= null;
410 if (description
instanceof SpecimenDescription
){
411 describedObjectUuid
= descDto
.getSpecimenDto().getUuid();
412 }else if (description
instanceof TaxonDescription
){
413 describedObjectUuid
= descDto
.getTaxonDto().getUuid();
414 }else if (description
instanceof TaxonNameDescription
){
415 describedObjectUuid
= descDto
.getNameDto().getUuid();
418 Set
<DescriptionBase
> descSpecimen
= descriptionSpecimenMap
.get(describedObjectUuid
);
420 if (descSpecimen
!= null ){
422 // TODO: elements are Dtos now, no cdm entities, needs to get the value and replace or create new description element
423 Set
<DescriptionElementDto
> elements
= new HashSet
<>();
424 for (Object element
: descDto
.getElements()){
425 elements
.add((DescriptionElementDto
)element
);
428 DescriptionBase
<?
> desc
= null;
429 for (DescriptionBase
<?
> tempDesc
: descSpecimen
){
430 if (tempDesc
.getUuid().equals(descDto
.getDescriptionUuid())){
436 Set
<DescriptionElementBase
> removeElements
= new HashSet
<>();
437 Set
<DescriptionElementBase
> descriptionElements
= desc
.getElements();
438 for (DescriptionElementBase elementBase
: descriptionElements
){
439 UUID descElementUuid
= elementBase
.getUuid();
440 if (descElementUuid
!= null){
441 List
<DescriptionElementDto
> equalUuidsElements
= elements
.stream().filter( e
-> e
!= null && e
.getElementUuid() != null && e
.getElementUuid().equals(descElementUuid
)).collect(Collectors
.toList());
442 if (equalUuidsElements
.size() == 0 || (equalUuidsElements
.size() == 1 && equalUuidsElements
.get(0)instanceof QuantitativeDataDto
&& (((QuantitativeDataDto
)equalUuidsElements
.get(0)).getValues().isEmpty()) &&(((QuantitativeDataDto
)equalUuidsElements
.get(0)).getNoDataStatus() == null))){
443 removeElements
.add(elementBase
);
447 if (!removeElements
.isEmpty()){
448 for (DescriptionElementBase el
: removeElements
){
449 desc
.removeElement(el
);
453 // description.setDescribedSpecimenOrObservation(null);
455 for (DescriptionElementDto descElement
: elements
){
456 if (descElement
== null){
459 UUID descElementUuid
= descElement
.getElementUuid();
460 // if (descElement instanceof CategoricalDataDto && ((CategoricalDataDto)descElement).getStates().isEmpty() || descElement instanceof QuantitativeDataDto && ((QuantitativeDataDto)descElement).getValues().isEmpty()){
463 List
<DescriptionElementBase
> equalUuidsElements
= descriptionElements
.stream().filter( e
-> e
.getUuid().equals(descElementUuid
)).collect(Collectors
.toList());
464 Feature feature
= DefinedTermBase
.getTermByUUID(descElement
.getFeatureUuid(), Feature
.class);
466 if (equalUuidsElements
.size() == 0){
467 if (descElement
instanceof CategoricalDataDto
){
469 CategoricalData elementBase
= CategoricalData
.NewInstance(feature
);
470 List
<StateDataDto
> stateDtos
= ((CategoricalDataDto
)descElement
).getStates();
471 for (StateDataDto dataDto
: stateDtos
){
472 //create new statedata
473 if (dataDto
== null || dataDto
.getState() == null){
476 DefinedTermBase
<?
> newState
= DefinedTermBase
.getTermByUUID(dataDto
.getState().getUuid(), DefinedTermBase
.class);
477 StateData newStateData
= StateData
.NewInstance(newState
);
479 if (dataDto
.getModifiers()!= null && !dataDto
.getModifiers().isEmpty()) {
480 DefinedTerm modifier
= DefinedTermBase
.getTermByUUID(dataDto
.getModifiers().iterator().next().getUuid(), DefinedTerm
.class);
481 newStateData
.addModifier(modifier
);
484 elementBase
.addStateData(newStateData
);
486 desc
.addElement(elementBase
);
487 elementBase
.setNoDataStatus(((CategoricalDataDto
)descElement
).getNoDataStatus());
489 if (descElement
instanceof QuantitativeDataDto
){
491 QuantitativeData data
= QuantitativeData
.NewInstance(feature
);
492 if (((QuantitativeDataDto
) descElement
).getMeasurementUnit() != null){
493 MeasurementUnit unit
= DefinedTermBase
.getTermByClassAndUUID(MeasurementUnit
.class, ((QuantitativeDataDto
) descElement
).getMeasurementUnit().getUuid());
496 Set
<StatisticalMeasurementValue
> statisticalValues
= new HashSet
<>();
497 Set
<StatisticalMeasurementValueDto
> valueDtos
= ((QuantitativeDataDto
)descElement
).getValues();
498 data
.getStatisticalValues().clear();
499 for (StatisticalMeasurementValueDto dataDto
: valueDtos
){
500 //create new statedata
501 StatisticalMeasure sm
= DefinedTermBase
.getTermByClassAndUUID(StatisticalMeasure
.class, dataDto
.getType().getUuid());
502 StatisticalMeasurementValue newStatisticalMeasurement
= StatisticalMeasurementValue
.NewInstance(sm
, dataDto
.getValue());
503 statisticalValues
.add(newStatisticalMeasurement
);
504 data
.addStatisticalValue(newStatisticalMeasurement
);
507 // data.getStatisticalValues().addAll(statisticalValues);
508 data
= StructuredDescriptionAggregation
.handleMissingMinOrMax(data
,
509 MissingMinimumMode
.MinToZero
, MissingMaximumMode
.MaxToMin
);
510 desc
.addElement(data
);
511 data
.setNoDataStatus(((QuantitativeDataDto
)descElement
).getNoDataStatus());
516 DescriptionElementBase elementBase
= equalUuidsElements
.get(0);
517 if (elementBase
.isInstanceOf(CategoricalData
.class)){
518 CategoricalData data
= HibernateProxyHelper
.deproxy(elementBase
, CategoricalData
.class);
519 List
<StateData
> states
= new ArrayList
<>(data
.getStateData());
520 List
<StateDataDto
> stateDtos
= ((CategoricalDataDto
)descElement
).getStates();
522 data
.getStateData().clear();
523 if (stateDtos
.isEmpty() && ((CategoricalDataDto
)descElement
).getNoDataStatus() == null){
524 desc
.removeElement(data
);
526 for (StateDataDto dataDto
: stateDtos
){
527 if (dataDto
== null) {
530 DefinedTermBase
<?
> newState
= DefinedTermBase
.getTermByUUID(dataDto
.getState().getUuid(), DefinedTermBase
.class);
531 StateData newStateData
= StateData
.NewInstance(newState
);
532 data
.addStateData(newStateData
);
533 if (dataDto
.getModifiers()!= null && !dataDto
.getModifiers().isEmpty()) {
534 DefinedTerm modifier
= DefinedTermBase
.getTermByUUID(dataDto
.getModifiers().iterator().next().getUuid(), DefinedTerm
.class);
535 newStateData
.addModifier(modifier
);
539 data
.setNoDataStatus(((CategoricalDataDto
)descElement
).getNoDataStatus());
541 }else if (elementBase
.isInstanceOf(QuantitativeData
.class)){
542 QuantitativeData data
= HibernateProxyHelper
.deproxy(elementBase
, QuantitativeData
.class);
544 Set
<StatisticalMeasurementValue
> statisticalValues
= new HashSet
<>();
545 if (((QuantitativeDataDto
) descElement
).getMeasurementUnit() != null){
546 MeasurementUnit unit
= DefinedTermBase
.getTermByClassAndUUID(MeasurementUnit
.class, ((QuantitativeDataDto
) descElement
).getMeasurementUnit().getUuid());
547 if (data
.getUnit() == null || (data
.getUnit() != null && !data
.getUnit().equals(unit
))){
551 Set
<StatisticalMeasurementValueDto
> valueDtos
= ((QuantitativeDataDto
)descElement
).getValues();
552 data
.getStatisticalValues().clear();
553 if (valueDtos
.isEmpty() && ((QuantitativeDataDto
)descElement
).getNoDataStatus() == null){
554 desc
.removeElement(data
);
556 for (StatisticalMeasurementValueDto dataDto
: valueDtos
){
557 //create new statedata
558 StatisticalMeasure statMeasure
= DefinedTermBase
.getTermByClassAndUUID(StatisticalMeasure
.class, dataDto
.getType().getUuid());
560 StatisticalMeasurementValue newStatisticalMeasurement
= StatisticalMeasurementValue
.NewInstance(statMeasure
, dataDto
.getValue());
561 statisticalValues
.add(newStatisticalMeasurement
);
562 data
.addStatisticalValue(newStatisticalMeasurement
);
565 // data.getStatisticalValues().addAll(statisticalValues);
566 data
= StructuredDescriptionAggregation
.handleMissingMinOrMax(data
,
567 MissingMinimumMode
.MinToZero
, MissingMaximumMode
.MaxToMin
);
568 data
.setNoDataStatus(((QuantitativeDataDto
)descElement
).getNoDataStatus());
573 //remove deleted elements
577 descriptionSpecimenMap
.get(describedObjectUuid
).add(desc
);
582 if (description
!= null){
583 mergeResult
= dao
.merge(description
, true);
584 result
.addUpdatedObject( mergeResult
.getMergedEntity());
587 // if (description instanceof SpecimenDescription){
588 // result.addUpdatedObject(mergeResult.getMergedEntity().getDescribedSpecimenOrObservation());
589 // }else if (description instanceof TaxonDescription){
590 // result.addUpdatedObject(((TaxonDescription)mergeResult.getMergedEntity()).getTaxon());
591 // }else if (description instanceof TaxonNameDescription){
592 // result.addUpdatedObject(((TaxonNameDescription)mergeResult.getMergedEntity()).getTaxonName());
604 @Transactional(readOnly
= false)
605 public DeleteResult
deleteDescription(DescriptionBase
<?
> description
) {
607 DeleteResult deleteResult
= new DeleteResult();
608 if (description
== null){
611 //avoid lazy init exception
612 description
= load(description
.getId(), Arrays
.asList("descriptiveDataSets"));
614 deleteResult
= isDeletable(description
.getUuid());
615 if (deleteResult
.getRelatedObjects() != null && deleteResult
.getRelatedObjects().size() == 1){
616 Iterator
<CdmBase
> relObjects
= deleteResult
.getRelatedObjects().iterator();
617 CdmBase next
= relObjects
.next();
618 if (next
instanceof CdmLinkSource
){
619 CdmLinkSource source
= (CdmLinkSource
)next
;
620 ICdmTarget target
= source
.getTarget();
625 if (deleteResult
.isOk() ){
626 CdmBase
.deproxy(description
);
627 if (description
instanceof TaxonDescription
){
628 TaxonDescription taxDescription
= (TaxonDescription
)description
;
629 Taxon tax
= taxDescription
.getTaxon();
631 tax
.removeDescription(taxDescription
, true);
632 deleteResult
.addUpdatedObject(tax
);
635 else if (description
instanceof SpecimenDescription
){
636 SpecimenDescription specimenDescription
= (SpecimenDescription
)description
;
637 SpecimenOrObservationBase
<?
> specimen
= specimenDescription
.getDescribedSpecimenOrObservation();
638 if (specimen
!= null){
639 specimen
.removeDescription(specimenDescription
);
640 deleteResult
.addUpdatedObject(specimen
);
644 for (DescriptiveDataSet dataset
: description
.getDescriptiveDataSets()) {
645 dataset
.removeDescription(description
);
648 dao
.delete(description
);
649 deleteResult
.addDeletedObject(description
);
650 deleteResult
.setCdmEntity(description
);
652 logger
.info(deleteResult
.getExceptions().toString());
659 @Transactional(readOnly
= false)
660 public DeleteResult
deleteDescription(UUID descriptionUuid
) {
661 return deleteDescription(dao
.load(descriptionUuid
));
667 public DeleteResult
isDeletable(UUID descriptionUuid
){
668 DeleteResult result
= new DeleteResult();
669 DescriptionBase
<?
> description
= this.load(descriptionUuid
);
670 Set
<CdmBase
> references
= commonService
.getReferencingObjectsForDeletion(description
);
672 if (references
== null || references
.isEmpty()){
675 for (CdmBase ref
: references
){
676 if (description
instanceof TaxonDescription
&& ref
instanceof Taxon
&& ref
.equals(((TaxonDescription
)description
).getTaxon())){
678 } else if (description
instanceof TaxonNameDescription
&& ref
instanceof TaxonName
&& ref
.equals(((TaxonNameDescription
)description
).getTaxonName())){
680 } else if (description
instanceof SpecimenDescription
&& ref
instanceof SpecimenOrObservationBase
&& ref
.equals(((SpecimenDescription
)description
).getDescribedSpecimenOrObservation())){
682 } else if (ref
instanceof DescriptionElementBase
){
684 } else if (ref
instanceof CdmLinkSource
&& ((CdmLinkSource
)ref
).hasNoTarget()) {
685 continue; //maybe only workaround #9801
687 String message
= "The description can't be completely deleted because it is referenced by " + ref
.getUserFriendlyTypeName() ;
689 result
.addException(new ReferencedObjectUndeletableException(message
));
690 result
.addRelatedObject(ref
);
699 public <T
extends DescriptionElementBase
> List
<T
> getDescriptionElementsForTaxon(
700 Taxon taxon
, Set
<Feature
> features
,
701 Class
<T
> type
, boolean includeUnpublished
,
702 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
704 return listDescriptionElementsForTaxon(taxon
, features
, type
, includeUnpublished
,
705 pageSize
, pageNumber
, propertyPaths
);
709 public <T
extends DescriptionElementBase
> List
<T
> listDescriptionElementsForTaxon(
710 Taxon taxon
, Set
<Feature
> features
,
711 Class
<T
> type
, boolean includePublished
,
712 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
714 return dao
.getDescriptionElementForTaxon(taxon
.getUuid(), features
, type
, includePublished
,
715 pageSize
, pageNumber
, propertyPaths
);
719 public <T
extends DescriptionElementBase
> Pager
<T
> pageDescriptionElementsForTaxon(
720 Taxon taxon
, Set
<Feature
> features
,
721 Class
<T
> type
, boolean includeUnpublished
,
722 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
724 if (logger
.isDebugEnabled()){logger
.debug(" get count ...");}
725 Long count
= dao
.countDescriptionElementForTaxon(taxon
.getUuid(), features
, type
, includeUnpublished
);
726 List
<T
> descriptionElements
;
727 if(AbstractPagerImpl
.hasResultsInRange(count
, pageNumber
, pageSize
)){ // no point checking again
728 if (logger
.isDebugEnabled()){logger
.debug(" get list ...");}
729 descriptionElements
= listDescriptionElementsForTaxon(taxon
, features
, type
, includeUnpublished
,
730 pageSize
, pageNumber
, propertyPaths
);
732 descriptionElements
= new ArrayList
<>(0);
734 if (logger
.isDebugEnabled()){logger
.debug(" service - DONE ...");}
735 return new DefaultPagerImpl
<>(pageNumber
, count
, pageSize
, descriptionElements
);
739 public String
generateNaturalLanguageDescription(TermTree featureTree
,
740 TaxonDescription description
, List
<Language
> preferredLanguages
, String separator
) {
742 Language lang
= preferredLanguages
.size() > 0 ? preferredLanguages
.get(0) : Language
.DEFAULT();
744 description
= (TaxonDescription
)load(description
.getUuid());
745 featureTree
= featureTreeDao
.load(featureTree
.getUuid());
747 StringBuilder naturalLanguageDescription
= new StringBuilder();
749 MarkerType useMarkerType
= (MarkerType
) definedTermDao
.load(UUID
.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
750 boolean isUseDescription
= false;
751 if(!description
.getMarkers().isEmpty()) {
752 for (Marker marker
: description
.getMarkers()) {
753 MarkerType markerType
= marker
.getMarkerType();
754 if (markerType
.equals(useMarkerType
)) {
755 isUseDescription
= true;
761 if(description
.hasStructuredData() && !isUseDescription
){
764 String lastCategory
= null;
765 String categorySeparator
= ". ";
767 List
<TextData
> textDataList
;
768 TextData naturalLanguageDescriptionText
= null;
770 boolean useMicroFormatQuantitativeDescriptionBuilder
= false;
772 if(useMicroFormatQuantitativeDescriptionBuilder
){
774 MicroFormatQuantitativeDescriptionBuilder micro
= new MicroFormatQuantitativeDescriptionBuilder();
775 naturalLanguageGenerator
.setQuantitativeDescriptionBuilder(micro
);
776 naturalLanguageDescriptionText
= naturalLanguageGenerator
.generateSingleTextData(featureTree
, (description
), lang
);
780 naturalLanguageDescriptionText
= naturalLanguageGenerator
.generateSingleTextData(
786 return naturalLanguageDescriptionText
.getText(lang
);
789 // boolean doItBetter = false;
791 // for (TextData textData : textDataList.toArray(new TextData[textDataList.size()])){
792 // if(textData.getMultilanguageText().size() > 0){
794 // if (!textData.getFeature().equals(Feature.UNKNOWN())) {
795 // String featureLabel = textData.getFeature().getLabel(lang);
800 // * The code lines below are desinged to handle
801 // * a special case where as the feature label contains
802 // * hierarchical information on the features. This code
803 // * exist only as a base for discussion, and is not
804 // * intendet to be used in production.
806 // featureLabel = StringUtils.remove(featureLabel, '>');
808 // String[] labelTokens = StringUtils.split(featureLabel, '<');
809 // if(labelTokens[0].equals(lastCategory) && labelTokens.length > 1){
810 // if(naturalLanguageDescription.length() > 0){
811 // naturalLanguageDescription.append(separator);
813 // naturalLanguageDescription.append(labelTokens[1]);
815 // if(naturalLanguageDescription.length() > 0){
816 // naturalLanguageDescription.append(categorySeparator);
818 // naturalLanguageDescription.append(StringUtils.join(labelTokens));
820 // lastCategory = labelTokens[0];
821 // // end of demo code
823 // if(naturalLanguageDescription.length() > 0){
824 // naturalLanguageDescription.append(separator);
826 // naturalLanguageDescription.append(textData.getFeature().getLabel(lang));
829 // if(naturalLanguageDescription.length() > 0){
830 // naturalLanguageDescription.append(separator);
833 // String text = textData.getMultilanguageText().values().iterator().next().getText();
834 // naturalLanguageDescription.append(text);
840 else if (isUseDescription
) {
841 //AT: Left Blank in case we need to generate a Natural language text string.
843 return naturalLanguageDescription
.toString();
848 public boolean hasStructuredData(DescriptionBase
<?
> description
) {
849 return load(description
.getUuid()).hasStructuredData();
854 // @Transactional(readOnly = false)
855 public UpdateResult
moveDescriptionElementsToDescription(
856 Collection
<DescriptionElementBase
> descriptionElements
,
857 DescriptionBase targetDescription
,
859 boolean setNameInSource
) {
861 UpdateResult result
= new UpdateResult();
862 if (descriptionElements
.isEmpty() || descriptionElements
.iterator().next() == null){
868 if (! isCopy
&& descriptionElements
== descriptionElements
.iterator().next().getInDescription().getElements()){
869 //if the descriptionElements collection is the elements set of a description, put it in a separate set before to avoid concurrent modification exceptions
870 descriptionElements
= new HashSet
<DescriptionElementBase
>(descriptionElements
);
871 // descriptionElementsTmp.addAll(descriptionElements);
872 // descriptionElements = descriptionElementsTmp;
874 for (DescriptionElementBase element
: descriptionElements
){
875 DescriptionBase
<?
> description
= element
.getInDescription();
876 description
= HibernateProxyHelper
.deproxy(dao
.load(description
.getUuid()));
878 TaxonName name
= null;
879 if (description
instanceof TaxonDescription
){
880 TaxonDescription taxonDescription
= HibernateProxyHelper
.deproxy(description
, TaxonDescription
.class);
881 if (taxonDescription
.getTaxon() != null){
882 taxon
= (Taxon
) taxonDao
.load(taxonDescription
.getTaxon().getUuid());
883 name
= taxon
.getName();
888 DescriptionElementBase newElement
= element
.clone();
889 if (setNameInSource
) {
890 for (DescriptionElementSource source
: newElement
.getSources()){
891 if (source
.getNameUsedInSource() == null){
892 source
.setNameUsedInSource(name
);
897 targetDescription
.addElement(newElement
);
899 description
.removeElement(element
);
900 dao
.saveOrUpdate(description
);
901 result
.addUpdatedObject(description
);
902 // if (description.getElements().isEmpty()){
903 // if (description instanceof TaxonDescription){
904 // TaxonDescription taxDescription = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
905 // if (taxDescription.getTaxon() != null){
906 // taxDescription.getTaxon().removeDescription((TaxonDescription)description);
909 // dao.delete(description);
912 // dao.saveOrUpdate(description);
913 // result.addUpdatedObject(description);
919 dao
.saveOrUpdate(targetDescription
);
920 result
.addUpdatedObject(targetDescription
);
921 if (targetDescription
instanceof TaxonDescription
){
922 result
.addUpdatedObject(((TaxonDescription
)targetDescription
).getTaxon());
928 // @Transactional(readOnly = false)
929 // public UpdateResult moveDescriptionElementsToDescription(
930 // Set<UUID> descriptionElementUUIDs,
931 // UUID targetDescriptionUuid,
932 // boolean isCopy, boolean setNameInSource) {
933 // Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
934 // for(UUID deUuid : descriptionElementUUIDs) {
935 // DescriptionElementBase element = descriptionElementDao.load(deUuid);
936 // if (element != null){
937 // descriptionElements.add(element);
940 // DescriptionBase targetDescription = dao.load(targetDescriptionUuid);
942 // return moveDescriptionElementsToDescription(descriptionElements, targetDescription, isCopy, setNameInSource);
946 @Transactional(readOnly
= false)
947 public UpdateResult
moveDescriptionElementsToDescription(
948 Set
<UUID
> descriptionElementUUIDs
,
949 DescriptionBase targetDescription
,
950 boolean isCopy
, boolean setNameInSource
) {
951 Set
<DescriptionElementBase
> descriptionElements
= new HashSet
<DescriptionElementBase
>();
952 for(UUID deUuid
: descriptionElementUUIDs
) {
953 DescriptionElementBase element
= descriptionElementDao
.load(deUuid
);
954 if (element
!= null){
955 descriptionElements
.add(element
);
958 DescriptionBase newTargetDescription
;
959 if (targetDescription
.isPersisted()){
960 newTargetDescription
= dao
.load(targetDescription
.getUuid());
962 if (targetDescription
instanceof TaxonDescription
){
963 Taxon taxon
= (Taxon
)taxonDao
.load(((TaxonDescription
)targetDescription
).getTaxon().getUuid());
965 newTargetDescription
= TaxonDescription
.NewInstance(taxon
, targetDescription
.isImageGallery());
967 }else if (targetDescription
instanceof TaxonNameDescription
){
968 TaxonName name
= nameDao
.load(((TaxonNameDescription
)targetDescription
).getTaxonName().getUuid());
969 newTargetDescription
= TaxonNameDescription
.NewInstance(name
);
971 SpecimenOrObservationBase specimen
= occurrenceDao
.load(((SpecimenDescription
)targetDescription
).getDescribedSpecimenOrObservation().getUuid());
972 newTargetDescription
= SpecimenDescription
.NewInstance(specimen
);
975 newTargetDescription
.addSources(targetDescription
.getSources());
976 newTargetDescription
.setTitleCache(targetDescription
.getTitleCache(), targetDescription
.isProtectedTitleCache());
979 return moveDescriptionElementsToDescription(descriptionElements
, newTargetDescription
, isCopy
, setNameInSource
);
984 @Transactional(readOnly
= false)
985 public UpdateResult
moveDescriptionElementsToDescription(
986 Set
<UUID
> descriptionElementUUIDs
,
987 UUID targetTaxonUuid
,
989 boolean isCopy
, boolean setNameInSource
, boolean useDefaultDescription
, boolean createNewCurrentDeterminations
) {
990 Taxon targetTaxon
= CdmBase
.deproxy(taxonDao
.load(targetTaxonUuid
), Taxon
.class);
991 TaxonDescription targetDescription
= null;
992 if (useDefaultDescription
&& targetTaxon
.hasDefaultDescription()) {
993 for (TaxonDescription des
:targetTaxon
.getDescriptions()) {
994 if (des
.isDefault()) {
995 targetDescription
= des
;
1000 if (targetDescription
== null) {
1001 targetDescription
= TaxonDescription
.NewInstance(targetTaxon
);
1003 if (!targetTaxon
.hasDefaultDescription()) {
1004 targetDescription
.setDefault(true);
1006 targetDescription
.setTitleCache(moveMessage
, true);
1007 Annotation annotation
= Annotation
.NewInstance(moveMessage
, Language
.getDefaultLanguage());
1008 annotation
.setAnnotationType(AnnotationType
.TECHNICAL());
1009 targetDescription
.addAnnotation(annotation
);
1011 targetDescription
= dao
.save(targetDescription
);
1012 Set
<DescriptionElementBase
> descriptionElements
= new HashSet
<DescriptionElementBase
>();
1013 for(UUID deUuid
: descriptionElementUUIDs
) {
1014 DescriptionElementBase descEl
= descriptionElementDao
.load(deUuid
);
1015 descriptionElements
.add(descEl
);
1016 if (createNewCurrentDeterminations
&& descEl
instanceof IndividualsAssociation
&& ((IndividualsAssociation
)descEl
).getAssociatedSpecimenOrObservation()!= null){
1017 SpecimenOrObservationBase specimen
= HibernateProxyHelper
.deproxy(((IndividualsAssociation
)descEl
).getAssociatedSpecimenOrObservation());
1018 DeterminationEvent event
= specimen
.getDeterminationsForTaxonOrName(targetTaxon
, targetTaxon
.getName());
1019 if (event
!= null) {
1020 specimen
.setPreferredDetermination(event
);
1022 DeterminationEvent detEvent
= DeterminationEvent
.NewInstance(targetTaxon
, specimen
);
1023 specimen
.setPreferredDetermination(detEvent
);
1028 return moveDescriptionElementsToDescription(descriptionElements
, targetDescription
, isCopy
, setNameInSource
);
1032 public Pager
<TermDto
> pageNamedAreasInUse(boolean includeAllParents
, Integer pageSize
,
1034 List
<TermDto
> results
= dao
.listNamedAreasInUse(includeAllParents
, null, null);
1035 List
<TermDto
> subList
= PagerUtils
.pageList(results
, pageIndex
, pageSize
);
1036 return new DefaultPagerImpl
<>(pageIndex
, Long
.valueOf(results
.size()), pageSize
, subList
);
1041 @Transactional(readOnly
= false)
1042 public UpdateResult
moveTaxonDescriptions(Taxon sourceTaxon
, Taxon targetTaxon
, boolean setNameInSource
) {
1043 List
<TaxonDescription
> descriptions
= new ArrayList
<>(sourceTaxon
.getDescriptions());
1044 UpdateResult result
= new UpdateResult();
1045 result
.addUpdatedObject(sourceTaxon
);
1046 result
.addUpdatedObject(targetTaxon
);
1047 for(TaxonDescription description
: descriptions
){
1048 targetTaxon
.addDescription(prepareDescriptionForMove(description
, sourceTaxon
, setNameInSource
));
1053 private TaxonDescription
prepareDescriptionForMove(TaxonDescription description
, Taxon sourceTaxon
, boolean setNameInSource
){
1054 String moveMessage
= String
.format("Description moved from %s", sourceTaxon
);
1055 if(description
.isProtectedTitleCache()){
1056 String separator
= "";
1057 if(!StringUtils
.isBlank(description
.getTitleCache())){
1060 description
.setTitleCache(description
.getTitleCache() + separator
+ moveMessage
, true);
1063 description
.setTitleCache(moveMessage
, true);
1065 Annotation annotation
= Annotation
.NewInstance(moveMessage
, Language
.getDefaultLanguage());
1066 annotation
.setAnnotationType(AnnotationType
.TECHNICAL());
1067 description
.addAnnotation(annotation
);
1068 if(setNameInSource
){
1069 for (DescriptionElementBase element
: description
.getElements()){
1070 for (DescriptionElementSource source
: element
.getSources()){
1071 if (source
.getNameUsedInSource() == null){
1072 source
.setNameUsedInSource(sourceTaxon
.getName());
1077 description
.setDefault(false);
1082 @Transactional(readOnly
= false)
1083 public UpdateResult
moveTaxonDescriptions(UUID sourceTaxonUuid
, UUID targetTaxonUuid
, boolean setNameInSource
) {
1084 Taxon sourceTaxon
= HibernateProxyHelper
.deproxy(taxonDao
.load(sourceTaxonUuid
), Taxon
.class);
1085 Taxon targetTaxon
= HibernateProxyHelper
.deproxy(taxonDao
.load(targetTaxonUuid
), Taxon
.class);
1086 return moveTaxonDescriptions(sourceTaxon
, targetTaxon
, setNameInSource
);
1091 @Transactional(readOnly
= false)
1092 public UpdateResult
moveTaxonDescription(UUID descriptionUuid
, UUID targetTaxonUuid
, boolean setNameInSource
){
1093 TaxonDescription description
= HibernateProxyHelper
.deproxy(dao
.load(descriptionUuid
), TaxonDescription
.class);
1094 Taxon targetTaxon
= HibernateProxyHelper
.deproxy(taxonDao
.load(targetTaxonUuid
), Taxon
.class);
1095 Taxon sourceTaxon
= description
.getTaxon();
1096 UpdateResult result
= new UpdateResult();
1097 result
.addUpdatedObject(sourceTaxon
);
1098 result
.addUpdatedObject(targetTaxon
);
1100 targetTaxon
.addDescription(prepareDescriptionForMove(description
, sourceTaxon
, setNameInSource
));
1106 public DescriptionBaseDto
loadDto(UUID descriptionUuid
) {
1107 return dao
.loadDto(descriptionUuid
);
1112 public List
<DescriptionBaseDto
> loadDtos(Set
<UUID
> descriptionUuids
) {
1114 return dao
.loadDtos(descriptionUuids
);
1117 // FIXME Query should not be used in service layer
1119 public List
<DescriptionBaseDto
> loadDtosForTaxon(UUID taxonUuid
) {
1120 String sqlSelect
= DescriptionBaseDto
.getDescriptionBaseDtoForTaxonSelect();
1121 Query
<Object
[]> query
= getSession().createQuery(sqlSelect
, Object
[].class);
1122 query
.setParameter("uuid", taxonUuid
);
1124 List
<Object
[]> result
= query
.list();
1125 List
<DescriptionBaseDto
> list
= DescriptionBaseDto
.descriptionBaseDtoListFrom(result
);
1131 public TaxonNodeDto
findTaxonNodeDtoForIndividualAssociation(UUID specimenUuid
, UUID classificationUuid
) {
1132 //get specimen used in description
1133 //get individial associations with this specimen
1134 //get taxon node for the classification
1135 List
<SortableTaxonNodeQueryResult
> result
= dao
.getNodeOfIndividualAssociationForSpecimen(specimenUuid
, classificationUuid
);
1137 if (!result
.isEmpty()){
1138 List
<TaxonNodeDto
> dtos
= taxonNodeDao
.createNodeDtos(result
);
1139 if (dtos
.size() == 1){
1142 logger
.debug("There is more than one taxon associated to the specimen with uuid: " + specimenUuid
+ " return the first in the list");
1150 @Transactional(readOnly
= false)
1151 public UpdateResult
moveDescriptionElementsToDescription(
1152 Set
<UUID
> descriptionElementUUIDs
,
1153 UUID targetDescriptionUuid
,
1154 boolean isCopy
, boolean setNameInSource
) {
1155 Set
<DescriptionElementBase
> descriptionElements
= new HashSet
<DescriptionElementBase
>();
1156 for(UUID deUuid
: descriptionElementUUIDs
) {
1157 DescriptionElementBase element
= descriptionElementDao
.load(deUuid
);
1158 if (element
!= null){
1159 descriptionElements
.add(element
);
1162 DescriptionBase
<?
> targetDescription
= dao
.load(targetDescriptionUuid
);
1164 return moveDescriptionElementsToDescription(descriptionElements
, targetDescription
, isCopy
, setNameInSource
);