1 package eu
.etaxonomy
.cdm
.api
.service
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Arrays
;
5 import java
.util
.Collection
;
6 import java
.util
.HashMap
;
7 import java
.util
.HashSet
;
10 import java
.util
.Optional
;
12 import java
.util
.UUID
;
13 import java
.util
.stream
.Collectors
;
15 import org
.apache
.log4j
.Logger
;
16 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
17 import org
.springframework
.stereotype
.Service
;
18 import org
.springframework
.transaction
.annotation
.Transactional
;
20 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RowWrapperDTO
;
21 import eu
.etaxonomy
.cdm
.api
.service
.dto
.SpecimenRowWrapperDTO
;
22 import eu
.etaxonomy
.cdm
.api
.service
.dto
.TaxonRowWrapperDTO
;
23 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
24 import eu
.etaxonomy
.cdm
.common
.monitor
.IRemotingProgressMonitor
;
25 import eu
.etaxonomy
.cdm
.filter
.TaxonNodeFilter
;
26 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
27 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
28 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
29 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
30 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
31 import eu
.etaxonomy
.cdm
.model
.common
.OriginalSourceType
;
32 import eu
.etaxonomy
.cdm
.model
.description
.CategoricalData
;
33 import eu
.etaxonomy
.cdm
.model
.description
.Character
;
34 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
35 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
36 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveDataSet
;
37 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveSystemRole
;
38 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
39 import eu
.etaxonomy
.cdm
.model
.description
.QuantitativeData
;
40 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
41 import eu
.etaxonomy
.cdm
.model
.description
.StateData
;
42 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasure
;
43 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasurementValue
;
44 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
45 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
46 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
47 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
48 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
49 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
54 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptiveDataSetDao
;
55 import eu
.etaxonomy
.cdm
.persistence
.dto
.SpecimenNodeWrapper
;
56 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
57 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
60 @Transactional(readOnly
=true)
61 public class DescriptiveDataSetService
62 extends IdentifiableServiceBase
<DescriptiveDataSet
, IDescriptiveDataSetDao
>
63 implements IDescriptiveDataSetService
{
65 private static Logger logger
= Logger
.getLogger(DescriptiveDataSetService
.class);
68 private IOccurrenceService occurrenceService
;
71 private ITaxonService taxonService
;
74 private IDescriptionService descriptionService
;
77 private ITaxonNodeService taxonNodeService
;
80 private IProgressMonitorService progressMonitorService
;
84 protected void setDao(IDescriptiveDataSetDao dao
) {
89 public Map
<DescriptionBase
, Set
<DescriptionElementBase
>> getDescriptionElements(DescriptiveDataSet descriptiveDataSet
, Set
<Feature
> features
, Integer pageSize
, Integer pageNumber
,
90 List
<String
> propertyPaths
) {
91 return dao
.getDescriptionElements(descriptiveDataSet
, features
, pageSize
, pageNumber
, propertyPaths
);
95 public <T
extends DescriptionElementBase
> Map
<UuidAndTitleCache
, Map
<UUID
, Set
<T
>>> getTaxonFeatureDescriptionElementMap(
96 Class
<T
> clazz
, UUID descriptiveDataSetUuid
, DescriptiveSystemRole role
) {
97 return dao
.getTaxonFeatureDescriptionElementMap(clazz
, descriptiveDataSetUuid
, role
);
101 public List
<UuidAndTitleCache
<DescriptiveDataSet
>> getDescriptiveDataSetUuidAndTitleCache(Integer limitOfInitialElements
, String pattern
) {
102 return dao
.getDescriptiveDataSetUuidAndTitleCache( limitOfInitialElements
, pattern
);
106 public ArrayList
<RowWrapperDTO
> getRowWrapper(DescriptiveDataSet descriptiveDataSet
, IProgressMonitor monitor
) {
107 monitor
.beginTask("Load row wrapper", descriptiveDataSet
.getDescriptions().size());
108 ArrayList
<RowWrapperDTO
> wrappers
= new ArrayList
<>();
109 Set
<DescriptionBase
> descriptions
= descriptiveDataSet
.getDescriptions();
110 for (DescriptionBase description
: descriptions
) {
111 if(monitor
.isCanceled()){
112 return new ArrayList
<>();
114 RowWrapperDTO rowWrapper
= null;
115 if(HibernateProxyHelper
.isInstanceOf(description
, TaxonDescription
.class)){
116 rowWrapper
= createTaxonRowWrapper(description
.getUuid(), descriptiveDataSet
.getUuid());
118 else if (HibernateProxyHelper
.isInstanceOf(description
, SpecimenDescription
.class)){
119 rowWrapper
= createSpecimenRowWrapper(HibernateProxyHelper
.deproxy(description
, SpecimenDescription
.class), descriptiveDataSet
);
121 if(rowWrapper
!=null){
122 wrappers
.add(rowWrapper
);
130 public Collection
<SpecimenNodeWrapper
> loadSpecimens(DescriptiveDataSet descriptiveDataSet
){
131 List
<UUID
> filteredNodes
= findFilteredTaxonNodes(descriptiveDataSet
);
132 return occurrenceService
.listUuidAndTitleCacheByAssociatedTaxon(filteredNodes
, null, null);
136 public List
<UUID
> findFilteredTaxonNodes(DescriptiveDataSet descriptiveDataSet
){
137 TaxonNodeFilter filter
= TaxonNodeFilter
.NewRankInstance(descriptiveDataSet
.getMinRank(), descriptiveDataSet
.getMaxRank());
138 descriptiveDataSet
.getGeoFilter().forEach(area
-> filter
.orArea(area
.getUuid()));
139 descriptiveDataSet
.getTaxonSubtreeFilter().forEach(node
-> filter
.orSubtree(node
));
140 filter
.setIncludeUnpublished(true);
142 return taxonNodeService
.uuidList(filter
);
146 public List
<TaxonNode
> loadFilteredTaxonNodes(DescriptiveDataSet descriptiveDataSet
, List
<String
> propertyPaths
){
147 return taxonNodeService
.load(findFilteredTaxonNodes(descriptiveDataSet
), propertyPaths
);
150 private TaxonNode
findTaxonNodeForDescription(TaxonNode taxonNode
, SpecimenOrObservationBase specimen
){
151 Collection
<SpecimenNodeWrapper
> nodeWrapper
= occurrenceService
.listUuidAndTitleCacheByAssociatedTaxon(Arrays
.asList(taxonNode
.getUuid()), null, null);
152 for (SpecimenNodeWrapper specimenNodeWrapper
: nodeWrapper
) {
153 if(specimenNodeWrapper
.getUuidAndTitleCache().getId().equals(specimen
.getId())){
161 public TaxonRowWrapperDTO
createTaxonRowWrapper(UUID taxonDescriptionUuid
, UUID descriptiveDataSetUuid
) {
162 TaxonNode taxonNode
= null;
163 Classification classification
= null;
164 TaxonDescription description
= (TaxonDescription
) descriptionService
.load(taxonDescriptionUuid
,
165 Arrays
.asList("taxon", "descriptionElements", "descriptionElements.feature"));
166 DescriptiveDataSet descriptiveDataSet
= dao
.load(descriptiveDataSetUuid
, null);
167 Optional
<TaxonNode
> first
= descriptiveDataSet
.getTaxonSubtreeFilter().stream()
168 .filter(node
->node
.getClassification()!=null).findFirst();
169 Optional
<Classification
> classificationOptional
= first
.map(node
->node
.getClassification());
170 if(classificationOptional
.isPresent()){
171 classification
= classificationOptional
.get();
172 Taxon taxon
= (Taxon
) taxonService
.load(description
.getTaxon().getId(), Arrays
.asList("taxonNodes", "taxonNodes.classification"));
173 taxonNode
= taxon
.getTaxonNode(classification
);
175 return new TaxonRowWrapperDTO(description
, taxonNode
);
179 public SpecimenRowWrapperDTO
createSpecimenRowWrapper(SpecimenDescription description
, DescriptiveDataSet descriptiveDataSet
){
180 SpecimenOrObservationBase specimen
= description
.getDescribedSpecimenOrObservation();
181 TaxonNode taxonNode
= null;
182 FieldUnit fieldUnit
= null;
183 String identifier
= null;
184 NamedArea country
= null;
185 //supplemental information
187 Set
<TaxonNode
> taxonSubtreeFilter
= descriptiveDataSet
.getTaxonSubtreeFilter();
188 for (TaxonNode node
: taxonSubtreeFilter
) {
190 List
<String
> taxonNodePropertyPath
= Arrays
.asList("taxon", "taxon.descriptions", "taxon.descriptions.markers");
191 node
= taxonNodeService
.load(node
.getId(), taxonNodePropertyPath
);
192 taxonNode
= findTaxonNodeForDescription(node
, specimen
);
197 //check for child nodes
198 List
<TaxonNode
> allChildren
= taxonNodeService
.loadChildNodesOfTaxonNode(node
, taxonNodePropertyPath
, true, true, null);
199 for (TaxonNode child
: allChildren
) {
200 taxonNode
= findTaxonNodeForDescription(child
, specimen
);
210 //taxon node was found
213 Collection
<FieldUnit
> fieldUnits
= occurrenceService
.findFieldUnits(specimen
.getUuid(),
214 Arrays
.asList(new String
[]{
216 "gatheringEvent.country"
218 if(fieldUnits
.size()!=1){
219 logger
.error("More than one or no field unit found for specimen"); //$NON-NLS-1$
223 fieldUnit
= fieldUnits
.iterator().next();
226 if(HibernateProxyHelper
.isInstanceOf(specimen
, DerivedUnit
.class)){
227 identifier
= occurrenceService
.getMostSignificantIdentifier(HibernateProxyHelper
.deproxy(specimen
, DerivedUnit
.class));
230 if(fieldUnit
!=null && fieldUnit
.getGatheringEvent()!=null){
231 country
= fieldUnit
.getGatheringEvent().getCountry();
233 //get default taxon description
234 TaxonDescription defaultTaxonDescription
= findDefaultTaxonDescription(descriptiveDataSet
,
236 TaxonRowWrapperDTO taxonRowWrapper
= defaultTaxonDescription
!= null
237 ?
createTaxonRowWrapper(defaultTaxonDescription
.getUuid(), descriptiveDataSet
.getUuid()) : null;
238 return new SpecimenRowWrapperDTO(description
, taxonNode
, fieldUnit
, identifier
, country
, taxonRowWrapper
);
242 @Transactional(readOnly
= false)
243 public void updateTitleCache(Class
<?
extends DescriptiveDataSet
> clazz
, Integer stepSize
,
244 IIdentifiableEntityCacheStrategy
<DescriptiveDataSet
> cacheStrategy
, IProgressMonitor monitor
) {
246 clazz
= DescriptiveDataSet
.class;
248 super.updateTitleCacheImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
252 * Returns a {@link TaxonDescription} for a given taxon node with corresponding
253 * features according to the {@link DescriptiveDataSet}.<br>
254 * If a description is found that matches all features of the data set this description
256 * @param descriptiveDataSetUuid the uuid of the dataset defining the features
257 * @param taxonNodeUuid the uuid of the taxon node that links to the taxon
258 * if none could be found
259 * @return the found taxon description or <code>null</code>
261 private TaxonDescription
findDefaultTaxonDescription(DescriptiveDataSet dataSet
, TaxonNode taxonNode
){
262 Set
<DescriptionBase
> dataSetDescriptions
= dataSet
.getDescriptions();
263 //filter out COMPUTED descriptions
264 List
<TaxonDescription
> nonComputedDescriptions
= taxonNode
.getTaxon().getDescriptions().stream()
265 .filter(desc
-> desc
.getMarkers().stream()
266 .noneMatch(marker
-> marker
.getMarkerType().equals(MarkerType
.COMPUTED())))
267 .collect(Collectors
.toList());
268 for (TaxonDescription taxonDescription
: nonComputedDescriptions
) {
269 for (DescriptionBase description
: dataSetDescriptions
) {
270 if(description
.getUuid().equals(taxonDescription
.getUuid())){
271 return HibernateProxyHelper
.deproxy(descriptionService
.load(taxonDescription
.getUuid(),
272 Arrays
.asList("taxon", "descriptionElements", "descriptionElements.feature")), TaxonDescription
.class);
280 @Transactional(readOnly
=false)
281 public UpdateResult
aggregateTaxonDescription(UUID taxonNodeUuid
, UUID descriptiveDataSetUuid
,
282 IRemotingProgressMonitor monitor
){
283 UpdateResult result
= new UpdateResult();
285 TaxonNode node
= taxonNodeService
.load(taxonNodeUuid
);
286 Taxon taxon
= HibernateProxyHelper
.deproxy(taxonService
.load(node
.getTaxon().getUuid()), Taxon
.class);
287 result
.setCdmEntity(taxon
);
289 //get all "computed" descriptions from all sub nodes
290 List
<TaxonNode
> childNodes
= taxonNodeService
.listChildrenOf(node
, null, null, true, false, null);
291 List
<TaxonDescription
> computedDescriptions
= new ArrayList
<>();
293 childNodes
.stream().map(childNode
-> childNode
.getTaxon())
294 .forEach(childTaxon
-> childTaxon
.getDescriptions().stream()
295 // filter out non-computed descriptions
296 .filter(description
-> description
.getMarkers().stream()
297 .anyMatch(marker
-> marker
.getMarkerType().equals(MarkerType
.COMPUTED())))
298 // add them to the list
299 .forEach(computedDescription
-> computedDescriptions
.add(computedDescription
)));
301 UpdateResult aggregateDescription
= aggregateDescription(taxon
, computedDescriptions
,
302 "[Taxon Descriptions]"+taxon
.getTitleCache(), descriptiveDataSetUuid
);
303 result
.includeResult(aggregateDescription
);
304 result
.setCdmEntity(aggregateDescription
.getCdmEntity());
305 aggregateDescription
.setCdmEntity(null);
310 @Transactional(readOnly
=false)
311 public UpdateResult
aggregateDescription(UUID taxonUuid
, List
<UUID
> descriptionUuids
, String descriptionTitle
312 , UUID descriptiveDataSetUuid
) {
313 UpdateResult result
= new UpdateResult();
315 TaxonBase taxonBase
= taxonService
.load(taxonUuid
);
316 if(!(taxonBase
instanceof Taxon
)){
317 result
.addException(new ClassCastException("The given taxonUUID does not belong to a taxon"));
321 Taxon taxon
= (Taxon
)taxonBase
;
323 List
<DescriptionBase
> descriptions
= descriptionService
.load(descriptionUuids
, null);
325 UpdateResult aggregateDescriptionResult
= aggregateDescription(taxon
, descriptions
, descriptionTitle
, descriptiveDataSetUuid
);
326 result
.setCdmEntity(aggregateDescriptionResult
.getCdmEntity());
327 aggregateDescriptionResult
.setCdmEntity(null);
328 result
.includeResult(aggregateDescriptionResult
);
332 @SuppressWarnings("unchecked")
333 private UpdateResult
aggregateDescription(Taxon taxon
, List
<?
extends DescriptionBase
> descriptions
, String descriptionTitle
334 , UUID descriptiveDataSetUuid
) {
335 UpdateResult result
= new UpdateResult();
336 Map
<Character
, List
<DescriptionElementBase
>> featureToElementMap
= new HashMap
<>();
338 DescriptiveDataSet dataSet
= load(descriptiveDataSetUuid
);
340 result
.addException(new IllegalArgumentException("Could not find data set for uuid "+descriptiveDataSetUuid
));
345 //extract all character description elements
346 descriptions
.forEach(description
->{
347 description
.getElements()
349 //filter out elements that do not have a Characters as Feature
350 .filter(element
->HibernateProxyHelper
.isInstanceOf(((DescriptionElementBase
)element
).getFeature(), Character
.class))
352 DescriptionElementBase descriptionElement
= (DescriptionElementBase
)ele
;
353 List
<DescriptionElementBase
> list
= featureToElementMap
.get(descriptionElement
.getFeature());
355 list
= new ArrayList
<>();
357 list
.add(descriptionElement
);
358 featureToElementMap
.put(HibernateProxyHelper
.deproxy(descriptionElement
.getFeature(), Character
.class), list
);
362 TaxonDescription description
= TaxonDescription
.NewInstance(taxon
);
363 description
.setTitleCache("[Aggregation] "+descriptionTitle
, true);
364 description
.addMarker(Marker
.NewInstance(MarkerType
.COMPUTED(), true));
365 IdentifiableSource source
= IdentifiableSource
.NewInstance(OriginalSourceType
.Aggregation
);
366 description
.addSource(source
);
367 description
.addDescriptiveDataSet(dataSet
);
369 featureToElementMap
.forEach((feature
, elements
)->{
370 //aggregate categorical data
371 if(feature
.isSupportsCategoricalData()){
372 CategoricalData aggregate
= CategoricalData
.NewInstance(feature
);
374 .filter(element
->element
instanceof CategoricalData
)
375 .forEach(categoricalData
->((CategoricalData
)categoricalData
).getStateData()
376 .forEach(stateData
->aggregate
.addStateData((StateData
) stateData
.clone())));
377 description
.addElement(aggregate
);
379 //aggregate quantitative data
380 else if(feature
.isSupportsQuantitativeData()){
381 QuantitativeData aggregate
= QuantitativeData
.NewInstance(feature
);
383 .filter(element
->element
instanceof QuantitativeData
)
384 .forEach(categoricalData
->((QuantitativeData
)categoricalData
).getStatisticalValues()
385 .forEach(statisticalValue
->aggregate
.addStatisticalValue((StatisticalMeasurementValue
) statisticalValue
.clone())));
386 description
.addElement(aggregate
);
389 result
.addUpdatedObject(taxon
);
390 result
.setCdmEntity(description
);
395 @Transactional(readOnly
=false)
396 public TaxonRowWrapperDTO
createTaxonDescription(UUID dataSetUuid
, UUID taxonNodeUuid
, MarkerType markerType
, boolean markerFlag
){
397 DescriptiveDataSet dataSet
= load(dataSetUuid
);
398 TaxonNode taxonNode
= taxonNodeService
.load(taxonNodeUuid
, Arrays
.asList("taxon"));
399 TaxonDescription newTaxonDescription
= TaxonDescription
.NewInstance(taxonNode
.getTaxon());
402 if(markerType
.equals(MarkerType
.USE())){
405 else if(markerType
.equals(MarkerType
.IN_BIBLIOGRAPHY())){
406 tag
= "[Literature]";
409 newTaxonDescription
.setTitleCache(tag
+" "+dataSet
.getLabel()+": "+newTaxonDescription
.generateTitle(), true); //$NON-NLS-2$
410 if(markerType
!=null){
411 newTaxonDescription
.addMarker(Marker
.NewInstance(markerType
, markerFlag
));
413 dataSet
.getDescriptiveSystem().getDistinctFeatures().forEach(wsFeature
->{
414 if(wsFeature
.isSupportsCategoricalData()){
415 newTaxonDescription
.addElement(CategoricalData
.NewInstance(wsFeature
));
417 else if(wsFeature
.isSupportsQuantitativeData()){
418 newTaxonDescription
.addElement(QuantitativeData
.NewInstance(wsFeature
));
421 dataSet
.addDescription(newTaxonDescription
);
423 return createTaxonRowWrapper(newTaxonDescription
.getUuid(), dataSet
.getUuid());
427 @Transactional(readOnly
=false)
428 public SpecimenDescription
findSpecimenDescription(UUID descriptiveDataSetUuid
, UUID specimenUuid
, boolean addDatasetSource
){
429 DescriptiveDataSet dataSet
= load(descriptiveDataSetUuid
);
430 SpecimenOrObservationBase specimen
= occurrenceService
.load(specimenUuid
);
432 Set
<Feature
> datasetFeatures
= dataSet
.getDescriptiveSystem().getDistinctFeatures();
433 List
<DescriptionElementBase
> matchingDescriptionElements
= new ArrayList
<>();
435 for (SpecimenDescription specimenDescription
: (Set
<SpecimenDescription
>) specimen
.getDescriptions()) {
436 specimenDescription
= (SpecimenDescription
) descriptionService
.load(specimenDescription
.getUuid());
438 //check if description is already added to data set
439 if(dataSet
.getDescriptions().contains(specimenDescription
)){
440 return specimenDescription
;
443 //gather specimen description features and check for match with dataset features
444 Set
<Feature
> specimenDescriptionFeatures
= new HashSet
<>();
445 for (DescriptionElementBase specimenDescriptionElement
: specimenDescription
.getElements()) {
446 Feature feature
= specimenDescriptionElement
.getFeature();
447 specimenDescriptionFeatures
.add(feature
);
448 if(datasetFeatures
.contains(feature
)){
449 matchingDescriptionElements
.add(specimenDescriptionElement
);
453 //Create new specimen description if description has not already been added to the dataset
454 SpecimenDescription newDesription
= SpecimenDescription
.NewInstance(specimen
);
455 newDesription
.setTitleCache("Dataset "+dataSet
.getLabel()+": "+newDesription
.generateTitle(), true); //$NON-NLS-2$
457 //check for equals description element (same feature and same values)
458 Map
<Feature
, List
<DescriptionElementBase
>> featureToElementMap
= new HashMap
<>();
459 for(DescriptionElementBase element
:matchingDescriptionElements
){
460 List
<DescriptionElementBase
> list
= featureToElementMap
.get(element
.getFeature());
462 list
= new ArrayList
<>();
465 featureToElementMap
.put(element
.getFeature(), list
);
467 Set
<DescriptionElementBase
> descriptionElementsToClone
= new HashSet
<>();
468 for(Feature feature
:featureToElementMap
.keySet()){
469 List
<DescriptionElementBase
> elements
= featureToElementMap
.get(feature
);
470 //no duplicate description elements found for this feature
471 if(elements
.size()==1){
472 descriptionElementsToClone
.add(elements
.get(0));
474 //duplicates found -> check if all are equal
476 DescriptionElementBase match
= null;
477 for (DescriptionElementBase descriptionElementBase
: elements
) {
479 match
= descriptionElementBase
;
481 else if(!new DescriptionElementCompareWrapper(match
).equals(new DescriptionElementCompareWrapper(descriptionElementBase
))){
483 //TODO: propagate message
484 // MessagingUtils.informationDialog(Messages.CharacterMatrix_MULTIPLE_DATA,
485 // String.format(Messages.CharacterMatrix_MULTIPLE_DATA_MESSAGE, feature.getLabel()));
490 descriptionElementsToClone
.add(match
);
494 //clone matching descriptionElements
495 for (DescriptionElementBase descriptionElementBase
: descriptionElementsToClone
) {
496 DescriptionElementBase clone
;
498 clone
= descriptionElementBase
.clone(newDesription
);
499 clone
.getSources().forEach(source
-> {
500 if(descriptionElementBase
instanceof CategoricalData
){
501 TextData label
= new DefaultCategoricalDescriptionBuilder().build((CategoricalData
) descriptionElementBase
, null);
502 source
.setOriginalNameString(label
.getText(Language
.DEFAULT()));
504 else if(descriptionElementBase
instanceof QuantitativeData
){
505 TextData label
= new DefaultQuantitativeDescriptionBuilder().build((QuantitativeData
) descriptionElementBase
, null);
506 source
.setOriginalNameString(label
.getText(Language
.DEFAULT()));
509 } catch (CloneNotSupportedException e
) {
514 //add all remaining description elements to the new description
515 for(Feature wsFeature
:datasetFeatures
){
516 boolean featureFound
= false;
517 for(DescriptionElementBase element
:newDesription
.getElements()){
518 if(element
.getFeature().equals(wsFeature
)){
524 if(wsFeature
.isSupportsCategoricalData()){
525 newDesription
.addElement(CategoricalData
.NewInstance(wsFeature
));
527 else if(wsFeature
.isSupportsQuantitativeData()){
528 newDesription
.addElement(QuantitativeData
.NewInstance(wsFeature
));
532 //add sources of data set
533 if(addDatasetSource
){
534 dataSet
.getSources().forEach(source
->{
536 newDesription
.addSource((IdentifiableSource
) source
.clone());
537 } catch (CloneNotSupportedException e
) {
542 return newDesription
;
546 //TODO: this should either be solved in the model class itself
547 //OR this should cover all possibilities including modifiers for example
548 private class DescriptionElementCompareWrapper
{
550 private DescriptionElementBase element
;
551 private Set
<UUID
> stateUuids
= new HashSet
<>();
552 private Set
<Float
> avgs
= new HashSet
<>();
553 private Set
<Float
> exacts
= new HashSet
<>();
554 private Set
<Float
> maxs
= new HashSet
<>();
555 private Set
<Float
> mins
= new HashSet
<>();
556 private Set
<Float
> sampleSizes
= new HashSet
<>();
557 private Set
<Float
> standardDevs
= new HashSet
<>();
558 private Set
<Float
> lowerBounds
= new HashSet
<>();
559 private Set
<Float
> upperBounds
= new HashSet
<>();
560 private Set
<Float
> variances
= new HashSet
<>();
562 public DescriptionElementCompareWrapper(DescriptionElementBase element
) {
563 this.element
= element
;
564 if(element
.isInstanceOf(CategoricalData
.class)){
565 CategoricalData elementData
= (CategoricalData
)element
;
566 elementData
.getStatesOnly().forEach(state
->stateUuids
.add(state
.getUuid()));
568 else if(element
.isInstanceOf(QuantitativeData
.class)){
569 QuantitativeData elementData
= (QuantitativeData
)element
;
570 elementData
.getStatisticalValues().forEach(value
->{
571 if(value
.getType().equals(StatisticalMeasure
.AVERAGE())){
572 avgs
.add(value
.getValue());
574 else if(value
.getType().equals(StatisticalMeasure
.EXACT_VALUE())){
575 exacts
.add(value
.getValue());
578 else if(value
.getType().equals(StatisticalMeasure
.MAX())){
579 maxs
.add(value
.getValue());
581 else if(value
.getType().equals(StatisticalMeasure
.MIN())){
582 mins
.add(value
.getValue());
584 else if(value
.getType().equals(StatisticalMeasure
.SAMPLE_SIZE())){
585 sampleSizes
.add(value
.getValue());
588 else if(value
.getType().equals(StatisticalMeasure
.STANDARD_DEVIATION())){
589 standardDevs
.add(value
.getValue());
591 else if(value
.getType().equals(StatisticalMeasure
.TYPICAL_LOWER_BOUNDARY())){
592 lowerBounds
.add(value
.getValue());
595 else if(value
.getType().equals(StatisticalMeasure
.TYPICAL_UPPER_BOUNDARY())){
596 upperBounds
.add(value
.getValue());
598 else if(value
.getType().equals(StatisticalMeasure
.VARIANCE())){
599 variances
.add(value
.getValue());
606 public int hashCode() {
607 final int prime
= 31;
609 result
= prime
* result
+ getOuterType().hashCode();
610 result
= prime
* result
+ ((avgs
== null) ?
0 : avgs
.hashCode());
611 result
= prime
* result
+ ((element
== null) ?
0 : element
.hashCode());
612 result
= prime
* result
+ ((exacts
== null) ?
0 : exacts
.hashCode());
613 result
= prime
* result
+ ((lowerBounds
== null) ?
0 : lowerBounds
.hashCode());
614 result
= prime
* result
+ ((maxs
== null) ?
0 : maxs
.hashCode());
615 result
= prime
* result
+ ((mins
== null) ?
0 : mins
.hashCode());
616 result
= prime
* result
+ ((sampleSizes
== null) ?
0 : sampleSizes
.hashCode());
617 result
= prime
* result
+ ((standardDevs
== null) ?
0 : standardDevs
.hashCode());
618 result
= prime
* result
+ ((stateUuids
== null) ?
0 : stateUuids
.hashCode());
619 result
= prime
* result
+ ((upperBounds
== null) ?
0 : upperBounds
.hashCode());
620 result
= prime
* result
+ ((variances
== null) ?
0 : variances
.hashCode());
625 public boolean equals(Object obj
) {
632 if (getClass() != obj
.getClass()) {
635 DescriptionElementCompareWrapper other
= (DescriptionElementCompareWrapper
) obj
;
636 if (!getOuterType().equals(other
.getOuterType())) {
640 if (other
.avgs
!= null) {
643 } else if (!avgs
.equals(other
.avgs
)) {
646 if (element
== null) {
647 if (other
.element
!= null) {
650 } else if (!element
.equals(other
.element
)) {
653 if (exacts
== null) {
654 if (other
.exacts
!= null) {
657 } else if (!exacts
.equals(other
.exacts
)) {
660 if (lowerBounds
== null) {
661 if (other
.lowerBounds
!= null) {
664 } else if (!lowerBounds
.equals(other
.lowerBounds
)) {
668 if (other
.maxs
!= null) {
671 } else if (!maxs
.equals(other
.maxs
)) {
675 if (other
.mins
!= null) {
678 } else if (!mins
.equals(other
.mins
)) {
681 if (sampleSizes
== null) {
682 if (other
.sampleSizes
!= null) {
685 } else if (!sampleSizes
.equals(other
.sampleSizes
)) {
688 if (standardDevs
== null) {
689 if (other
.standardDevs
!= null) {
692 } else if (!standardDevs
.equals(other
.standardDevs
)) {
695 if (stateUuids
== null) {
696 if (other
.stateUuids
!= null) {
699 } else if (!stateUuids
.equals(other
.stateUuids
)) {
702 if (upperBounds
== null) {
703 if (other
.upperBounds
!= null) {
706 } else if (!upperBounds
.equals(other
.upperBounds
)) {
709 if (variances
== null) {
710 if (other
.variances
!= null) {
713 } else if (!variances
.equals(other
.variances
)) {
719 private DescriptiveDataSetService
getOuterType() {
720 return DescriptiveDataSetService
.this;