Project

General

Profile

Download (11.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2017 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.Arrays;
12
import java.util.Collection;
13
import java.util.Collections;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.UUID;
18
import java.util.stream.Collectors;
19

    
20
import javax.annotation.PostConstruct;
21
import javax.annotation.PreDestroy;
22
import javax.inject.Inject;
23

    
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
26
import org.eclipse.e4.core.contexts.IEclipseContext;
27
import org.eclipse.e4.core.services.events.IEventBroker;
28
import org.eclipse.e4.ui.di.Focus;
29
import org.eclipse.e4.ui.di.Persist;
30
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
31
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
32
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
33
import org.eclipse.jface.viewers.IStructuredSelection;
34
import org.eclipse.nebula.widgets.nattable.NatTable;
35
import org.eclipse.swt.SWT;
36
import org.eclipse.swt.custom.StackLayout;
37
import org.eclipse.swt.widgets.Composite;
38
import org.eclipse.swt.widgets.Label;
39

    
40
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
41
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
42
import eu.etaxonomy.cdm.api.service.DeleteResult;
43
import eu.etaxonomy.cdm.api.service.IDescriptionService;
44
import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
45
import eu.etaxonomy.cdm.api.service.UpdateResult;
46
import eu.etaxonomy.cdm.api.service.config.RemoveDescriptionsFromDescriptiveDataSetConfigurator;
47
import eu.etaxonomy.cdm.api.service.dto.DescriptionBaseDto;
48
import eu.etaxonomy.cdm.api.service.dto.RowWrapperDTO;
49
import eu.etaxonomy.cdm.api.service.dto.SpecimenRowWrapperDTO;
50
import eu.etaxonomy.cdm.model.common.CdmBase;
51
import eu.etaxonomy.cdm.model.description.DescriptionBase;
52
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
53
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
54
import eu.etaxonomy.cdm.model.term.TermType;
55
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
56
import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
57
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
58
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
59
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
60
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
61
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
62
import eu.etaxonomy.taxeditor.model.MessagingUtils;
63
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
64
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
65
import eu.etaxonomy.taxeditor.store.CdmStore;
66
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
67

    
68
/**
69
 * Character matrix editor for editing specimen/taxon descriptions in a table
70
 * @author pplitzner
71
 * @since Nov 26, 2017
72
 */
73
public class CharacterMatrixPart implements IE4SavablePart, IConversationEnabled, IDirtyMarkable,
74
		ICdmEntitySessionEnabled<DescriptiveDataSet>, IPartContentHasSupplementalData, 
75
		IPartContentHasDetails {
76

    
77
    private static final List<String> WS_PROPERTY_PATH = Arrays.asList(new String[] {
78
            "descriptions", //$NON-NLS-1$
79
            "descriptions.describedSpecimenOrObservation", //$NON-NLS-1$
80
            "descriptions.describedSpecimenOrObservation.gatheringEvent", //$NON-NLS-1$
81
            "descriptions.describedSpecimenOrObservation.gatheringEvent.actor", //$NON-NLS-1$
82
            "descriptions.descriptionElements", //$NON-NLS-1$
83
            "descriptions.descriptionElements.stateData", //$NON-NLS-1$
84
            "descriptions.descriptionElements.stateData.state", //$NON-NLS-1$
85
            "descriptions.descriptionElements.inDescription", //$NON-NLS-1$
86
            "descriptions.descriptionElements.inDescription.descriptionElements", //$NON-NLS-1$
87
            "descriptions.descriptionElements.feature", //$NON-NLS-1$
88
            "representations", //$NON-NLS-1$
89
            "descriptiveSystem", //$NON-NLS-1$
90
            "taxonSubtreeFilter", //$NON-NLS-1$
91
            "taxonSubtreeFilter.parent", //$NON-NLS-1$
92
            "taxonSubtreeFilter.classification", //$NON-NLS-1$
93
            "taxonSubtreeFilter.taxon", //$NON-NLS-1$
94
            "taxonSubtreeFilter.taxon.name", //$NON-NLS-1$
95
            "taxonSubtreeFilter.taxon.name.rank", //$NON-NLS-1$
96
            "geoFilter", //$NON-NLS-1$
97
            "minRank", //$NON-NLS-1$
98
            "maxRank", //$NON-NLS-1$
99
    });
100

    
101
    private DescriptiveDataSet descriptiveDataSet;
102

    
103
    private ConversationHolder conversation;
104

    
105
    private ICdmEntitySession cdmEntitySession;
106

    
107
    @Inject
108
    private ESelectionService selService;
109

    
110
    @Inject
111
    private MDirtyable dirty;
112

    
113
    @Inject
114
    private MPart thisPart;
115

    
116
    @Inject
117
    private IEventBroker eventBroker;
118

    
119
    private CharacterMatrix matrix;
120

    
121
    private StackLayout stackLayout;
122

    
123
    private Label label;
124

    
125
    @PostConstruct
126
    public void create(Composite parent, IEclipseContext context) {
127
        if(CdmStore.isActive() && conversation==null){
128
            conversation = CdmStore.createConversation();
129
        }
130
        if(cdmEntitySession == null){
131
            cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
132
            cdmEntitySession.bind();
133
        }
134
        else{
135
            return;
136
        }
137
        stackLayout = new StackLayout();
138
        parent.setLayout(stackLayout);
139
        matrix = new CharacterMatrix(parent, this);
140
        label = new Label(parent, SWT.NONE);
141
        label.setText(Messages.CharacterMatrixPart_LOADING_MATRIX);
142
        stackLayout.topControl = label;
143
        ContextInjectionFactory.inject(matrix, context);
144
    }
145

    
146
    public void init(UUID descriptiveDataSetUuid, boolean treeView) {
147
        this.descriptiveDataSet = CdmStore.getService(IDescriptiveDataSetService.class).load(descriptiveDataSetUuid, WS_PROPERTY_PATH);
148
        if(descriptiveDataSet!=null){
149
            if(descriptiveDataSet.getDescriptiveSystem()==null
150
                    || descriptiveDataSet.getDescriptiveSystem().getTermType()==null
151
                    || !descriptiveDataSet.getDescriptiveSystem().getTermType().equals(TermType.Character)){
152
                MessagingUtils.informationDialog(Messages.CharacterMatrixPart_COULD_NOT_OPEN, Messages.CharacterMatrixPart_COULD_NOT_OPEN_MESSAGE);
153
                loadingFailed();
154
                return;
155
            }
156
            try {
157
                matrix.initDescriptiveDataSet();
158
            } catch (IllegalArgumentException e) {
159
                MessagingUtils.errorDialog("Error during initilization", this, "Could not load matrix", TaxeditorEditorPlugin.PLUGIN_ID, e, false);
160
                loadingFailed();
161
                return;
162
            }
163
            matrix.createTable(treeView, true, true);
164
            thisPart.setLabel(descriptiveDataSet.getLabel());
165
            matrix.loadDescriptions( true, true);
166
        }
167
    }
168

    
169
    public IStructuredSelection getSelection(){
170
        return matrix.getSelection();
171
    }
172

    
173
    public void setDirty() {
174
        this.dirty.setDirty(true);
175
    }
176

    
177
    public DescriptiveDataSet getDescriptiveDataSet() {
178
        return descriptiveDataSet;
179
    }
180

    
181
    public void setDescriptiveDataSet(DescriptiveDataSet dataSet) {
182
        this.descriptiveDataSet = dataSet;
183
    }
184

    
185
    public NatTable getNatTable() {
186
        return matrix.getNatTable();
187
    }
188

    
189
    public ESelectionService getSelectionService() {
190
        return selService;
191
    }
192

    
193
    public CharacterMatrix getMatrix() {
194
        return matrix;
195
    }
196

    
197
    @Persist
198
    @Override
199
    public void save(IProgressMonitor monitor) {
200

    
201

    
202
        matrix.addSpecimensToDescriptiveDataSet();
203
        //newly added descriptions should not be saved again.
204
//        descriptions.removeAll(matrix.getRowsToSave().values());
205
        // save edited descriptions
206
        List<DescriptionBaseDto> descriptionsToMerge = matrix.getRowsToMerge().values().stream()
207
                .map(row->row.getDescription())
208
                .collect(Collectors.toList());
209

    
210
        if (matrix.getDescriptionsToDelete() != null && !matrix.getDescriptionsToDelete().isEmpty()){
211
            DeleteResult result = new DeleteResult();
212
            for (RemoveDescriptionsFromDescriptiveDataSetConfigurator config: matrix.getDescriptionsToDelete().keySet()){
213
               result.includeResult(CdmStore.getService(IDescriptiveDataSetService.class).removeDescriptions(matrix.getDescriptionsToDelete().get(config), matrix.getDescriptiveDataSet().getUuid(), config));
214
            }
215
            matrix.getDescriptionsToDelete().clear();
216

    
217
        }
218

    
219
        UpdateResult results = CdmStore.getService(IDescriptionService.class).mergeDescriptions(descriptionsToMerge, matrix.getDescriptiveDataSet().getUuid());
220
        matrix.getRowsToMerge().clear();
221
        conversation.commit();
222
        HashMap<UUID, DescriptionBase> descriptionResults = new HashMap<>();
223
        for (CdmBase result: results.getUpdatedObjects()){
224
            if (result instanceof DescriptionBase){
225
                descriptionResults.put(result.getUuid(), (DescriptionBase)result);
226
            }
227
        }
228
        List<Object> updateRows = matrix.getDescriptions().stream().filter(row->descriptionResults.keySet().contains(((RowWrapperDTO)row).getDescription().getDescription().getUuid())).collect(Collectors.toList());
229
        for (Object updateRow: updateRows){
230
            if (updateRow instanceof SpecimenRowWrapperDTO){
231
                SpecimenRowWrapperDTO dto = (SpecimenRowWrapperDTO)updateRow;
232
                dto.getDescription().setDescription(descriptionResults.get(((SpecimenRowWrapperDTO) updateRow).getDescription().getDescription().getUuid()));
233
            }
234
        }
235
//        matrix.loadDescriptions(getDescriptiveDataSet().getUuid(), false);
236
        eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
237
        dirty.setDirty(false);
238
    }
239

    
240
    @Override
241
    public boolean isDirty() {
242
        return dirty.isDirty();
243
    }
244

    
245
    @Focus
246
    public void setFocus(){
247
        if(conversation!=null){
248
            conversation.bind();
249
        }
250
        if(cdmEntitySession != null) {
251
            cdmEntitySession.bind();
252
        }
253
    }
254

    
255
    @PreDestroy
256
    public void dispose(){
257
        if (conversation != null) {
258
            conversation.close();
259
            conversation = null;
260
        }
261
        if(cdmEntitySession != null) {
262
            cdmEntitySession.dispose();
263
            cdmEntitySession = null;
264
        }
265
        dirty.setDirty(false);
266
    }
267

    
268
    @Override
269
    public void update(CdmDataChangeMap arg0) {
270
    }
271

    
272
    @Override
273
    public ConversationHolder getConversationHolder() {
274
        return conversation;
275
    }
276

    
277
    @Override
278
    public void changed(Object element) {
279
        setDirty();
280
        matrix.getNatTable().refresh();
281
    }
282

    
283
    @Override
284
    public void forceDirty() {
285
        setDirty();
286
    }
287

    
288
    @Override
289
    public ICdmEntitySession getCdmEntitySession() {
290
        return cdmEntitySession;
291
    }
292

    
293
    @Override
294
    public Collection<DescriptiveDataSet> getRootEntities() {
295
        return Collections.singleton(this.descriptiveDataSet);
296
    }
297

    
298
    @Override
299
    public Map<Object, List<String>> getPropertyPathsMap() {
300
        Map<Object, List<String>> propertyMap = new HashMap<>();
301
        propertyMap.put(SpecimenOrObservationBase.class,WS_PROPERTY_PATH);
302
        return propertyMap;
303
    }
304

    
305
    private void loadingFailed() {
306
        label.setText(Messages.CharacterMatrixPart_LOADING_MATRIX_FAILED);
307
    }
308

    
309
    void loadingDone() {
310
        stackLayout.topControl = matrix;
311
        matrix.getParent().layout();
312
    }
313

    
314
}
(9-9/19)