Project

General

Profile

Download (15.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
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.l10n.Messages;
73
import eu.etaxonomy.taxeditor.event.EventUtility;
74
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
75
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
76
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
77
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
78
import eu.etaxonomy.taxeditor.model.MessagingUtils;
79
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
80
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
81
import eu.etaxonomy.taxeditor.store.CdmStore;
82
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
83
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
84

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

    
94
    private DescriptiveDataSetComposite composite;
95

    
96
    private ConversationHolder conversation;
97

    
98
    private ICdmEntitySession cdmEntitySession;
99

    
100
    private DescriptiveDataSet descriptiveDataSet;
101

    
102
    private final int dndOperations = DND.DROP_MOVE;
103

    
104
    @Inject
105
    private MDirtyable dirty;
106

    
107
    @Inject
108
    private ESelectionService selectionService;
109

    
110
    private ModifyListener labelModifyListener;
111

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

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

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

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

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

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

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

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

    
194

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

    
198
    }
199

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

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

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

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

    
301

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

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

    
322
        conversation.commit();
323
        CdmStore.getService(IDescriptiveDataSetService.class).merge(descriptiveDataSet, true);
324

    
325
        dirty.setDirty(false);
326
    }
327

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

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

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

    
359
    public Viewer getTaxonTreeViewer() {
360
        return composite.getTaxonNodeTree();
361
    }
362

    
363
    public DescriptiveDataSet getDescriptiveDataSet() {
364
        return descriptiveDataSet;
365
    }
366

    
367
    @Override
368
    public void update(CdmDataChangeMap arg0) {
369
    }
370

    
371
    @Override
372
    public ICdmEntitySession getCdmEntitySession() {
373
        return cdmEntitySession;
374
    }
375

    
376
    @Override
377
    public Collection<DescriptiveDataSet> getRootEntities() {
378
        return Collections.singleton(descriptiveDataSet);
379
    }
380

    
381
    @Override
382
    public Map<Object, List<String>> getPropertyPathsMap() {
383
        return null;
384
    }
385

    
386
    @Override
387
    public ConversationHolder getConversationHolder() {
388
        return conversation;
389
    }
390

    
391
    @Override
392
    public void changed(Object element) {
393
        dirty.setDirty(true);
394
    }
395

    
396
    @Override
397
    public void forceDirty() {
398
        dirty.setDirty(true);
399
    }
400

    
401
}
(3-3/5)