Project

General

Profile

Download (13.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
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.
8
*/
9
package eu.etaxonomy.taxeditor.editor.descriptiveDataSet.matrix;
10

    
11
import java.util.ArrayList;
12
import java.util.Collection;
13
import java.util.HashMap;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.Set;
18
import java.util.UUID;
19
import java.util.stream.Collectors;
20

    
21
import org.eclipse.jface.layout.GridDataFactory;
22
import org.eclipse.jface.window.Window;
23
import org.eclipse.swt.SWT;
24
import org.eclipse.swt.events.SelectionAdapter;
25
import org.eclipse.swt.events.SelectionEvent;
26
import org.eclipse.swt.layout.RowLayout;
27
import org.eclipse.swt.widgets.Button;
28
import org.eclipse.swt.widgets.Composite;
29

    
30
import eu.etaxonomy.cdm.api.service.IDescriptionService;
31
import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
32
import eu.etaxonomy.cdm.api.service.IOccurrenceService;
33
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
34
import eu.etaxonomy.cdm.api.service.UpdateResult;
35
import eu.etaxonomy.cdm.api.service.dto.RowWrapperDTO;
36
import eu.etaxonomy.cdm.model.description.CategoricalData;
37
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
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.occurrence.SpecimenOrObservationBase;
42
import eu.etaxonomy.cdm.model.taxon.Taxon;
43
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
44
import eu.etaxonomy.cdm.persistence.dto.SpecimenNodeWrapper;
45
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
46
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
47
import eu.etaxonomy.taxeditor.model.DescriptionHelper;
48
import eu.etaxonomy.taxeditor.model.ImageResources;
49
import eu.etaxonomy.taxeditor.model.MessagingUtils;
50
import eu.etaxonomy.taxeditor.store.CdmStore;
51
import eu.etaxonomy.taxeditor.ui.dialog.selection.TaxonSelectionDialog;
52

    
53
/**
54
 * @author pplitzner
55
 * @since Jul 9, 2018
56
 *
57
 */
58
public class CharacterMatrixBottomToolbar extends Composite{
59

    
60
    private CharacterMatrix matrix;
61

    
62
    public CharacterMatrixBottomToolbar(CharacterMatrix matrix, int style) {
63
        super(matrix, style);
64
        this.matrix = matrix;
65

    
66
        init();
67
    }
68

    
69
    private void init() {
70

    
71
        setLayout(new RowLayout());
72
        GridDataFactory.fillDefaults().grab(true, false).applyTo(this);
73

    
74
        /**
75
         * Add description button
76
         */
77
        Button btnAddDescription = new Button(this, SWT.PUSH);
78
        btnAddDescription.setImage(ImageResources.getImage(ImageResources.ADD_ICON_GREEN));
79
        btnAddDescription.addSelectionListener(new SelectionAdapter() {
80
            @Override
81
            public void widgetSelected(SelectionEvent e) {
82
                SpecimenSelectionDialog dialog = new SpecimenSelectionDialog(matrix.getShell(), matrix);
83
                if(dialog.open()==Window.OK){
84
                    Collection<SpecimenNodeWrapper> wrappers = dialog.getSpecimen();
85
                    for (SpecimenNodeWrapper wrapper : wrappers) {
86
                        SpecimenOrObservationBase specimen = CdmStore.getService(IOccurrenceService.class).load(wrapper.getUuidAndTitleCache().getUuid());
87
                        SpecimenDescription description = getDescriptionForDescriptiveDataSet(specimen);
88
                        //description elements
89
                        Map<Feature, DescriptionElementBase> featureToElementMap = new HashMap<>();
90
                        Set<DescriptionElementBase> elements = description.getElements();
91
                        for (DescriptionElementBase descriptionElementBase : elements) {
92
                            Feature feature = descriptionElementBase.getFeature();
93
                            featureToElementMap.put(feature, descriptionElementBase);
94
                        }
95
                        RowWrapperDTO rowWrapper = CdmStore.getService(IDescriptiveDataSetService.class).createRowWrapper(description, matrix.getDescriptiveDataSet());
96
                        matrix.getDescriptions().add(rowWrapper);
97
                        matrix.getDescriptiveDataSet().addDescription(description);
98
                        matrix.setDirty();
99
                        matrix.getSpecimenCache().remove(wrapper);
100
                    }
101
                }
102
            }
103
        });
104
        /**
105
         * Remove description button
106
         */
107
        Button btnRemoveDescription = new Button(this, SWT.PUSH);
108
        btnRemoveDescription.setImage(ImageResources.getImage(ImageResources.ACTIVE_DELETE_ICON));
109
        btnRemoveDescription.addSelectionListener(new SelectionAdapter() {
110
            @Override
111
            public void widgetSelected(SelectionEvent e) {
112
                int[] fullySelectedRowPositions = matrix.getBodyLayer().getSelectionLayer().getFullySelectedRowPositions();
113
                List<RowWrapperDTO> toRemove = new ArrayList<>();
114
                for (int i : fullySelectedRowPositions) {
115
                    Object rowObject = matrix.getBodyDataProvider().getRowObject(i);
116
                    if(rowObject instanceof RowWrapperDTO){
117
                        toRemove.add((RowWrapperDTO) rowObject);
118
                    }
119
                }
120
                toRemove.forEach(rowToRemove->{
121
                    matrix.getDescriptions().remove(rowToRemove);
122
                    matrix.getDescriptiveDataSet().removeDescription(rowToRemove.getSpecimenDescription());
123
                    matrix.setDirty();
124
                });
125
            }
126
        });
127
        /**
128
         * Aggregate button
129
         */
130
        Button btnAggregate = new Button(this, SWT.PUSH);
131
        btnAggregate.setText("Aggregate");
132
        btnAggregate.addSelectionListener(new SelectionAdapter() {
133
            @Override
134
            public void widgetSelected(SelectionEvent e) {
135
                Set<TaxonNode> taxonSubtreeFilter = matrix.getDescriptiveDataSet().getTaxonSubtreeFilter();
136
                List<TaxonNodeDto> nodeDtos = taxonSubtreeFilter.stream()
137
                        .map(node -> new TaxonNodeDto(node)).collect(Collectors.toList());
138
                TaxonNodeDto parentDto = CdmStore.getService(ITaxonNodeService.class).findCommonParentDto(nodeDtos);
139
                UUID taxonUuid = parentDto.getTaxonUuid();
140
                int response = MessagingUtils.confirmDialog(
141
                        "Choose location for the aggregated description",
142
                        String.format("The aggregated description will be stored at "
143
                                + "the common parent taxon of this data set:\n%s\n\n"
144
                                + "Do you want to use this taxon?"
145
                                , parentDto.getTaxonTitleCache()), "Yes", "Choose taxon", "Cancel");
146
                if(response==2){
147
                    return;
148
                }
149
                else if(response==1){
150
                    Taxon taxon = TaxonSelectionDialog.selectTaxon(getShell(), null);
151
                    if(taxon==null){
152
                        return;
153
                    }
154
                    taxonUuid = taxon.getUuid();
155
                }
156
                UpdateResult result = CdmStore.getService(IDescriptionService.class).aggregateDescription(taxonUuid, null, matrix.getDescriptiveDataSet().getUuid());
157
                matrix.addUpdateResult(result);
158
                matrix.setDirty();
159

    
160
                //aggregate histogram for categorical tooltip
161
                Map<Feature, CategoricalDataHistogram> featureToHistogramMap = matrix.getFeatureToHistogramMap();
162
                featureToHistogramMap.clear();
163
                aggregateCategorcialHistogram(featureToHistogramMap);
164
            }
165

    
166
        });
167
    }
168

    
169
    @SuppressWarnings("unchecked")
170
    private void aggregateCategorcialHistogram(Map<Feature, CategoricalDataHistogram> featureToHistogramMap) {
171
        matrix.getDescriptions()
172
                .forEach(o -> ((RowWrapperDTO) o).getSpecimenDescription().getElements().stream()
173
                        .filter(descriptionElement -> descriptionElement instanceof CategoricalData)
174
                        .forEach(categoricalData -> {
175
                            Feature feature = ((CategoricalData) categoricalData).getFeature();
176
                            CategoricalDataHistogram dataHistogram = featureToHistogramMap.get(feature);
177
                            if(dataHistogram==null){
178
                                dataHistogram = new CategoricalDataHistogram(feature);
179
                            }
180
                            featureToHistogramMap.put(feature, dataHistogram);
181
                            ((CategoricalData) categoricalData).getStateData()
182
                                    .forEach(stateData -> featureToHistogramMap.get(feature).addState(stateData.getState()));
183
                        }));
184
    }
185

    
186
    private SpecimenDescription getDescriptionForDescriptiveDataSet(SpecimenOrObservationBase specimen){
187
        Set<Feature> wsFeatures = matrix.getDescriptiveDataSet().getDescriptiveSystem().getDistinctFeatures();
188
        List<DescriptionElementBase> matchingDescriptionElements = new ArrayList<>();
189

    
190
        for (SpecimenDescription specimenDescription : (Set<SpecimenDescription>) specimen.getDescriptions()) {
191
            specimenDescription = (SpecimenDescription) CdmStore.getService(IDescriptionService.class).load(specimenDescription.getUuid());
192
            Set<Feature> specimenDescriptionFeatures = new HashSet<>();
193
            //gather specimen description features and check for match with WS features
194
            for (DescriptionElementBase specimenDescriptionElement : specimenDescription.getElements()) {
195
                Feature feature = specimenDescriptionElement.getFeature();
196
                specimenDescriptionFeatures.add(feature);
197
                if(wsFeatures.contains(feature)){
198
                    matchingDescriptionElements.add(specimenDescriptionElement);
199
                }
200
            }
201
            //if description with the exact same features is found return the description
202
            if(specimenDescriptionFeatures.equals(wsFeatures)){
203
                return specimenDescription;
204
            }
205
        }
206
        //Create new specimen description if no match was found
207
        matrix.setDirty();
208
        SpecimenDescription newDesription = SpecimenDescription.NewInstance(specimen);
209
        newDesription.setTitleCache(Messages.CharacterMatrix_DESCRIPTIVE_DATA_SET+matrix.getDescriptiveDataSet().getLabel()+": "+newDesription.generateTitle(), true); //$NON-NLS-2$
210

    
211
        //check for equals description element (same feature and same values)
212
        Map<Feature, List<DescriptionElementBase>> featureToElementMap = new HashMap<>();
213
        for(DescriptionElementBase element:matchingDescriptionElements){
214
            List<DescriptionElementBase> list = featureToElementMap.get(element.getFeature());
215
            if(list==null){
216
                list = new ArrayList<>();
217
            }
218
            list.add(element);
219
            featureToElementMap.put(element.getFeature(), list);
220
        }
221
        Set<DescriptionElementBase> descriptionElementsToClone = new HashSet<>();
222
        for(Feature feature:featureToElementMap.keySet()){
223
            List<DescriptionElementBase> elements = featureToElementMap.get(feature);
224
            //no duplicate description elements found for this feature
225
            if(elements.size()==1){
226
                descriptionElementsToClone.add(elements.get(0));
227
            }
228
            //duplicates found -> check if all are equal
229
            else{
230
                DescriptionElementBase match = null;
231
                for (DescriptionElementBase descriptionElementBase : elements) {
232
                    if(match==null){
233
                        match = descriptionElementBase;
234
                    }
235
                    else if(!new DescriptionElementCompareWrapper(match).equals(new DescriptionElementCompareWrapper(descriptionElementBase))){
236
                        match = null;
237
                        MessagingUtils.informationDialog(Messages.CharacterMatrix_MULTIPLE_DATA,
238
                                String.format(Messages.CharacterMatrix_MULTIPLE_DATA_MESSAGE, feature.getLabel()));
239
                        break;
240
                    }
241
                }
242
                if(match!=null){
243
                    descriptionElementsToClone.add(match);
244
                }
245
            }
246
        }
247
        //clone matching descriptionElements
248
        for (DescriptionElementBase descriptionElementBase : descriptionElementsToClone) {
249
            DescriptionElementBase clone;
250
            try {
251
                clone = descriptionElementBase.clone(newDesription);
252
                clone.getSources().forEach(source -> source.setOriginalNameString(DescriptionHelper.getLabel(descriptionElementBase)));
253
            } catch (CloneNotSupportedException e) {
254
                MessagingUtils.error(CharacterMatrix.class, e);
255
            }
256
        }
257

    
258
        //add all remaining description elements to the new description
259
        for(Feature wsFeature:wsFeatures){
260
            boolean featureFound = false;
261
            for(DescriptionElementBase element:newDesription.getElements()){
262
                if(element.getFeature().equals(wsFeature)){
263
                    featureFound = true;
264
                    break;
265
                }
266
            }
267
            if(!featureFound){
268
                if(wsFeature.isSupportsCategoricalData()){
269
                    newDesription.addElement(CategoricalData.NewInstance(wsFeature));
270
                }
271
                else if(wsFeature.isSupportsQuantitativeData()){
272
                    newDesription.addElement(QuantitativeData.NewInstance(wsFeature));
273
                }
274
            }
275
        }
276
        return newDesription;
277

    
278
    }
279
}
(5-5/18)