Project

General

Profile

Download (14.9 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.common.DefinedTermBase;
61
import eu.etaxonomy.cdm.model.common.TermType;
62
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
63
import eu.etaxonomy.cdm.model.description.FeatureTree;
64
import eu.etaxonomy.cdm.model.location.NamedArea;
65
import eu.etaxonomy.cdm.model.name.Rank;
66
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
67
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
68
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
69
import eu.etaxonomy.cdm.persistence.dto.TermDto;
70
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
71
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
72
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
73
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
74
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
75
import eu.etaxonomy.taxeditor.model.MessagingUtils;
76
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
77
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
78
import eu.etaxonomy.taxeditor.store.CdmStore;
79
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
80
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
81

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

    
91
    private DescriptiveDataSetComposite composite;
92

    
93
    private ConversationHolder conversation;
94

    
95
    private ICdmEntitySession cdmEntitySession;
96

    
97
    private DescriptiveDataSet descriptiveDataSet;
98

    
99
    private final int dndOperations = DND.DROP_MOVE;
100

    
101
    @Inject
102
    private MDirtyable dirty;
103

    
104
    @Inject
105
    private ESelectionService selectionService;
106

    
107
    private ModifyListener labelModifyListener;
108

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

    
126
        composite = new DescriptiveDataSetComposite(parent, SWT.NONE);
127

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

    
154
        composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
155

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

    
169
        composite.getFeatureTreeEditorComposite().init("Character Tree",
170
                TermType.Character,
171
                null,
172
                null,
173
                e->selectionService.setSelection(e.getSelection()),
174
                this,
175
                null);
176

    
177
        //add drag'n'drop support
178
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
179
        composite.getTaxonNodeTree().addDropSupport(dndOperations, transfers, new TaxonNodeDropAdapter(this));
180

    
181
        composite.getTaxonNodeTree().getTree().addKeyListener(new KeyAdapter() {
182
            @Override
183
            public void keyPressed(KeyEvent e) {
184
                if(e.character==SWT.DEL){
185
                    removeSelectedTaxonNodes();
186
                }
187
            }
188
        });
189

    
190

    
191
        //create context menu
192
        menuService.registerContextMenu(composite.getTaxonNodeTree().getControl(), "eu.etaxonomy.taxeditor.editor.descriptiveDataSet.DescriptiveDataSetEditor.popupmenu.specimeneditor");
193

    
194
    }
195

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

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

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

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

    
297

    
298
        DefinedTermBase rankMaxSelection = composite.getRankMax().getSelection();
299
        Rank rankMax = null;
300
        if(rankMaxSelection instanceof Rank){
301
            rankMax = (Rank) rankMaxSelection;
302
        }
303
        DefinedTermBase rankMinSelection = composite.getRankMin().getSelection();
304
        Rank rankMin = null;
305
        if(rankMinSelection instanceof Rank){
306
            rankMin = (Rank) rankMinSelection;
307
        }
308

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

    
318
        conversation.commit();
319
        CdmStore.getService(IDescriptiveDataSetService.class).merge(descriptiveDataSet, true);
320

    
321
        dirty.setDirty(false);
322
    }
323

    
324
    @Override
325
    public boolean isDirty() {
326
        return dirty.isDirty();
327
    }
328

    
329
    @PreDestroy
330
    public void dispose() {
331
        if (conversation != null) {
332
            conversation.close();
333
            conversation = null;
334
        }
335
        if(cdmEntitySession != null) {
336
            cdmEntitySession.dispose();
337
            cdmEntitySession = null;
338
        }
339
        dirty.setDirty(false);
340
    }
341

    
342
    @Focus
343
    public void setFocus() {
344
        if(composite!=null){
345
            composite.setFocus();
346
        }
347
        if (getConversationHolder() != null) {
348
            getConversationHolder().bind();
349
        }
350
        if(cdmEntitySession != null) {
351
            cdmEntitySession.bind();
352
        }
353
    }
354

    
355
    public Viewer getTaxonTreeViewer() {
356
        return composite.getTaxonNodeTree();
357
    }
358

    
359
    public DescriptiveDataSet getDescriptiveDataSet() {
360
        return descriptiveDataSet;
361
    }
362

    
363
    @Override
364
    public void update(CdmDataChangeMap arg0) {
365
    }
366

    
367
    @Override
368
    public ICdmEntitySession getCdmEntitySession() {
369
        return cdmEntitySession;
370
    }
371

    
372
    @Override
373
    public Collection<DescriptiveDataSet> getRootEntities() {
374
        return Collections.singleton(descriptiveDataSet);
375
    }
376

    
377
    @Override
378
    public Map<Object, List<String>> getPropertyPathsMap() {
379
        return null;
380
    }
381

    
382
    @Override
383
    public ConversationHolder getConversationHolder() {
384
        return conversation;
385
    }
386

    
387
    @Override
388
    public void changed(Object element) {
389
        dirty.setDirty(true);
390
    }
391

    
392
    @Override
393
    public void forceDirty() {
394
        dirty.setDirty(true);
395
    }
396

    
397
}
(3-3/5)