ref #7674 Add aggregated description directly to matrix after creation
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / descriptiveDataSet / matrix / CharacterMatrixBottomToolbar.java
index 3069e41c653d0b3630924b8aca76468036a7d512..4a24e2f7f2d1ae30733aa8f341dffd271b4afdaf 100644 (file)
@@ -10,11 +10,8 @@ package eu.etaxonomy.taxeditor.editor.descriptiveDataSet.matrix;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -29,22 +26,21 @@ import org.eclipse.swt.widgets.Composite;
 
 import eu.etaxonomy.cdm.api.service.IDescriptionService;
 import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
-import eu.etaxonomy.cdm.api.service.IOccurrenceService;
 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
 import eu.etaxonomy.cdm.api.service.UpdateResult;
 import eu.etaxonomy.cdm.api.service.dto.RowWrapperDTO;
+import eu.etaxonomy.cdm.api.service.dto.SpecimenRowWrapperDTO;
+import eu.etaxonomy.cdm.api.service.dto.TaxonRowWrapperDTO;
+import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.model.description.CategoricalData;
-import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
 import eu.etaxonomy.cdm.model.description.Feature;
 import eu.etaxonomy.cdm.model.description.QuantitativeData;
 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
-import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
 import eu.etaxonomy.cdm.persistence.dto.SpecimenNodeWrapper;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
-import eu.etaxonomy.taxeditor.editor.l10n.Messages;
-import eu.etaxonomy.taxeditor.model.DescriptionHelper;
 import eu.etaxonomy.taxeditor.model.ImageResources;
 import eu.etaxonomy.taxeditor.model.MessagingUtils;
 import eu.etaxonomy.taxeditor.store.CdmStore;
@@ -79,25 +75,37 @@ public class CharacterMatrixBottomToolbar extends Composite{
         btnAddDescription.addSelectionListener(new SelectionAdapter() {
             @Override
             public void widgetSelected(SelectionEvent e) {
+                String error = "";
                 SpecimenSelectionDialog dialog = new SpecimenSelectionDialog(matrix.getShell(), matrix);
                 if(dialog.open()==Window.OK){
                     Collection<SpecimenNodeWrapper> wrappers = dialog.getSpecimen();
                     for (SpecimenNodeWrapper wrapper : wrappers) {
-                        SpecimenOrObservationBase specimen = CdmStore.getService(IOccurrenceService.class).load(wrapper.getUuidAndTitleCache().getUuid());
-                        SpecimenDescription description = getDescriptionForDescriptiveDataSet(specimen);
-                        //description elements
-                        Map<Feature, DescriptionElementBase> featureToElementMap = new HashMap<>();
-                        Set<DescriptionElementBase> elements = description.getElements();
-                        for (DescriptionElementBase descriptionElementBase : elements) {
-                            Feature feature = descriptionElementBase.getFeature();
-                            featureToElementMap.put(feature, descriptionElementBase);
+                        SpecimenDescription specimenDescription = CdmStore.getService(IDescriptiveDataSetService.class)
+                                .findSpecimenDescription(matrix.getDescriptiveDataSet().getUuid(),
+                                        wrapper.getUuidAndTitleCache().getUuid());
+                        SpecimenRowWrapperDTO rowWrapper = CdmStore.getService(IDescriptiveDataSetService.class)
+                                .createSpecimenRowWrapper(specimenDescription, matrix.getDescriptiveDataSet(), true);
+                        if(rowWrapper==null){
+                            error += specimenDescription;
+                            continue;
                         }
-                        RowWrapperDTO rowWrapper = CdmStore.getService(IDescriptiveDataSetService.class).createRowWrapper(description, matrix.getDescriptiveDataSet());
+                        //add specimen description
                         matrix.getDescriptions().add(rowWrapper);
-                        matrix.getDescriptiveDataSet().addDescription(description);
+                        matrix.getDescriptiveDataSet().addDescription(specimenDescription);
+                        matrix.getCdmEntitiySession().load(specimenDescription, true);
+
+                        //add taxon description
+                        TaxonRowWrapperDTO taxonDescription = rowWrapper.getDefaultTaxonDescription();
+                        matrix.getDescriptiveDataSet().addDescription(taxonDescription.getDescription());
+                        matrix.getCdmEntitiySession().load(taxonDescription.getDescription(), true);
+
                         matrix.setDirty();
                         matrix.getSpecimenCache().remove(wrapper);
                     }
+                    if(CdmUtils.isNotBlank(error)){
+                        MessagingUtils.warningDialog("Errors during row creation", this,
+                                String.format("Could not create rows for the following description:\n\n%s", error));
+                    }
                 }
             }
         });
@@ -119,7 +127,7 @@ public class CharacterMatrixBottomToolbar extends Composite{
                 }
                 toRemove.forEach(rowToRemove->{
                     matrix.getDescriptions().remove(rowToRemove);
-                    matrix.getDescriptiveDataSet().removeDescription(rowToRemove.getSpecimenDescription());
+                    matrix.getDescriptiveDataSet().removeDescription(rowToRemove.getDescription());
                     matrix.setDirty();
                 });
             }
@@ -130,10 +138,9 @@ public class CharacterMatrixBottomToolbar extends Composite{
         Button btnAggregate = new Button(this, SWT.PUSH);
         btnAggregate.setText("Aggregate");
         btnAggregate.addSelectionListener(new SelectionAdapter() {
-            @SuppressWarnings("unchecked")
             @Override
             public void widgetSelected(SelectionEvent e) {
-                Set<TaxonNode> taxonSubtreeFilter = matrix.getDescriptiveDataSet().getTaxonSubtreeFilter();
+                List<TaxonNode> taxonSubtreeFilter = CdmStore.getService(IDescriptiveDataSetService.class).loadFilteredTaxonNodes(matrix.getDescriptiveDataSet(), null);
                 List<TaxonNodeDto> nodeDtos = taxonSubtreeFilter.stream()
                         .map(node -> new TaxonNodeDto(node)).collect(Collectors.toList());
                 TaxonNodeDto parentDto = CdmStore.getService(ITaxonNodeService.class).findCommonParentDto(nodeDtos);
@@ -154,121 +161,56 @@ public class CharacterMatrixBottomToolbar extends Composite{
                     }
                     taxonUuid = taxon.getUuid();
                 }
-                UpdateResult result = CdmStore.getService(IDescriptionService.class).aggregateDescription(taxonUuid, null, matrix.getDescriptiveDataSet().getUuid());
+                List<UUID> descriptionUuids = new ArrayList<>();
+                matrix.getDescriptiveDataSet().getDescriptions().forEach(desc->descriptionUuids.add(desc.getUuid()));
+                UpdateResult result = CdmStore.getService(IDescriptionService.class).aggregateDescription(taxonUuid, descriptionUuids, matrix.getDescriptiveDataSet().getLabel(), matrix.getDescriptiveDataSet().getUuid());
+                TaxonDescription taxonDescription = (TaxonDescription) result.getCdmEntity();
+                TaxonRowWrapperDTO taxonRowWrapper = CdmStore.getService(IDescriptiveDataSetService.class).createTaxonRowWrapper(taxonDescription, matrix.getDescriptiveDataSet());
+                matrix.getDescriptions().add(taxonRowWrapper);
                 matrix.addUpdateResult(result);
-                matrix.setDirty();
 
-                //aggregate histogram for categorical tooltip
-                Map<Feature, CategoricalDataHistogram> featureToHistogramMap = matrix.getFeatureToHistogramMap();
-                featureToHistogramMap.clear();
-                // matrix.getFeatures().forEach(feature->{
-                matrix.getDescriptions()
-                        .forEach(o -> ((RowWrapperDTO) o).getSpecimenDescription().getElements().stream()
-                                .filter(descriptionElement -> descriptionElement instanceof CategoricalData)
-                                .forEach(categoricalData -> {
-                                    Feature feature = ((CategoricalData) categoricalData).getFeature();
-                                    CategoricalDataHistogram dataHistogram = featureToHistogramMap.get(feature);
-                                    if(dataHistogram==null){
-                                        dataHistogram = new CategoricalDataHistogram(feature);
-                                    }
-                                    featureToHistogramMap.put(feature, dataHistogram);
-                                    ((CategoricalData) categoricalData).getStateData()
-                                            .forEach(stateData -> featureToHistogramMap.get(feature).addState(stateData.getState()));
-                                }));
+                aggregateCategorcialHistogram(matrix.getFeatureToHistogramMap());
+                aggregateQuantitativeSummary(matrix.getFeatureToQuantDataStatisticsMap());
             }
+
         });
     }
-    private SpecimenDescription getDescriptionForDescriptiveDataSet(SpecimenOrObservationBase specimen){
-        Set<Feature> wsFeatures = matrix.getDescriptiveDataSet().getDescriptiveSystem().getDistinctFeatures();
-        List<DescriptionElementBase> matchingDescriptionElements = new ArrayList<>();
 
-        for (SpecimenDescription specimenDescription : (Set<SpecimenDescription>) specimen.getDescriptions()) {
-            specimenDescription = (SpecimenDescription) CdmStore.getService(IDescriptionService.class).load(specimenDescription.getUuid());
-            Set<Feature> specimenDescriptionFeatures = new HashSet<>();
-            //gather specimen description features and check for match with WS features
-            for (DescriptionElementBase specimenDescriptionElement : specimenDescription.getElements()) {
-                Feature feature = specimenDescriptionElement.getFeature();
-                specimenDescriptionFeatures.add(feature);
-                if(wsFeatures.contains(feature)){
-                    matchingDescriptionElements.add(specimenDescriptionElement);
-                }
-            }
-            //if description with the exact same features is found return the description
-            if(specimenDescriptionFeatures.equals(wsFeatures)){
-                return specimenDescription;
-            }
-        }
-        //Create new specimen description if no match was found
-        matrix.setDirty();
-        SpecimenDescription newDesription = SpecimenDescription.NewInstance(specimen);
-        newDesription.setTitleCache(Messages.CharacterMatrix_DESCRIPTIVE_DATA_SET+matrix.getDescriptiveDataSet().getLabel()+": "+newDesription.generateTitle(), true); //$NON-NLS-2$
+    @SuppressWarnings("unchecked")
+    private void aggregateCategorcialHistogram(Map<Feature, CategoricalDataHistogram> featureToHistogramMap) {
+        featureToHistogramMap.clear();
+        matrix.getDescriptions().stream()
+        .filter(desc->desc instanceof SpecimenRowWrapperDTO)
+                .forEach(o -> ((SpecimenRowWrapperDTO) o).getDescription().getElements().stream()
+                        .filter(descriptionElement -> descriptionElement instanceof CategoricalData)
+                        .forEach(categoricalData -> {
+                            Feature feature = ((CategoricalData) categoricalData).getFeature();
+                            CategoricalDataHistogram dataHistogram = featureToHistogramMap.get(feature);
+                            if(dataHistogram==null){
+                                dataHistogram = new CategoricalDataHistogram(feature);
+                            }
+                            featureToHistogramMap.put(feature, dataHistogram);
+                            ((CategoricalData) categoricalData).getStateData()
+                                    .forEach(stateData -> featureToHistogramMap.get(feature).addState(stateData.getState()));
+                        }));
+    }
 
-        //check for equals description element (same feature and same values)
-        Map<Feature, List<DescriptionElementBase>> featureToElementMap = new HashMap<>();
-        for(DescriptionElementBase element:matchingDescriptionElements){
-            List<DescriptionElementBase> list = featureToElementMap.get(element.getFeature());
-            if(list==null){
-                list = new ArrayList<>();
-            }
-            list.add(element);
-            featureToElementMap.put(element.getFeature(), list);
-        }
-        Set<DescriptionElementBase> descriptionElementsToClone = new HashSet<>();
-        for(Feature feature:featureToElementMap.keySet()){
-            List<DescriptionElementBase> elements = featureToElementMap.get(feature);
-            //no duplicate description elements found for this feature
-            if(elements.size()==1){
-                descriptionElementsToClone.add(elements.get(0));
-            }
-            //duplicates found -> check if all are equal
-            else{
-                DescriptionElementBase match = null;
-                for (DescriptionElementBase descriptionElementBase : elements) {
-                    if(match==null){
-                        match = descriptionElementBase;
-                    }
-                    else if(!new DescriptionElementCompareWrapper(match).equals(new DescriptionElementCompareWrapper(descriptionElementBase))){
-                        match = null;
-                        MessagingUtils.informationDialog(Messages.CharacterMatrix_MULTIPLE_DATA,
-                                String.format(Messages.CharacterMatrix_MULTIPLE_DATA_MESSAGE, feature.getLabel()));
-                        break;
+    @SuppressWarnings("unchecked")
+    private void aggregateQuantitativeSummary(Map<Feature, QuantitativeDataStatistics> featureToQuantDataStatisticsMap) {
+        featureToQuantDataStatisticsMap.clear();
+        matrix.getDescriptions().stream()
+        .filter(desc->desc instanceof SpecimenRowWrapperDTO)
+        .forEach(o -> ((SpecimenRowWrapperDTO) o).getDescription().getElements().stream()
+                .filter(descriptionElement -> descriptionElement instanceof QuantitativeData)
+                .forEach(quantData -> {
+                    Feature feature = ((QuantitativeData) quantData).getFeature();
+                    QuantitativeDataStatistics dataStatistics = featureToQuantDataStatisticsMap.get(feature);
+                    if(dataStatistics==null){
+                        dataStatistics = new QuantitativeDataStatistics();
                     }
-                }
-                if(match!=null){
-                    descriptionElementsToClone.add(match);
-                }
-            }
-        }
-        //clone matching descriptionElements
-        for (DescriptionElementBase descriptionElementBase : descriptionElementsToClone) {
-            DescriptionElementBase clone;
-            try {
-                clone = descriptionElementBase.clone(newDesription);
-                clone.getSources().forEach(source -> source.setOriginalNameString(DescriptionHelper.getLabel(descriptionElementBase)));
-            } catch (CloneNotSupportedException e) {
-                MessagingUtils.error(CharacterMatrix.class, e);
-            }
-        }
-
-        //add all remaining description elements to the new description
-        for(Feature wsFeature:wsFeatures){
-            boolean featureFound = false;
-            for(DescriptionElementBase element:newDesription.getElements()){
-                if(element.getFeature().equals(wsFeature)){
-                    featureFound = true;
-                    break;
-                }
-            }
-            if(!featureFound){
-                if(wsFeature.isSupportsCategoricalData()){
-                    newDesription.addElement(CategoricalData.NewInstance(wsFeature));
-                }
-                else if(wsFeature.isSupportsQuantitativeData()){
-                    newDesription.addElement(QuantitativeData.NewInstance(wsFeature));
-                }
-            }
-        }
-        return newDesription;
-
+                    featureToQuantDataStatisticsMap.put(feature, dataStatistics);
+                    dataStatistics.addQuantitativeData((QuantitativeData) quantData);
+                }));
     }
+
 }