1 package eu
.etaxonomy
.cdm
.api
.service
;
3 import java
.io
.Serializable
;
4 import java
.util
.ArrayList
;
5 import java
.util
.Arrays
;
6 import java
.util
.Collection
;
7 import java
.util
.HashMap
;
8 import java
.util
.HashSet
;
11 import java
.util
.Optional
;
13 import java
.util
.UUID
;
14 import java
.util
.stream
.Collectors
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
18 import org
.springframework
.stereotype
.Service
;
19 import org
.springframework
.transaction
.annotation
.Transactional
;
21 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RowWrapperDTO
;
22 import eu
.etaxonomy
.cdm
.api
.service
.dto
.SpecimenRowWrapperDTO
;
23 import eu
.etaxonomy
.cdm
.api
.service
.dto
.TaxonRowWrapperDTO
;
24 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
25 import eu
.etaxonomy
.cdm
.common
.monitor
.IRemotingProgressMonitor
;
26 import eu
.etaxonomy
.cdm
.common
.monitor
.RemotingProgressMonitorThread
;
27 import eu
.etaxonomy
.cdm
.filter
.TaxonNodeFilter
;
28 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
29 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
30 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
31 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
32 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
33 import eu
.etaxonomy
.cdm
.model
.common
.OriginalSourceType
;
34 import eu
.etaxonomy
.cdm
.model
.description
.CategoricalData
;
35 import eu
.etaxonomy
.cdm
.model
.description
.Character
;
36 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
37 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
38 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveDataSet
;
39 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveSystemRole
;
40 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
41 import eu
.etaxonomy
.cdm
.model
.description
.QuantitativeData
;
42 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
43 import eu
.etaxonomy
.cdm
.model
.description
.StateData
;
44 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasure
;
45 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasurementValue
;
46 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
47 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
48 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
49 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
50 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
51 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
56 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptiveDataSetDao
;
57 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonNodeDao
;
58 import eu
.etaxonomy
.cdm
.persistence
.dto
.SpecimenNodeWrapper
;
59 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
60 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
63 @Transactional(readOnly
= false)
64 public class DescriptiveDataSetService
65 extends IdentifiableServiceBase
<DescriptiveDataSet
, IDescriptiveDataSetDao
>
66 implements IDescriptiveDataSetService
{
68 private static Logger logger
= Logger
.getLogger(DescriptiveDataSetService
.class);
71 private IOccurrenceService occurrenceService
;
74 private ITaxonService taxonService
;
77 private IDescriptionService descriptionService
;
80 private ITaxonNodeService taxonNodeService
;
83 private ITaxonNodeDao taxonNodeDao
;
86 private IProgressMonitorService progressMonitorService
;
90 protected void setDao(IDescriptiveDataSetDao dao
) {
95 public Map
<DescriptionBase
, Set
<DescriptionElementBase
>> getDescriptionElements(DescriptiveDataSet descriptiveDataSet
, Set
<Feature
> features
, Integer pageSize
, Integer pageNumber
,
96 List
<String
> propertyPaths
) {
97 return dao
.getDescriptionElements(descriptiveDataSet
, features
, pageSize
, pageNumber
, propertyPaths
);
101 public <T
extends DescriptionElementBase
> Map
<UuidAndTitleCache
, Map
<UUID
, Set
<T
>>> getTaxonFeatureDescriptionElementMap(
102 Class
<T
> clazz
, UUID descriptiveDataSetUuid
, DescriptiveSystemRole role
) {
103 return dao
.getTaxonFeatureDescriptionElementMap(clazz
, descriptiveDataSetUuid
, role
);
107 public List
<UuidAndTitleCache
<DescriptiveDataSet
>> getDescriptiveDataSetUuidAndTitleCache(Integer limitOfInitialElements
, String pattern
) {
108 return dao
.getDescriptiveDataSetUuidAndTitleCache( limitOfInitialElements
, pattern
);
114 public UUID
monitGetRowWrapper(DescriptiveDataSet descriptiveDataSet
) {
115 RemotingProgressMonitorThread monitorThread
= new RemotingProgressMonitorThread() {
117 public Serializable
doRun(IRemotingProgressMonitor monitor
) {
118 return getRowWrapper(descriptiveDataSet
, monitor
);
121 UUID uuid
= progressMonitorService
.registerNewRemotingMonitor(monitorThread
);
122 monitorThread
.setPriority(3);
123 monitorThread
.start();
128 public ArrayList
<RowWrapperDTO
> getRowWrapper(DescriptiveDataSet descriptiveDataSet
, IProgressMonitor monitor
) {
129 monitor
.beginTask("Load row wrapper", descriptiveDataSet
.getDescriptions().size());
130 ArrayList
<RowWrapperDTO
> wrappers
= new ArrayList
<>();
131 Set
<DescriptionBase
> descriptions
= descriptiveDataSet
.getDescriptions();
132 for (DescriptionBase description
: descriptions
) {
133 if(monitor
.isCanceled()){
134 return new ArrayList
<>();
136 RowWrapperDTO rowWrapper
= null;
137 if(HibernateProxyHelper
.isInstanceOf(description
, TaxonDescription
.class)){
138 rowWrapper
= createTaxonRowWrapper(HibernateProxyHelper
.deproxy(description
, TaxonDescription
.class), descriptiveDataSet
);
140 else if (HibernateProxyHelper
.isInstanceOf(description
, SpecimenDescription
.class)){
141 rowWrapper
= createSpecimenRowWrapper(HibernateProxyHelper
.deproxy(description
, SpecimenDescription
.class), descriptiveDataSet
, false);
143 if(rowWrapper
!=null){
144 wrappers
.add(rowWrapper
);
152 public Collection
<SpecimenNodeWrapper
> loadSpecimens(DescriptiveDataSet descriptiveDataSet
){
153 List
<UUID
> filteredNodes
= findFilteredTaxonNodes(descriptiveDataSet
);
154 return occurrenceService
.listUuidAndTitleCacheByAssociatedTaxon(filteredNodes
, null, null);
158 public List
<UUID
> findFilteredTaxonNodes(DescriptiveDataSet descriptiveDataSet
){
159 TaxonNodeFilter filter
= TaxonNodeFilter
.NewRankInstance(descriptiveDataSet
.getMinRank(), descriptiveDataSet
.getMaxRank());
160 descriptiveDataSet
.getGeoFilter().forEach(area
-> filter
.orArea(area
.getUuid()));
161 descriptiveDataSet
.getTaxonSubtreeFilter().forEach(node
-> filter
.orSubtree(node
));
162 filter
.setIncludeUnpublished(true);
164 return taxonNodeService
.uuidList(filter
);
168 public List
<TaxonNode
> loadFilteredTaxonNodes(DescriptiveDataSet descriptiveDataSet
, List
<String
> propertyPaths
){
169 return taxonNodeService
.load(findFilteredTaxonNodes(descriptiveDataSet
), propertyPaths
);
172 private TaxonNode
findTaxonNodeForDescription(TaxonNode taxonNode
, SpecimenOrObservationBase specimen
){
173 Collection
<SpecimenNodeWrapper
> nodeWrapper
= occurrenceService
.listUuidAndTitleCacheByAssociatedTaxon(Arrays
.asList(taxonNode
.getUuid()), null, null);
174 for (SpecimenNodeWrapper specimenNodeWrapper
: nodeWrapper
) {
175 if(specimenNodeWrapper
.getUuidAndTitleCache().getId().equals(specimen
.getId())){
183 public TaxonRowWrapperDTO
createTaxonRowWrapper(TaxonDescription description
,
184 DescriptiveDataSet descriptiveDataSet
) {
185 TaxonNode taxonNode
= null;
186 Classification classification
= null;
187 Optional
<TaxonNode
> first
= descriptiveDataSet
.getTaxonSubtreeFilter().stream()
188 .filter(node
->node
.getClassification()!=null).findFirst();
189 Optional
<Classification
> classificationOptional
= first
.map(node
->node
.getClassification());
190 if(classificationOptional
.isPresent()){
191 classification
= classificationOptional
.get();
192 Taxon taxon
= (Taxon
) taxonService
.load(description
.getTaxon().getId(), Arrays
.asList("taxonNodes", "taxonNodes.classification"));
193 taxonNode
= taxon
.getTaxonNode(classification
);
195 return new TaxonRowWrapperDTO(description
, taxonNode
);
199 public SpecimenRowWrapperDTO
createSpecimenRowWrapper(SpecimenDescription description
, DescriptiveDataSet descriptiveDataSet
,
200 boolean createDefaultTaxonDescription
){
201 SpecimenOrObservationBase specimen
= description
.getDescribedSpecimenOrObservation();
202 TaxonNode taxonNode
= null;
203 FieldUnit fieldUnit
= null;
204 String identifier
= null;
205 NamedArea country
= null;
206 //supplemental information
208 Set
<TaxonNode
> taxonSubtreeFilter
= descriptiveDataSet
.getTaxonSubtreeFilter();
209 for (TaxonNode node
: taxonSubtreeFilter
) {
211 node
= taxonNodeService
.load(node
.getId(), Arrays
.asList("taxon"));
212 taxonNode
= findTaxonNodeForDescription(node
, specimen
);
217 //check for child nodes
218 List
<TaxonNode
> allChildren
= taxonNodeService
.loadChildNodesOfTaxonNode(node
, Arrays
.asList("taxon"), true, true, null);
219 for (TaxonNode child
: allChildren
) {
220 taxonNode
= findTaxonNodeForDescription(child
, specimen
);
230 //taxon node was found
233 Collection
<FieldUnit
> fieldUnits
= occurrenceService
.findFieldUnits(specimen
.getUuid(),
234 Arrays
.asList(new String
[]{
236 "gatheringEvent.country"
238 if(fieldUnits
.size()!=1){
239 logger
.error("More than one or no field unit found for specimen"); //$NON-NLS-1$
243 fieldUnit
= fieldUnits
.iterator().next();
246 if(HibernateProxyHelper
.isInstanceOf(specimen
, DerivedUnit
.class)){
247 identifier
= occurrenceService
.getMostSignificantIdentifier(HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class));
250 if(fieldUnit
!=null && fieldUnit
.getGatheringEvent()!=null){
251 country
= fieldUnit
.getGatheringEvent().getCountry();
253 //get default taxon description
254 TaxonDescription defaultTaxonDescription
= findDefaultTaxonDescription(descriptiveDataSet
.getUuid(),
255 taxonNode
.getUuid(), createDefaultTaxonDescription
);
256 TaxonRowWrapperDTO taxonRowWrapper
= defaultTaxonDescription
!= null
257 ?
createTaxonRowWrapper(defaultTaxonDescription
, descriptiveDataSet
) : null;
258 return new SpecimenRowWrapperDTO(description
, taxonNode
, fieldUnit
, identifier
, country
, taxonRowWrapper
);
262 @Transactional(readOnly
= false)
263 public void updateTitleCache(Class
<?
extends DescriptiveDataSet
> clazz
, Integer stepSize
,
264 IIdentifiableEntityCacheStrategy
<DescriptiveDataSet
> cacheStrategy
, IProgressMonitor monitor
) {
266 clazz
= DescriptiveDataSet
.class;
268 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
272 public TaxonDescription
findDefaultTaxonDescription(UUID descriptiveDataSetUuid
, UUID taxonNodeUuid
, boolean create
){
273 DescriptiveDataSet dataSet
= load(descriptiveDataSetUuid
);
274 TaxonNode taxonNode
= taxonNodeService
.load(taxonNodeUuid
, Arrays
.asList("taxon", "taxon.descriptions", "taxon.descriptions.markers"));
275 Set
<DescriptionBase
> dataSetDescriptions
= dataSet
.getDescriptions();
276 //filter out COMPUTED descriptions
277 List
<TaxonDescription
> nonComputedDescriptions
= taxonNode
.getTaxon().getDescriptions().stream()
278 .filter(desc
-> desc
.getMarkers().stream()
279 .noneMatch(marker
-> marker
.getMarkerType().equals(MarkerType
.COMPUTED())))
280 .collect(Collectors
.toList());
281 for (TaxonDescription taxonDescription
: nonComputedDescriptions
) {
282 for (DescriptionBase description
: dataSetDescriptions
) {
283 if(description
.getUuid().equals(taxonDescription
.getUuid())){
284 return HibernateProxyHelper
.deproxy(descriptionService
.load(taxonDescription
.getUuid(),
285 Arrays
.asList("taxon", "descriptionElements", "descriptionElements.feature")), TaxonDescription
.class);
292 TaxonRowWrapperDTO taxonRowWrapperDTO
= createTaxonDescription(descriptiveDataSetUuid
, taxonNodeUuid
, MarkerType
.USE(), true);
293 TaxonDescription newTaxonDescription
= taxonRowWrapperDTO
.getDescription();
294 return newTaxonDescription
;
298 @Transactional(readOnly
=false)
299 public UpdateResult
aggregateTaxonDescription(UUID taxonNodeUuid
, UUID descriptiveDataSetUuid
,
300 IRemotingProgressMonitor monitor
){
301 UpdateResult result
= new UpdateResult();
303 TaxonNode node
= taxonNodeService
.load(taxonNodeUuid
);
304 Taxon taxon
= HibernateProxyHelper
.deproxy(taxonService
.load(node
.getTaxon().getUuid()), Taxon
.class);
305 result
.setCdmEntity(taxon
);
307 //get all "computed" descriptions from all sub nodes
308 List
<TaxonNode
> childNodes
= taxonNodeDao
.listChildrenOf(node
, null, null, true, false, null);
309 List
<TaxonDescription
> computedDescriptions
= new ArrayList
<>();
311 childNodes
.stream().map(childNode
-> childNode
.getTaxon())
312 .forEach(childTaxon
-> childTaxon
.getDescriptions().stream()
313 // filter out non-computed descriptions
314 .filter(description
-> description
.getMarkers().stream()
315 .anyMatch(marker
-> marker
.getMarkerType().equals(MarkerType
.COMPUTED())))
316 // add them to the list
317 .forEach(computedDescription
-> computedDescriptions
.add(computedDescription
)));
319 UpdateResult aggregateDescription
= aggregateDescription(taxon
, computedDescriptions
,
320 "[Taxon Descriptions]"+taxon
.getTitleCache(), descriptiveDataSetUuid
);
321 result
.includeResult(aggregateDescription
);
322 result
.setCdmEntity(aggregateDescription
.getCdmEntity());
323 aggregateDescription
.setCdmEntity(null);
328 @Transactional(readOnly
=false)
329 public UpdateResult
aggregateDescription(UUID taxonUuid
, List
<UUID
> descriptionUuids
, String descriptionTitle
330 , UUID descriptiveDataSetUuid
) {
331 UpdateResult result
= new UpdateResult();
333 TaxonBase taxonBase
= taxonService
.load(taxonUuid
);
334 if(!(taxonBase
instanceof Taxon
)){
335 result
.addException(new ClassCastException("The given taxonUUID does not belong to a taxon"));
339 Taxon taxon
= (Taxon
)taxonBase
;
341 List
<DescriptionBase
> descriptions
= descriptionService
.load(descriptionUuids
, null);
343 UpdateResult aggregateDescriptionResult
= aggregateDescription(taxon
, descriptions
, descriptionTitle
, descriptiveDataSetUuid
);
344 result
.setCdmEntity(aggregateDescriptionResult
.getCdmEntity());
345 aggregateDescriptionResult
.setCdmEntity(null);
346 result
.includeResult(aggregateDescriptionResult
);
350 @SuppressWarnings("unchecked")
351 private UpdateResult
aggregateDescription(Taxon taxon
, List
<?
extends DescriptionBase
> descriptions
, String descriptionTitle
352 , UUID descriptiveDataSetUuid
) {
353 UpdateResult result
= new UpdateResult();
354 Map
<Character
, List
<DescriptionElementBase
>> featureToElementMap
= new HashMap
<>();
356 DescriptiveDataSet dataSet
= load(descriptiveDataSetUuid
);
358 result
.addException(new IllegalArgumentException("Could not find data set for uuid "+descriptiveDataSetUuid
));
363 //extract all character description elements
364 descriptions
.forEach(description
->{
365 description
.getElements()
367 //filter out elements that do not have a Characters as Feature
368 .filter(element
->HibernateProxyHelper
.isInstanceOf(((DescriptionElementBase
)element
).getFeature(), Character
.class))
370 DescriptionElementBase descriptionElement
= (DescriptionElementBase
)ele
;
371 List
<DescriptionElementBase
> list
= featureToElementMap
.get(descriptionElement
.getFeature());
373 list
= new ArrayList
<>();
375 list
.add(descriptionElement
);
376 featureToElementMap
.put(HibernateProxyHelper
.deproxy(descriptionElement
.getFeature(), Character
.class), list
);
380 TaxonDescription description
= TaxonDescription
.NewInstance(taxon
);
381 description
.setTitleCache("[Aggregation] "+descriptionTitle
, true);
382 description
.addMarker(Marker
.NewInstance(MarkerType
.COMPUTED(), true));
383 IdentifiableSource source
= IdentifiableSource
.NewInstance(OriginalSourceType
.Aggregation
);
384 description
.addSource(source
);
385 description
.addDescriptiveDataSet(dataSet
);
387 featureToElementMap
.forEach((feature
, elements
)->{
388 //aggregate categorical data
389 if(feature
.isSupportsCategoricalData()){
390 CategoricalData aggregate
= CategoricalData
.NewInstance(feature
);
392 .filter(element
->element
instanceof CategoricalData
)
393 .forEach(categoricalData
->((CategoricalData
)categoricalData
).getStateData()
394 .forEach(stateData
->aggregate
.addStateData((StateData
) stateData
.clone())));
395 description
.addElement(aggregate
);
397 //aggregate quantitative data
398 else if(feature
.isSupportsQuantitativeData()){
399 QuantitativeData aggregate
= QuantitativeData
.NewInstance(feature
);
401 .filter(element
->element
instanceof QuantitativeData
)
402 .forEach(categoricalData
->((QuantitativeData
)categoricalData
).getStatisticalValues()
403 .forEach(statisticalValue
->aggregate
.addStatisticalValue((StatisticalMeasurementValue
) statisticalValue
.clone())));
404 description
.addElement(aggregate
);
407 result
.addUpdatedObject(taxon
);
408 result
.setCdmEntity(description
);
413 public TaxonRowWrapperDTO
createTaxonDescription(UUID dataSetUuid
, UUID taxonNodeUuid
, MarkerType markerType
, boolean markerFlag
){
414 DescriptiveDataSet dataSet
= load(dataSetUuid
);
415 TaxonNode taxonNode
= taxonNodeService
.load(taxonNodeUuid
, Arrays
.asList("taxon"));
416 TaxonDescription newTaxonDescription
= TaxonDescription
.NewInstance(taxonNode
.getTaxon());
419 if(markerType
.equals(MarkerType
.USE())){
422 else if(markerType
.equals(MarkerType
.IN_BIBLIOGRAPHY())){
423 tag
= "[Literature]";
426 newTaxonDescription
.setTitleCache(tag
+" "+dataSet
.getLabel()+": "+newTaxonDescription
.generateTitle(), true); //$NON-NLS-2$
427 if(markerType
!=null){
428 newTaxonDescription
.addMarker(Marker
.NewInstance(markerType
, markerFlag
));
430 dataSet
.getDescriptiveSystem().getDistinctFeatures().forEach(wsFeature
->{
431 if(wsFeature
.isSupportsCategoricalData()){
432 newTaxonDescription
.addElement(CategoricalData
.NewInstance(wsFeature
));
434 else if(wsFeature
.isSupportsQuantitativeData()){
435 newTaxonDescription
.addElement(QuantitativeData
.NewInstance(wsFeature
));
438 dataSet
.addDescription(newTaxonDescription
);
440 return createTaxonRowWrapper(newTaxonDescription
, dataSet
);
444 public SpecimenDescription
findSpecimenDescription(UUID descriptiveDataSetUuid
, UUID specimenUuid
){
445 DescriptiveDataSet dataSet
= load(descriptiveDataSetUuid
);
446 SpecimenOrObservationBase specimen
= occurrenceService
.load(specimenUuid
);
448 Set
<Feature
> datasetFeatures
= dataSet
.getDescriptiveSystem().getDistinctFeatures();
449 List
<DescriptionElementBase
> matchingDescriptionElements
= new ArrayList
<>();
451 for (SpecimenDescription specimenDescription
: (Set
<SpecimenDescription
>) specimen
.getDescriptions()) {
452 specimenDescription
= (SpecimenDescription
) descriptionService
.load(specimenDescription
.getUuid());
454 //check if description is already added to data set
455 if(dataSet
.getDescriptions().contains(specimenDescription
)){
456 return specimenDescription
;
459 //gather specimen description features and check for match with dataset features
460 Set
<Feature
> specimenDescriptionFeatures
= new HashSet
<>();
461 for (DescriptionElementBase specimenDescriptionElement
: specimenDescription
.getElements()) {
462 Feature feature
= specimenDescriptionElement
.getFeature();
463 specimenDescriptionFeatures
.add(feature
);
464 if(datasetFeatures
.contains(feature
)){
465 matchingDescriptionElements
.add(specimenDescriptionElement
);
469 //Create new specimen description if description has not already been added to the dataset
470 SpecimenDescription newDesription
= SpecimenDescription
.NewInstance(specimen
);
471 newDesription
.setTitleCache("Dataset "+dataSet
.getLabel()+": "+newDesription
.generateTitle(), true); //$NON-NLS-2$
473 //check for equals description element (same feature and same values)
474 Map
<Feature
, List
<DescriptionElementBase
>> featureToElementMap
= new HashMap
<>();
475 for(DescriptionElementBase element
:matchingDescriptionElements
){
476 List
<DescriptionElementBase
> list
= featureToElementMap
.get(element
.getFeature());
478 list
= new ArrayList
<>();
481 featureToElementMap
.put(element
.getFeature(), list
);
483 Set
<DescriptionElementBase
> descriptionElementsToClone
= new HashSet
<>();
484 for(Feature feature
:featureToElementMap
.keySet()){
485 List
<DescriptionElementBase
> elements
= featureToElementMap
.get(feature
);
486 //no duplicate description elements found for this feature
487 if(elements
.size()==1){
488 descriptionElementsToClone
.add(elements
.get(0));
490 //duplicates found -> check if all are equal
492 DescriptionElementBase match
= null;
493 for (DescriptionElementBase descriptionElementBase
: elements
) {
495 match
= descriptionElementBase
;
497 else if(!new DescriptionElementCompareWrapper(match
).equals(new DescriptionElementCompareWrapper(descriptionElementBase
))){
499 //TODO: propagate message
500 // MessagingUtils.informationDialog(Messages.CharacterMatrix_MULTIPLE_DATA,
501 // String.format(Messages.CharacterMatrix_MULTIPLE_DATA_MESSAGE, feature.getLabel()));
506 descriptionElementsToClone
.add(match
);
510 //clone matching descriptionElements
511 for (DescriptionElementBase descriptionElementBase
: descriptionElementsToClone
) {
512 DescriptionElementBase clone
;
514 clone
= descriptionElementBase
.clone(newDesription
);
515 clone
.getSources().forEach(source
-> {
516 if(descriptionElementBase
instanceof CategoricalData
){
517 TextData label
= new DefaultCategoricalDescriptionBuilder().build((CategoricalData
) descriptionElementBase
, null);
518 source
.setOriginalNameString(label
.getText(Language
.DEFAULT()));
520 else if(descriptionElementBase
instanceof QuantitativeData
){
521 TextData label
= new DefaultQuantitativeDescriptionBuilder().build((QuantitativeData
) descriptionElementBase
, null);
522 source
.setOriginalNameString(label
.getText(Language
.DEFAULT()));
525 } catch (CloneNotSupportedException e
) {
526 // MessagingUtils.error(CharacterMatrix.class, e);
530 //add all remaining description elements to the new description
531 for(Feature wsFeature
:datasetFeatures
){
532 boolean featureFound
= false;
533 for(DescriptionElementBase element
:newDesription
.getElements()){
534 if(element
.getFeature().equals(wsFeature
)){
540 if(wsFeature
.isSupportsCategoricalData()){
541 newDesription
.addElement(CategoricalData
.NewInstance(wsFeature
));
543 else if(wsFeature
.isSupportsQuantitativeData()){
544 newDesription
.addElement(QuantitativeData
.NewInstance(wsFeature
));
548 return newDesription
;
552 //TODO: this should either be solved in the model class itself
553 //OR this should cover all possibilities including modifiers for example
554 private class DescriptionElementCompareWrapper
{
556 private DescriptionElementBase element
;
557 private Set
<UUID
> stateUuids
= new HashSet
<>();
558 private Set
<Float
> avgs
= new HashSet
<>();
559 private Set
<Float
> exacts
= new HashSet
<>();
560 private Set
<Float
> maxs
= new HashSet
<>();
561 private Set
<Float
> mins
= new HashSet
<>();
562 private Set
<Float
> sampleSizes
= new HashSet
<>();
563 private Set
<Float
> standardDevs
= new HashSet
<>();
564 private Set
<Float
> lowerBounds
= new HashSet
<>();
565 private Set
<Float
> upperBounds
= new HashSet
<>();
566 private Set
<Float
> variances
= new HashSet
<>();
568 public DescriptionElementCompareWrapper(DescriptionElementBase element
) {
569 this.element
= element
;
570 if(element
.isInstanceOf(CategoricalData
.class)){
571 CategoricalData elementData
= (CategoricalData
)element
;
572 elementData
.getStatesOnly().forEach(state
->stateUuids
.add(state
.getUuid()));
574 else if(element
.isInstanceOf(QuantitativeData
.class)){
575 QuantitativeData elementData
= (QuantitativeData
)element
;
576 elementData
.getStatisticalValues().forEach(value
->{
577 if(value
.getType().equals(StatisticalMeasure
.AVERAGE())){
578 avgs
.add(value
.getValue());
580 else if(value
.getType().equals(StatisticalMeasure
.EXACT_VALUE())){
581 exacts
.add(value
.getValue());
584 else if(value
.getType().equals(StatisticalMeasure
.MAX())){
585 maxs
.add(value
.getValue());
587 else if(value
.getType().equals(StatisticalMeasure
.MIN())){
588 mins
.add(value
.getValue());
590 else if(value
.getType().equals(StatisticalMeasure
.SAMPLE_SIZE())){
591 sampleSizes
.add(value
.getValue());
594 else if(value
.getType().equals(StatisticalMeasure
.STANDARD_DEVIATION())){
595 standardDevs
.add(value
.getValue());
597 else if(value
.getType().equals(StatisticalMeasure
.TYPICAL_LOWER_BOUNDARY())){
598 lowerBounds
.add(value
.getValue());
601 else if(value
.getType().equals(StatisticalMeasure
.TYPICAL_UPPER_BOUNDARY())){
602 upperBounds
.add(value
.getValue());
604 else if(value
.getType().equals(StatisticalMeasure
.VARIANCE())){
605 variances
.add(value
.getValue());
612 public int hashCode() {
613 final int prime
= 31;
615 result
= prime
* result
+ getOuterType().hashCode();
616 result
= prime
* result
+ ((avgs
== null) ?
0 : avgs
.hashCode());
617 result
= prime
* result
+ ((element
== null) ?
0 : element
.hashCode());
618 result
= prime
* result
+ ((exacts
== null) ?
0 : exacts
.hashCode());
619 result
= prime
* result
+ ((lowerBounds
== null) ?
0 : lowerBounds
.hashCode());
620 result
= prime
* result
+ ((maxs
== null) ?
0 : maxs
.hashCode());
621 result
= prime
* result
+ ((mins
== null) ?
0 : mins
.hashCode());
622 result
= prime
* result
+ ((sampleSizes
== null) ?
0 : sampleSizes
.hashCode());
623 result
= prime
* result
+ ((standardDevs
== null) ?
0 : standardDevs
.hashCode());
624 result
= prime
* result
+ ((stateUuids
== null) ?
0 : stateUuids
.hashCode());
625 result
= prime
* result
+ ((upperBounds
== null) ?
0 : upperBounds
.hashCode());
626 result
= prime
* result
+ ((variances
== null) ?
0 : variances
.hashCode());
631 public boolean equals(Object obj
) {
638 if (getClass() != obj
.getClass()) {
641 DescriptionElementCompareWrapper other
= (DescriptionElementCompareWrapper
) obj
;
642 if (!getOuterType().equals(other
.getOuterType())) {
646 if (other
.avgs
!= null) {
649 } else if (!avgs
.equals(other
.avgs
)) {
652 if (element
== null) {
653 if (other
.element
!= null) {
656 } else if (!element
.equals(other
.element
)) {
659 if (exacts
== null) {
660 if (other
.exacts
!= null) {
663 } else if (!exacts
.equals(other
.exacts
)) {
666 if (lowerBounds
== null) {
667 if (other
.lowerBounds
!= null) {
670 } else if (!lowerBounds
.equals(other
.lowerBounds
)) {
674 if (other
.maxs
!= null) {
677 } else if (!maxs
.equals(other
.maxs
)) {
681 if (other
.mins
!= null) {
684 } else if (!mins
.equals(other
.mins
)) {
687 if (sampleSizes
== null) {
688 if (other
.sampleSizes
!= null) {
691 } else if (!sampleSizes
.equals(other
.sampleSizes
)) {
694 if (standardDevs
== null) {
695 if (other
.standardDevs
!= null) {
698 } else if (!standardDevs
.equals(other
.standardDevs
)) {
701 if (stateUuids
== null) {
702 if (other
.stateUuids
!= null) {
705 } else if (!stateUuids
.equals(other
.stateUuids
)) {
708 if (upperBounds
== null) {
709 if (other
.upperBounds
!= null) {
712 } else if (!upperBounds
.equals(other
.upperBounds
)) {
715 if (variances
== null) {
716 if (other
.variances
!= null) {
719 } else if (!variances
.equals(other
.variances
)) {
725 private DescriptiveDataSetService
getOuterType() {
726 return DescriptiveDataSetService
.this;