Project

General

Profile

Download (13.8 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.Viewer;
38
import org.eclipse.swt.SWT;
39
import org.eclipse.swt.dnd.DND;
40
import org.eclipse.swt.dnd.Transfer;
41
import org.eclipse.swt.events.KeyAdapter;
42
import org.eclipse.swt.events.KeyEvent;
43
import org.eclipse.swt.events.ModifyEvent;
44
import org.eclipse.swt.events.ModifyListener;
45
import org.eclipse.swt.events.SelectionAdapter;
46
import org.eclipse.swt.widgets.Composite;
47
import org.eclipse.swt.widgets.Display;
48
import org.eclipse.swt.widgets.Shell;
49

    
50
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
51
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
52
import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
53
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
54
import eu.etaxonomy.cdm.api.service.ITermService;
55
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
56
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
57
import eu.etaxonomy.cdm.model.description.FeatureTree;
58
import eu.etaxonomy.cdm.model.location.NamedArea;
59
import eu.etaxonomy.cdm.model.name.Rank;
60
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
61
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
62
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
63
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
64
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
65
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
66
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
67
import eu.etaxonomy.taxeditor.model.MessagingUtils;
68
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
69
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
70
import eu.etaxonomy.taxeditor.store.CdmStore;
71
import eu.etaxonomy.taxeditor.ui.dialog.selection.NamedAreaSelectionDialog;
72
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
73
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
74

    
75
/**
76
 * Editor for configuring DescriptiveDataSets
77
 * @author pplitzner
78
 * @since Nov 21, 2017
79
 *
80
 */
81
public class DescriptiveDataSetEditor implements IE4SavablePart, IConversationEnabled, ICdmEntitySessionEnabled,
82
IPartContentHasDetails, IDirtyMarkable {
83

    
84
    private DescriptiveDataSetComposite composite;
85

    
86
    private ConversationHolder conversation;
87

    
88
    private ICdmEntitySession cdmEntitySession;
89

    
90
    private DescriptiveDataSet descriptiveDataSet;
91

    
92
    private final int dndOperations = DND.DROP_MOVE;
93

    
94
    @Inject
95
    private MDirtyable dirty;
96

    
97
    @Inject
98
    private ESelectionService selectionService;
99

    
100
    private ModifyListener labelModifyListener;
101

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

    
119
        composite = new DescriptiveDataSetComposite(parent, SWT.NONE);
120

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

    
147
        composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
148

    
149
            @Override
150
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
151
                NamedArea area = NamedAreaSelectionDialog.select(shell, null, null);
152
                if(area!=null){
153
                    composite.setArea(area);
154
                }
155
                dirty.setDirty(true);
156
            }
157
        });
158
        composite.getBtnRemoveArea().addSelectionListener(new SelectionAdapter() {
159

    
160
            @Override
161
            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
162
                composite.removeArea();
163
                dirty.setDirty(true);
164
            }
165
        });
166

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

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

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

    
182

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

    
186
    }
187

    
188
    public void init(UUID descriptiveDataSetUuid) {
189
        this.descriptiveDataSet = cdmEntitySession.remoteLoad(CdmStore.getService(IDescriptiveDataSetService.class), descriptiveDataSetUuid);
190
        if(descriptiveDataSet.getLabel()!=null){
191
            composite.getTxt_label().setText(descriptiveDataSet.getLabel());
192
        }
193
        if(descriptiveDataSet.getDescriptiveSystem()!=null){
194
            composite.setCharacters(descriptiveDataSet.getDescriptiveSystem());
195
        }
196
        Rank maxRank = descriptiveDataSet.getMaxRank();
197
        if(maxRank!=null){
198
            composite.setRankMax(maxRank);
199
        }
200
        Rank minRank = descriptiveDataSet.getMinRank();
201
        if(minRank!=null){
202
            composite.setRankMin(minRank);
203
        }
204
        Set<NamedArea> geoFilter = descriptiveDataSet.getGeoFilter();
205
        if(geoFilter!=null && !geoFilter.isEmpty()){
206
            composite.setArea(geoFilter.iterator().next());
207
        }
208
        Set<TaxonNode> taxonSubtreeFilter = descriptiveDataSet.getTaxonSubtreeFilter();
209
        if(taxonSubtreeFilter!=null){
210
            composite.getTaxonNodeTree().setInput(taxonSubtreeFilter);
211
        }
212

    
213
        composite.getTxt_label().addModifyListener(labelModifyListener);
214
    }
215

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

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

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

    
285

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

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

    
302
        conversation.commit();
303
        CdmStore.getService(IDescriptiveDataSetService.class).merge(descriptiveDataSet, true);
304

    
305
        dirty.setDirty(false);
306
    }
307

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

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

    
334
    public Viewer getTaxonTreeViewer() {
335
        return composite.getTaxonNodeTree();
336
    }
337

    
338
    public DescriptiveDataSet getDescriptiveDataSet() {
339
        return descriptiveDataSet;
340
    }
341

    
342
    @Override
343
    public void update(CdmDataChangeMap arg0) {
344
    }
345

    
346
    @Override
347
    public ICdmEntitySession getCdmEntitySession() {
348
        return cdmEntitySession;
349
    }
350

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

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

    
361
    @Override
362
    public ConversationHolder getConversationHolder() {
363
        return conversation;
364
    }
365

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

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

    
376
}
(2-2/4)