Project

General

Profile

Download (15.5 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;
10

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

    
22
import javax.annotation.PostConstruct;
23
import javax.annotation.PreDestroy;
24
import javax.inject.Inject;
25
import javax.inject.Named;
26

    
27
import org.eclipse.core.runtime.IProgressMonitor;
28
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
29
import org.eclipse.e4.core.contexts.IEclipseContext;
30
import org.eclipse.e4.ui.di.Focus;
31
import org.eclipse.e4.ui.di.Persist;
32
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
33
import org.eclipse.e4.ui.services.EMenuService;
34
import org.eclipse.e4.ui.services.IServiceConstants;
35
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
36
import org.eclipse.jface.util.LocalSelectionTransfer;
37
import org.eclipse.jface.viewers.IStructuredSelection;
38
import org.eclipse.jface.viewers.StructuredSelection;
39
import org.eclipse.jface.viewers.Viewer;
40
import org.eclipse.jface.window.Window;
41
import org.eclipse.swt.SWT;
42
import org.eclipse.swt.dnd.DND;
43
import org.eclipse.swt.dnd.Transfer;
44
import org.eclipse.swt.events.FocusAdapter;
45
import org.eclipse.swt.events.FocusEvent;
46
import org.eclipse.swt.events.KeyAdapter;
47
import org.eclipse.swt.events.KeyEvent;
48
import org.eclipse.swt.events.ModifyEvent;
49
import org.eclipse.swt.events.ModifyListener;
50
import org.eclipse.swt.events.SelectionAdapter;
51
import org.eclipse.swt.widgets.Composite;
52
import org.eclipse.swt.widgets.Display;
53
import org.eclipse.swt.widgets.Shell;
54

    
55
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
56
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
57
import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
58
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
59
import eu.etaxonomy.cdm.api.service.ITermService;
60
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
61
import eu.etaxonomy.cdm.model.description.Feature;
62
import eu.etaxonomy.cdm.model.location.NamedArea;
63
import eu.etaxonomy.cdm.model.name.Rank;
64
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
65
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
66
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
67
import eu.etaxonomy.cdm.model.term.TermTree;
68
import eu.etaxonomy.cdm.model.term.TermType;
69
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
70
import eu.etaxonomy.cdm.persistence.dto.TermDto;
71
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
72
import eu.etaxonomy.taxeditor.editor.IDescriptiveDataSetEditor;
73
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
74
import eu.etaxonomy.taxeditor.event.EventUtility;
75
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
76
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
77
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
78
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
79
import eu.etaxonomy.taxeditor.model.MessagingUtils;
80
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
81
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
82
import eu.etaxonomy.taxeditor.store.CdmStore;
83
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
84
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
85

    
86
/**
87
 * Editor for configuring DescriptiveDataSets
88
 * @author pplitzner
89
 * @since Nov 21, 2017
90
 *
91
 */
92
public class DescriptiveDataSetEditor implements IE4SavablePart, IConversationEnabled, ICdmEntitySessionEnabled,
93
IPartContentHasDetails, IPartContentHasSupplementalData, IDirtyMarkable, IDescriptiveDataSetEditor {
94

    
95
    private DescriptiveDataSetComposite composite;
96

    
97
    private ConversationHolder conversation;
98

    
99
    private ICdmEntitySession cdmEntitySession;
100

    
101
    private DescriptiveDataSet descriptiveDataSet;
102

    
103
    private final int dndOperations = DND.DROP_MOVE;
104

    
105
    @Inject
106
    private MDirtyable dirty;
107

    
108
    @Inject
109
    private ESelectionService selectionService;
110

    
111
    private ModifyListener labelModifyListener;
112

    
113
    @PostConstruct
114
    public void create(Composite parent, IEclipseContext context, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell,
115
            EMenuService menuService){
116
        if (CdmStore.isActive()){
117
            if(conversation == null){
118
                conversation = CdmStore.createConversation();
119
            }
120
            if(cdmEntitySession == null){
121
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
122
            }
123
        }
124
        else{
125
            return;
126
        }
127
        CdmFormFactory cdmFormFactory = new CdmFormFactory(Display.getCurrent());
128
        ContextInjectionFactory.inject(cdmFormFactory, context);
129

    
130
        composite = new DescriptiveDataSetComposite(parent, SWT.NONE);
131

    
132
        labelModifyListener = new ModifyListener() {
133
            @Override
134
            public void modifyText(ModifyEvent e) {
135
                descriptiveDataSet.setLabel(composite.getTxt_label().getText());
136
                EventUtility.postSyncEvent(WorkbenchEventConstants.REFRESH_DATASET_NAVIGATOR, descriptiveDataSet);
137
                dirty.setDirty(true);
138
            }
139
        };
140
        composite.getRankMin().addSelectionChangedListener(event->dirty.setDirty(true));
141
        composite.getRankMin().setText("Select min rank...");
142
        composite.getRankMax().addSelectionChangedListener(event->dirty.setDirty(true));
143
        composite.getRankMax().setText("Select max rank...");
144
        composite.getBtnRemoveRankMin().addSelectionListener(new SelectionAdapter() {
145
            @Override
146
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
147
             composite.getRankMin().setElement(null);
148
             dirty.setDirty(true);
149
            }
150
        });
151
        composite.getBtnRemoveRankMax().addSelectionListener(new SelectionAdapter() {
152
            @Override
153
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
154
                composite.getRankMax().setElement(null);
155
                dirty.setDirty(true);
156
            }
157
        });
158

    
159
        composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
160

    
161
            @Override
162
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
163
                AreasSelectionDialog areasSelectionDialog = new AreasSelectionDialog(composite.getShell(), composite.getAreas());
164
                if(areasSelectionDialog.open()==Window.OK){
165
                    List<TermDto> selectedAreas = areasSelectionDialog.getSelectedAreas();
166
                    if(selectedAreas!=null){
167
                        composite.setAreas(selectedAreas);
168
                        dirty.setDirty(true);
169
                    }
170
                }
171
            }
172
        });
173

    
174
        composite.getFeatureTreeEditorComposite().init("Character Tree",
175
                TermType.Character,
176
                null,
177
                null,
178
                e->selectionService.setSelection(e.getSelection()),
179
                this,
180
                null);
181

    
182
        //add drag'n'drop support
183
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
184
        composite.getTaxonNodeTree().addDropSupport(dndOperations, transfers, new TaxonNodeDropAdapter(this));
185

    
186
        composite.getTaxonNodeTree().getTree().addKeyListener(new KeyAdapter() {
187
            @Override
188
            public void keyPressed(KeyEvent e) {
189
                if(e.character==SWT.DEL){
190
                    removeSelectedTaxonNodes();
191
                }
192
            }
193
        });
194

    
195

    
196
        //create context menu
197
        menuService.registerContextMenu(composite.getTaxonNodeTree().getControl(), "eu.etaxonomy.taxeditor.editor.descriptiveDataSet.DescriptiveDataSetEditor.popupmenu.specimeneditor");
198

    
199
    }
200

    
201
    public void init(UUID descriptiveDataSetUuid) {
202
        this.descriptiveDataSet = cdmEntitySession.remoteLoad(CdmStore.getService(IDescriptiveDataSetService.class), descriptiveDataSetUuid);
203
        if(descriptiveDataSet.getLabel()!=null){
204
            composite.getTxt_label().setText(descriptiveDataSet.getLabel());
205
        }
206
        if(descriptiveDataSet.getDescriptiveSystem()!=null){
207
            composite.setCharacters(descriptiveDataSet.getDescriptiveSystem());
208
        }
209
        Rank maxRank = descriptiveDataSet.getMaxRank();
210
        if(maxRank!=null){
211
            composite.setRankMax(maxRank);
212
        }
213
        Rank minRank = descriptiveDataSet.getMinRank();
214
        if(minRank!=null){
215
            composite.setRankMin(minRank);
216
        }
217
        Set<NamedArea> geoFilter = descriptiveDataSet.getGeoFilter();
218
        if(geoFilter!=null && !geoFilter.isEmpty()){
219
            Set<TermDto> terms = geoFilter.stream().map(filter->TermDto.fromTerm(filter, true)).collect(Collectors.toSet());
220
            composite.setAreas(new ArrayList<>(terms));
221
        }
222
        Set<TaxonNode> taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter();
223
        if(taxonSubtreeFilter!=null){
224
            composite.getTaxonNodeTree().setInput(taxonSubtreeFilter);
225
        }
226
        composite.getTxt_label().addModifyListener(labelModifyListener);
227
        composite.getTxt_label().addFocusListener(new FocusAdapter() {
228
            @Override
229
            public void focusGained(FocusEvent e) {
230
                super.focusGained(e);
231
                selectionService.setSelection(new StructuredSelection(descriptiveDataSet));
232
            }
233
        });
234
        selectionService.setSelection(new StructuredSelection(descriptiveDataSet));
235
    }
236

    
237
    public void addTaxonNode(TaxonNodeDto taxonNodeDto){
238
        TaxonNode taxonNode = cdmEntitySession.remoteLoad(CdmStore.getService(ITaxonNodeService.class), taxonNodeDto.getUuid());
239
        //check if node belongs to same classification
240
        Set<TaxonNode> taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter();
241
        if(taxonSubtreeFilter!=null && !taxonSubtreeFilter.isEmpty()){
242
            if(!taxonSubtreeFilter.iterator().next().getClassification().equals(taxonNode.getClassification())){
243
                MessagingUtils.warningDialog(Messages.TaxonNodeDropAdapter_CLASSIFICATIONS_NO_MATCH, this.getClass(),
244
                        Messages.TaxonNodeDropAdapter_CLASSIFICATIONS_NO_MATCH_MESSAGE);
245
                return;
246
            }
247
        }
248
        Viewer taxonTreeViewer = getTaxonTreeViewer();
249
        Object input = taxonTreeViewer.getInput();
250
        Collection<TaxonNode> treeNodes;
251
        if(input==null){
252
            treeNodes = new ArrayList<>();
253
        }
254
        else{
255
            treeNodes = (Collection<TaxonNode>) input;
256
        }
257
        treeNodes.add(taxonNode);
258
        taxonTreeViewer.setInput(treeNodes);
259
        dirty.setDirty(true);
260
    }
261

    
262
    public void removeSelectedTaxonNodes(){
263
        IStructuredSelection selection = (IStructuredSelection) composite.getTaxonNodeTree().getSelection();
264
        if(selection.toList().stream().anyMatch(object->!(object instanceof TaxonNode))){
265
            MessagingUtils.warningDialog(Messages.DescriptiveDataSetEditor_DELETE_FAIL_TITLE, this.getClass(), Messages.DescriptiveDataSetEditor_DELETE_FAIL_MESSAGE);
266
            return;
267
        }
268
        Iterator<Object> iterator = selection.iterator();
269
        Viewer taxonTreeViewer = getTaxonTreeViewer();
270
        Collection<TaxonNode> input = (Collection<TaxonNode>) taxonTreeViewer.getInput();
271
        while(iterator.hasNext()){
272
            Object next = iterator.next();
273
            TaxonNode taxonNode = (TaxonNode) next;
274
            input.remove(taxonNode);
275
            descriptiveDataSet.removeTaxonSubtree(taxonNode);
276
        }
277
        taxonTreeViewer.setInput(input);
278
        dirty.setDirty(true);
279
    }
280

    
281
    @Persist
282
    @Override
283
    public void save(IProgressMonitor monitor) {
284
        Collection<TermDto> areas = composite.getAreas();
285
        Object input = composite.getTaxonNodeTree().getInput();
286
        if(input!=null){
287
            descriptiveDataSet.setTaxonSubtreeFilter(new HashSet<>());//clear existing filter
288
            Collection<ITaxonTreeNode> taxonNodes = (Collection<ITaxonTreeNode>) input;
289
            for (ITaxonTreeNode taxonTreeNode : taxonNodes) {
290
                if(taxonTreeNode instanceof TaxonNode){
291
                    TaxonNode taxonNode = (TaxonNode)taxonTreeNode;
292
                    descriptiveDataSet.addTaxonSubtree(taxonNode);
293
                }
294
            }
295
        }
296
        TermTree<Feature> characters = composite.getCharacters();
297
        if(characters!=null){
298
            //save characters because they can be modified in this editor
299
            characters.getDistinctTerms().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
300
        }
301

    
302

    
303
        DefinedTermBase rankMaxSelection = composite.getRankMax().getSelection();
304
        Rank rankMax = null;
305
        if(rankMaxSelection instanceof Rank){
306
            rankMax = (Rank) rankMaxSelection;
307
        }
308
        DefinedTermBase rankMinSelection = composite.getRankMin().getSelection();
309
        Rank rankMin = null;
310
        if(rankMinSelection instanceof Rank){
311
            rankMin = (Rank) rankMinSelection;
312
        }
313

    
314
        descriptiveDataSet.setMaxRank(rankMax);
315
        descriptiveDataSet.setMinRank(rankMin);
316
        descriptiveDataSet.setDescriptiveSystem(characters);
317
        List<DefinedTermBase> terms = CdmStore.getService(ITermService.class)
318
                .load(areas.stream().map(area -> area.getUuid()).collect(Collectors.toList()), null);
319
        Set<NamedArea> areaTerms = new HashSet<>();
320
        terms.forEach(term->areaTerms.add((NamedArea) term));
321
        descriptiveDataSet.setGeoFilter(areaTerms);
322

    
323
        conversation.commit();
324
        CdmStore.getService(IDescriptiveDataSetService.class).merge(descriptiveDataSet, true);
325
        //event for updatin matrix
326
        EventUtility.postEvent(WorkbenchEventConstants.REFRESH_DESCRIPTIVE_DATASET, descriptiveDataSet.getUuid());
327
        dirty.setDirty(false);
328
    }
329

    
330
    @Override
331
    public boolean isDirty() {
332
        return dirty.isDirty();
333
    }
334

    
335
    @PreDestroy
336
    public void dispose() {
337
        if (conversation != null) {
338
            conversation.close();
339
            conversation = null;
340
        }
341
        if(cdmEntitySession != null) {
342
            cdmEntitySession.dispose();
343
            cdmEntitySession = null;
344
        }
345
        dirty.setDirty(false);
346
        selectionService.setSelection(null);
347
    }
348

    
349
    @Focus
350
    public void setFocus() {
351
        if(composite!=null){
352
            composite.setFocus();
353
        }
354
        if (getConversationHolder() != null) {
355
            getConversationHolder().bind();
356
        }
357
        if(cdmEntitySession != null) {
358
            cdmEntitySession.bind();
359
        }
360
    }
361

    
362
    public Viewer getTaxonTreeViewer() {
363
        return composite.getTaxonNodeTree();
364
    }
365

    
366
    public DescriptiveDataSet getDescriptiveDataSet() {
367
        return descriptiveDataSet;
368
    }
369

    
370
    @Override
371
    public void update(CdmDataChangeMap arg0) {
372
    }
373

    
374
    @Override
375
    public ICdmEntitySession getCdmEntitySession() {
376
        return cdmEntitySession;
377
    }
378

    
379
    @Override
380
    public Collection<DescriptiveDataSet> getRootEntities() {
381
        return Collections.singleton(descriptiveDataSet);
382
    }
383

    
384
    @Override
385
    public Map<Object, List<String>> getPropertyPathsMap() {
386
        return null;
387
    }
388

    
389
    @Override
390
    public ConversationHolder getConversationHolder() {
391
        return conversation;
392
    }
393

    
394
    @Override
395
    public void changed(Object element) {
396
        dirty.setDirty(true);
397
    }
398

    
399
    @Override
400
    public void forceDirty() {
401
        dirty.setDirty(true);
402
    }
403

    
404
}
(3-3/5)