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.model.application.ui.basic.MPart;
34
import org.eclipse.e4.ui.services.EMenuService;
35
import org.eclipse.e4.ui.services.IServiceConstants;
36
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
37
import org.eclipse.jface.util.LocalSelectionTransfer;
38
import org.eclipse.jface.viewers.IStructuredSelection;
39
import org.eclipse.jface.viewers.StructuredSelection;
40
import org.eclipse.jface.viewers.Viewer;
41
import org.eclipse.jface.window.Window;
42
import org.eclipse.swt.SWT;
43
import org.eclipse.swt.dnd.DND;
44
import org.eclipse.swt.dnd.Transfer;
45
import org.eclipse.swt.events.FocusAdapter;
46
import org.eclipse.swt.events.FocusEvent;
47
import org.eclipse.swt.events.KeyAdapter;
48
import org.eclipse.swt.events.KeyEvent;
49
import org.eclipse.swt.events.ModifyEvent;
50
import org.eclipse.swt.events.ModifyListener;
51
import org.eclipse.swt.events.SelectionAdapter;
52
import org.eclipse.swt.widgets.Composite;
53
import org.eclipse.swt.widgets.Display;
54
import org.eclipse.swt.widgets.Shell;
55

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

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

    
94
    private DescriptiveDataSetComposite composite;
95

    
96
    private ICdmEntitySession cdmEntitySession;
97

    
98
    private DescriptiveDataSet descriptiveDataSet;
99

    
100
    private final int dndOperations = DND.DROP_MOVE;
101

    
102
    @Inject
103
    private MDirtyable dirty;
104

    
105
    @Inject
106
    private MPart thisPart;
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(cdmEntitySession == null){
118
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
119
            }
120
        }
121
        else{
122
            return;
123
        }
124
        CdmFormFactory cdmFormFactory = new CdmFormFactory(Display.getCurrent());
125
        ContextInjectionFactory.inject(cdmFormFactory, context);
126

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

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

    
156
        composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
157

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

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

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

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

    
192

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

    
196
    }
197

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

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

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

    
284
    @Persist
285
    @Override
286
    public void save(IProgressMonitor monitor) {
287

    
288
        Collection<TermDto> areas = composite.getAreas();
289
        Object input = composite.getTaxonNodeTree().getInput();
290
        if(input!=null){
291
            descriptiveDataSet.setTaxonSubtreeFilter(new HashSet<>());//clear existing filter
292
            Collection<TaxonNodeDto> taxonNodes = (Collection<TaxonNodeDto>) input;
293
            for (TaxonNodeDto taxonTreeNode : taxonNodes) {
294
                TaxonNode taxonNode =  CdmStore.getService(ITaxonNodeService.class).load(taxonTreeNode.getUuid());
295
                descriptiveDataSet.addTaxonSubtree(taxonNode);
296
            }
297
        }
298
        TermTree<Feature> characters = composite.getCharacters();
299
        if(characters!=null){
300
            //save characters because they can be modified in this editor
301
            characters.getDistinctTerms().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
302
        }
303

    
304

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

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

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

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

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

    
347
    @Focus
348
    public void setFocus() {
349
        if(composite!=null){
350
            composite.setFocus();
351
        }
352

    
353
        if(cdmEntitySession != null) {
354
            cdmEntitySession.bind();
355
        }
356
    }
357

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

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

    
366
    
367

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

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

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

    
383
    @Override
384
    public void changed(Object element) {
385
        dirty.setDirty(true);
386
    }
387

    
388
    @Override
389
    public void forceDirty() {
390
        dirty.setDirty(true);
391
    }
392

    
393
}
(3-3/5)