Project

General

Profile

Download (14.2 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

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

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

    
54
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
55
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
56
import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
57
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
58
import eu.etaxonomy.cdm.api.service.ITermService;
59
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
60
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
61
import eu.etaxonomy.cdm.model.description.FeatureTree;
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.persistence.dto.TaxonNodeDto;
67
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
68
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
69
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
70
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
71
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
72
import eu.etaxonomy.taxeditor.model.MessagingUtils;
73
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
74
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
75
import eu.etaxonomy.taxeditor.store.CdmStore;
76
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
77
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
78

    
79
/**
80
 * Editor for configuring DescriptiveDataSets
81
 * @author pplitzner
82
 * @since Nov 21, 2017
83
 *
84
 */
85
public class DescriptiveDataSetEditor implements IE4SavablePart, IConversationEnabled, ICdmEntitySessionEnabled,
86
IPartContentHasDetails, IPartContentHasSupplementalData, IDirtyMarkable {
87

    
88
    private DescriptiveDataSetComposite composite;
89

    
90
    private ConversationHolder conversation;
91

    
92
    private ICdmEntitySession cdmEntitySession;
93

    
94
    private DescriptiveDataSet descriptiveDataSet;
95

    
96
    private final int dndOperations = DND.DROP_MOVE;
97

    
98
    @Inject
99
    private MDirtyable dirty;
100

    
101
    @Inject
102
    private ESelectionService selectionService;
103

    
104
    private ModifyListener labelModifyListener;
105

    
106
    @PostConstruct
107
    public void create(Composite parent, IEclipseContext context, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell,
108
            EMenuService menuService){
109
        if (CdmStore.isActive()){
110
            if(conversation == null){
111
                conversation = CdmStore.createConversation();
112
            }
113
            if(cdmEntitySession == null){
114
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
115
            }
116
        }
117
        else{
118
            return;
119
        }
120
        CdmFormFactory cdmFormFactory = new CdmFormFactory(Display.getCurrent());
121
        ContextInjectionFactory.inject(cdmFormFactory, context);
122

    
123
        composite = new DescriptiveDataSetComposite(parent, SWT.NONE);
124

    
125
        labelModifyListener = new ModifyListener() {
126
            @Override
127
            public void modifyText(ModifyEvent e) {
128
                descriptiveDataSet.setLabel(composite.getTxt_label().getText());
129
                dirty.setDirty(true);
130
            }
131
        };
132
        composite.getRankMin().addSelectionChangedListener(event->dirty.setDirty(true));
133
        composite.getRankMin().setText("Select min rank...");
134
        composite.getRankMax().addSelectionChangedListener(event->dirty.setDirty(true));
135
        composite.getRankMin().setText("Select max rank...");
136
        composite.getBtnRemoveRankMin().addSelectionListener(new SelectionAdapter() {
137
            @Override
138
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
139
             composite.getRankMin().setElement(null);
140
             dirty.setDirty(true);
141
            }
142
        });
143
        composite.getBtnRemoveRankMax().addSelectionListener(new SelectionAdapter() {
144
            @Override
145
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
146
                composite.getRankMax().setElement(null);
147
                dirty.setDirty(true);
148
            }
149
        });
150

    
151
        composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
152

    
153
            @Override
154
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
155
                AreasSelectionDialog areasSelectionDialog = new AreasSelectionDialog(composite.getShell(), composite.getAreas());
156
                if(areasSelectionDialog.open()==Window.OK){
157
                    Set<NamedArea> selectedAreas = areasSelectionDialog.getSelectedAreas();
158
                    if(selectedAreas!=null){
159
                        composite.setAreas(selectedAreas);
160
                        dirty.setDirty(true);
161
                    }
162
                }
163
            }
164
        });
165

    
166
        composite.getFeatureTreeEditorComposite().init("Character Tree", null, null, e->selectionService.setSelection(e.getSelection()), this, null);
167

    
168
        //add drag'n'drop support
169
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
170
        composite.getTaxonNodeTree().addDropSupport(dndOperations, transfers, new TaxonNodeDropAdapter(this));
171

    
172
        composite.getTaxonNodeTree().getTree().addKeyListener(new KeyAdapter() {
173
            @Override
174
            public void keyPressed(KeyEvent e) {
175
                if(e.character==SWT.DEL){
176
                    removeSelectedTaxonNodes();
177
                }
178
            }
179
        });
180

    
181

    
182
        //create context menu
183
        menuService.registerContextMenu(composite.getTaxonNodeTree().getControl(), "eu.etaxonomy.taxeditor.editor.descriptiveDataSet.DescriptiveDataSetEditor.popupmenu.specimeneditor");
184

    
185
    }
186

    
187
    public void init(UUID descriptiveDataSetUuid) {
188
        this.descriptiveDataSet = cdmEntitySession.remoteLoad(CdmStore.getService(IDescriptiveDataSetService.class), descriptiveDataSetUuid);
189
        if(descriptiveDataSet.getLabel()!=null){
190
            composite.getTxt_label().setText(descriptiveDataSet.getLabel());
191
        }
192
        if(descriptiveDataSet.getDescriptiveSystem()!=null){
193
            composite.setCharacters(descriptiveDataSet.getDescriptiveSystem());
194
        }
195
        Rank maxRank = descriptiveDataSet.getMaxRank();
196
        if(maxRank!=null){
197
            composite.setRankMax(maxRank);
198
        }
199
        Rank minRank = descriptiveDataSet.getMinRank();
200
        if(minRank!=null){
201
            composite.setRankMin(minRank);
202
        }
203
        Set<NamedArea> geoFilter = descriptiveDataSet.getGeoFilter();
204
        if(geoFilter!=null && !geoFilter.isEmpty()){
205
            composite.setAreas(geoFilter);
206
        }
207
        Set<TaxonNode> taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter();
208
        if(taxonSubtreeFilter!=null){
209
            composite.getTaxonNodeTree().setInput(taxonSubtreeFilter);
210
        }
211
        composite.getTxt_label().addModifyListener(labelModifyListener);
212
        composite.getTxt_label().addFocusListener(new FocusAdapter() {
213
            @Override
214
            public void focusGained(FocusEvent e) {
215
                super.focusGained(e);
216
                selectionService.setSelection(new StructuredSelection(descriptiveDataSet));
217
            }
218
        });
219
        selectionService.setSelection(new StructuredSelection(descriptiveDataSet));
220
    }
221

    
222
    public void addTaxonNode(TaxonNodeDto taxonNodeDto){
223
        TaxonNode taxonNode = cdmEntitySession.remoteLoad(CdmStore.getService(ITaxonNodeService.class), taxonNodeDto.getUuid());
224
        //check if node belongs to same classification
225
        Set<TaxonNode> taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter();
226
        if(taxonSubtreeFilter!=null && !taxonSubtreeFilter.isEmpty()){
227
            if(!taxonSubtreeFilter.iterator().next().getClassification().equals(taxonNode.getClassification())){
228
                MessagingUtils.warningDialog(Messages.TaxonNodeDropAdapter_CLASSIFICATIONS_NO_MATCH, this.getClass(),
229
                        Messages.TaxonNodeDropAdapter_CLASSIFICATIONS_NO_MATCH_MESSAGE);
230
                return;
231
            }
232
        }
233
        Viewer taxonTreeViewer = getTaxonTreeViewer();
234
        Object input = taxonTreeViewer.getInput();
235
        Collection<TaxonNode> treeNodes;
236
        if(input==null){
237
            treeNodes = new ArrayList<>();
238
        }
239
        else{
240
            treeNodes = (Collection<TaxonNode>) input;
241
        }
242
        treeNodes.add(taxonNode);
243
        taxonTreeViewer.setInput(treeNodes);
244
        dirty.setDirty(true);
245
    }
246

    
247
    public void removeSelectedTaxonNodes(){
248
        IStructuredSelection selection = (IStructuredSelection) composite.getTaxonNodeTree().getSelection();
249
        if(selection.toList().stream().anyMatch(object->!(object instanceof TaxonNode))){
250
            MessagingUtils.warningDialog(Messages.DescriptiveDataSetEditor_DELETE_FAIL_TITLE, this.getClass(), Messages.DescriptiveDataSetEditor_DELETE_FAIL_MESSAGE);
251
            return;
252
        }
253
        Iterator<Object> iterator = selection.iterator();
254
        Viewer taxonTreeViewer = getTaxonTreeViewer();
255
        Collection<TaxonNode> input = (Collection<TaxonNode>) taxonTreeViewer.getInput();
256
        while(iterator.hasNext()){
257
            Object next = iterator.next();
258
            TaxonNode taxonNode = (TaxonNode) next;
259
            input.remove(taxonNode);
260
            descriptiveDataSet.removeTaxonSubtree(taxonNode);
261
        }
262
        taxonTreeViewer.setInput(input);
263
        dirty.setDirty(true);
264
    }
265

    
266
    @Persist
267
    @Override
268
    public void save(IProgressMonitor monitor) {
269
        Set<NamedArea> areas = composite.getAreas();
270
        Object input = composite.getTaxonNodeTree().getInput();
271
        if(input!=null){
272
            descriptiveDataSet.setTaxonSubtreeFilter(new HashSet<>());//clear existing filter
273
            Collection<ITaxonTreeNode> taxonNodes = (Collection<ITaxonTreeNode>) input;
274
            for (ITaxonTreeNode taxonTreeNode : taxonNodes) {
275
                if(taxonTreeNode instanceof TaxonNode){
276
                    TaxonNode taxonNode = (TaxonNode)taxonTreeNode;
277
                    descriptiveDataSet.addTaxonSubtree(taxonNode);
278
                }
279
            }
280
        }
281
        FeatureTree characters = composite.getCharacters();
282
        if(characters!=null){
283
            //save characters because they can be modified in this editor
284
            characters.getDistinctFeatures().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
285
        }
286

    
287

    
288
        DefinedTermBase rankMaxSelection = composite.getRankMax().getSelection();
289
        Rank rankMax = null;
290
        if(rankMaxSelection instanceof Rank){
291
            rankMax = (Rank) rankMaxSelection;
292
        }
293
        DefinedTermBase rankMinSelection = composite.getRankMin().getSelection();
294
        Rank rankMin = null;
295
        if(rankMinSelection instanceof Rank){
296
            rankMin = (Rank) rankMinSelection;
297
        }
298

    
299
        descriptiveDataSet.setMaxRank(rankMax);
300
        descriptiveDataSet.setMinRank(rankMin);
301
        descriptiveDataSet.setDescriptiveSystem(characters);
302
        descriptiveDataSet.setGeoFilter(areas);
303

    
304
        conversation.commit();
305
        CdmStore.getService(IDescriptiveDataSetService.class).merge(descriptiveDataSet, true);
306

    
307
        dirty.setDirty(false);
308
    }
309

    
310
    @PreDestroy
311
    public void dispose() {
312
        if (conversation != null) {
313
            conversation.close();
314
            conversation = null;
315
        }
316
        if(cdmEntitySession != null) {
317
            cdmEntitySession.dispose();
318
            cdmEntitySession = null;
319
        }
320
        dirty.setDirty(false);
321
    }
322

    
323
    @Focus
324
    public void setFocus() {
325
        if(composite!=null){
326
            composite.setFocus();
327
        }
328
        if (getConversationHolder() != null) {
329
            getConversationHolder().bind();
330
        }
331
        if(cdmEntitySession != null) {
332
            cdmEntitySession.bind();
333
        }
334
    }
335

    
336
    public Viewer getTaxonTreeViewer() {
337
        return composite.getTaxonNodeTree();
338
    }
339

    
340
    public DescriptiveDataSet getDescriptiveDataSet() {
341
        return descriptiveDataSet;
342
    }
343

    
344
    @Override
345
    public void update(CdmDataChangeMap arg0) {
346
    }
347

    
348
    @Override
349
    public ICdmEntitySession getCdmEntitySession() {
350
        return cdmEntitySession;
351
    }
352

    
353
    @Override
354
    public Collection<DescriptiveDataSet> getRootEntities() {
355
        return Collections.singleton(descriptiveDataSet);
356
    }
357

    
358
    @Override
359
    public Map<Object, List<String>> getPropertyPathsMap() {
360
        return null;
361
    }
362

    
363
    @Override
364
    public ConversationHolder getConversationHolder() {
365
        return conversation;
366
    }
367

    
368
    @Override
369
    public void changed(Object element) {
370
        dirty.setDirty(true);
371
    }
372

    
373
    @Override
374
    public void forceDirty() {
375
        dirty.setDirty(true);
376
    }
377

    
378
}
(3-3/5)