Project

General

Profile

Download (16.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2007 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

    
10
package eu.etaxonomy.taxeditor.featuretree.e4;
11

    
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.UUID;
18

    
19
import javax.annotation.PostConstruct;
20
import javax.annotation.PreDestroy;
21
import javax.inject.Inject;
22

    
23
import org.eclipse.core.runtime.IProgressMonitor;
24
import org.eclipse.e4.core.di.annotations.Optional;
25
import org.eclipse.e4.ui.di.Focus;
26
import org.eclipse.e4.ui.di.Persist;
27
import org.eclipse.e4.ui.di.UIEventTopic;
28
import org.eclipse.e4.ui.di.UISynchronize;
29
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
30
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
31
import org.eclipse.e4.ui.services.EMenuService;
32
import org.eclipse.e4.ui.workbench.modeling.EPartService;
33
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
34
import org.eclipse.jface.util.LocalSelectionTransfer;
35
import org.eclipse.jface.viewers.ISelection;
36
import org.eclipse.jface.viewers.ISelectionChangedListener;
37
import org.eclipse.jface.viewers.IStructuredSelection;
38
import org.eclipse.jface.viewers.SelectionChangedEvent;
39
import org.eclipse.jface.viewers.StructuredSelection;
40
import org.eclipse.jface.viewers.TreeViewer;
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.KeyAdapter;
45
import org.eclipse.swt.events.KeyEvent;
46
import org.eclipse.swt.layout.FillLayout;
47
import org.eclipse.swt.widgets.Composite;
48
import org.eclipse.ui.IMemento;
49

    
50
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
51
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
52
import eu.etaxonomy.cdm.api.service.ITermNodeService;
53
import eu.etaxonomy.cdm.api.service.ITermTreeService;
54
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
55
import eu.etaxonomy.cdm.model.term.TermNode;
56
import eu.etaxonomy.cdm.model.term.TermType;
57
import eu.etaxonomy.cdm.persistence.dto.TermDto;
58
import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
59
import eu.etaxonomy.cdm.persistence.dto.TermTreeDto;
60
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
61
import eu.etaxonomy.taxeditor.editor.definedterm.FeatureTreeViewerComparator;
62
import eu.etaxonomy.taxeditor.editor.definedterm.TermTransfer;
63
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
64
import eu.etaxonomy.taxeditor.featuretree.FeatureNodeDtoTransfer;
65
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
66
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
67
import eu.etaxonomy.taxeditor.featuretree.e4.operation.AddFeatureOperation;
68
import eu.etaxonomy.taxeditor.model.AbstractUtility;
69
import eu.etaxonomy.taxeditor.model.IContextListener;
70
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
71
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
72
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
73
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
74
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
75
import eu.etaxonomy.taxeditor.store.AppModelId;
76
import eu.etaxonomy.taxeditor.store.CdmStore;
77
import eu.etaxonomy.taxeditor.store.StoreUtil;
78
import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
79

    
80
/**
81
 *
82
 * @author pplitzner
83
 * @date 06.06.2017
84
 *
85
 */
86
public class TermTreeEditor<T extends DefinedTermBase> implements IFeatureTreeEditor, ISelectionChangedListener,
87
        IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData,
88
        IContextListener, IConversationEnabled, IDirtyMarkable {
89

    
90
    public static final List<String> TREE_PROPERTY_PATH = Arrays.asList(new String[] {
91
            "root", //$NON-NLS-1$
92
            "root.children", //$NON-NLS-1$
93
            "root.children.inapplicableIf", //$NON-NLS-1$
94
            "root.children.inapplicableIf.feature", //$NON-NLS-1$
95
            "root.children.inapplicableIf.state", //$NON-NLS-1$
96
            "root.children.onlyApplicableIf", //$NON-NLS-1$
97
            "root.children.onlyApplicableIf.feature", //$NON-NLS-1$
98
            "root.children.onlyApplicableIf.state", //$NON-NLS-1$
99
    });
100

    
101
    private ConversationHolder conversation;
102

    
103
    private ICdmEntitySession cdmEntitySession;
104

    
105
    @Inject
106
    private ESelectionService selService;
107

    
108
    @Inject
109
    private MDirtyable dirty;
110

    
111
    @Inject
112
    private UISynchronize sync;
113

    
114
    @Inject
115
    private MPart thisPart;
116

    
117
    private TreeViewer viewer;
118

    
119
    Map<UUID,TermTreeDto> trees;
120

    
121
    Map<UUID, TermNodeDto> uuidTermMap = new HashMap<>();
122
    List<AbstractPostOperation<TermNode>> operationList = new ArrayList<>();
123
    List<TermNodeDto> listToUpdate = new ArrayList<>();
124

    
125
    TermType termType;
126

    
127
    @Inject
128
    public TermTreeEditor() {
129
        CdmStore.getContextManager().addContextListener(this);
130
    }
131

    
132
    @PostConstruct
133
    public void createControl(Composite parent, EMenuService menuService){
134
        if (CdmStore.isActive()){
135
            initSession();
136
        }
137
        else{
138
            return;
139
        }
140
        parent.setLayout(new FillLayout());
141
        viewer = new TreeViewer(parent);
142
        FeatureTreeContentProvider contentProvider = new FeatureTreeContentProvider();
143

    
144
        viewer.setContentProvider(contentProvider);
145
        viewer.setLabelProvider(new FeatureTreeLabelProvider());
146

    
147
        int ops = DND.DROP_COPY | DND.DROP_MOVE;
148
        Transfer[] transfers = new Transfer[] {
149
                FeatureNodeDtoTransfer.getInstance(),
150
                TermTransfer.getInstance(),
151
                LocalSelectionTransfer.getTransfer()};
152
        viewer.addDragSupport(ops, transfers, new FeatureNodeDtoDragListener(viewer));
153
        viewer.addDropSupport(ops, transfers, new FeatureTreeDtoDropAdapter(this, viewer, sync));
154
        viewer.addSelectionChangedListener(this);
155
        viewer.getTree().addKeyListener(new KeyAdapter() {
156
            @Override
157
            public void keyPressed(KeyEvent e) {
158
                if(e.stateMask == SWT.MOD1 && e.keyCode == 'c'){
159
                    copy(viewer.getStructuredSelection());
160
                }
161
                else if(e.stateMask == SWT.MOD1 && e.keyCode == 'v'){
162
                    paste(viewer.getStructuredSelection());
163
                }
164
            }
165
        });
166

    
167
        updateTrees();
168
        viewer.setComparator(new FeatureTreeViewerComparator());
169
        viewer.setInput(getTrees());
170
        contentProvider.setUuidTermMap(uuidTermMap);
171
        //create context menu
172
        menuService.registerContextMenu(viewer.getControl(), AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_STORE_POPUPMENU_FEATURETREEEDITOR);
173
    }
174

    
175
    public void init(TermType type, String label){
176
        this.termType = type;
177
        updateTrees();
178
        viewer.setComparator(new FeatureTreeViewerComparator());
179
        viewer.setInput(getTrees());
180
        ((FeatureTreeContentProvider)viewer.getContentProvider()).setUuidTermMap(uuidTermMap);
181
        thisPart.setLabel(label);
182
    }
183

    
184
//    protected abstract List<TermTreeDto> getTrees();
185

    
186
    public void paste(IStructuredSelection selection) {
187
        if (StoreUtil.promptCheckIsDirty(this)) {
188
            return;
189
        }
190

    
191
        ISelection clipBoardSelection = LocalSelectionTransfer.getTransfer().getSelection();
192
        Object firstElement = selection.getFirstElement();
193
        TermNodeDto parentNode = null;
194
        if(firstElement instanceof TermNodeDto){
195
            parentNode = (TermNodeDto) firstElement;
196
        }
197
        else if(firstElement instanceof TermTreeDto){
198
            parentNode = ((TermTreeDto)firstElement).getRoot();
199
        }
200
        if(parentNode!=null){
201
        	TermNodeDto copiedNode = (TermNodeDto) ((IStructuredSelection)clipBoardSelection).getFirstElement();
202

    
203
            AddFeatureOperation operation = new AddFeatureOperation(copiedNode.getUuid(), parentNode, this, this);
204
//            AbstractUtility.executeOperation(operation, sync);
205
            this.addOperation(operation);
206
        }
207

    
208
    }
209

    
210
    public void copy(IStructuredSelection selection) {
211
        LocalSelectionTransfer.getTransfer().setSelection(selection);
212
    }
213

    
214
    private void initSession(){
215
        if(conversation == null){
216
            conversation = CdmStore.createConversation();
217
        }
218
        if(cdmEntitySession==null){
219
            cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
220
        }
221
    }
222

    
223
    private void clearSession() {
224
        if(conversation!=null){
225
            conversation.close();
226
            conversation = null;
227
        }
228
        if(cdmEntitySession != null) {
229
            cdmEntitySession.dispose();
230
            cdmEntitySession = null;
231
        }
232
        dirty.setDirty(false);
233
    }
234

    
235
	public void setDirty(boolean isDirty){
236
	    this.dirty.setDirty(isDirty);
237
	}
238
	@Override
239
    public void setDirty(){
240
        this.dirty.setDirty(true);
241
    }
242

    
243
	@Override
244
    public boolean isDirty(){
245
	    return dirty.isDirty();
246
	}
247

    
248
	@Override
249
	public void selectionChanged(SelectionChangedEvent event) {
250
		//propagate selection
251
		selService.setSelection(event.getSelection());
252
	}
253

    
254
	@Focus
255
	public void focus(){
256
	    if(viewer!=null){
257
	        viewer.getControl().setFocus();
258
	    }
259
        if(conversation!=null && !conversation.isBound()){
260
            conversation.bind();
261
        }
262
        if(cdmEntitySession != null) {
263
            cdmEntitySession.bind();
264
        }
265
	}
266

    
267
	@Override
268
    public void refresh(){
269
	    viewer.refresh();
270
	}
271

    
272
	@Override
273
    public TreeViewer getViewer(){
274
	    return viewer;
275
	}
276

    
277
	@Override
278
	public IStructuredSelection getSelection() {
279
	    return (IStructuredSelection) viewer.getSelection();
280
	}
281

    
282
	@Override
283
	public ConversationHolder getConversationHolder() {
284
	    return conversation;
285
	}
286

    
287
	@Override
288
    @Persist
289
	public void save(IProgressMonitor monitor){
290
        if (!conversation.isBound()) {
291
            conversation.bind();
292
        }
293

    
294
        // commit the conversation and start a new transaction immediately
295
        Object[] expandedElements = this.viewer.getExpandedElements();
296
        conversation.commit(true);
297
        if (operationList != null && !operationList.isEmpty()){
298
            for (AbstractPostOperation<TermNode> operation: operationList){
299
                AbstractUtility.executeOperation(operation, sync);
300
            }
301
            operationList.clear();
302
        }
303

    
304
        CdmStore.getService(ITermNodeService.class).saveTermNodeDtoList(listToUpdate);
305
        listToUpdate.clear();
306
        List<TermTreeDto> rootEntities = getRootEntities();
307
        CdmStore.getService(ITermTreeService.class).saveOrUpdateTermTreeDtoList(rootEntities);
308
        initializeTrees();
309
        conversation.commit(true);
310

    
311
        this.setDirty(false);
312
//        this.viewer.setExpandedElements(expandedElements);
313
	}
314

    
315
    private void initializeTrees() {
316
        Object[] expandedElements = viewer.getExpandedElements();
317
        viewer.getTree().removeAll();
318
        updateTrees();
319
        viewer.setInput(getTrees());
320
        viewer.setExpandedElements(expandedElements);
321

    
322
    }
323

    
324
	@PreDestroy
325
	public void dispose(){
326
	    selService.setSelection(null);
327
	    clearSession();
328
	}
329

    
330
    @Override
331
    public ICdmEntitySession getCdmEntitySession() {
332
        return cdmEntitySession;
333
    }
334

    
335
    @Override
336
    public Map<Object, List<String>> getPropertyPathsMap() {
337
        List<String> propertyPaths = Arrays.asList(new String[] {
338
                "children", //$NON-NLS-1$
339
                "feature", //$NON-NLS-1$
340
                "featureTree", //$NON-NLS-1$
341
        });
342
        Map<Object, List<String>> propertyPathMap =
343
                new HashMap<Object, List<String>>();
344
        propertyPathMap.put(TermNode.class,propertyPaths);
345
        return propertyPathMap;
346
    }
347

    
348
    @Override
349
    public List<TermTreeDto> getRootEntities() {
350
        return (List<TermTreeDto>) viewer.getInput();
351
    }
352

    
353
    @Override
354
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
355
    }
356

    
357
    @Override
358
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
359
        //close view when workbench closes
360
        try{
361
            thisPart.getContext().get(EPartService.class).hidePart(thisPart);
362
        }
363
        catch(Exception e){
364
            //nothing
365
        }
366
    }
367

    
368
    @Override
369
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
370
    }
371

    
372
    @Override
373
    public void contextRefresh(IProgressMonitor monitor) {
374
    }
375

    
376
    @Override
377
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
378
    }
379

    
380
    @Override
381
    public void update(CdmDataChangeMap arg0) {
382
    }
383

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

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

    
395
    @Override
396
    public boolean postOperation(Object objectAffectedByOperation) {
397
        initializeTrees();
398
        viewer.refresh();
399
        if(objectAffectedByOperation instanceof TermNodeDto){
400
        	TermNodeDto node = (TermNodeDto)objectAffectedByOperation;
401
//            viewer.expandToLevel(((TermRelationBase) node).getGraph(), 1); find a solution for dto editor
402
        }
403
        if(objectAffectedByOperation!=null){
404
            StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
405
            viewer.setSelection(selection);
406
        }
407
        return true;
408
    }
409

    
410
    @Override
411
    public boolean onComplete() {
412
        return false;
413
    }
414

    
415
    @Override
416
    public TermNodeDto getNodeDtoForUuid(UUID nodeUuid){
417
        return uuidTermMap.get(nodeUuid);
418
    }
419

    
420
    protected void addAllNodesToMap(TermNodeDto root){
421
        if (!uuidTermMap.containsKey(root.getUuid())){
422
            uuidTermMap.put(root.getUuid(), root);
423
            if (root.getTerm() != null){
424
                getTreeDtoForUuid(root.getTree().getUuid()).addTerm(root.getTerm());
425
            }
426
        }
427
        for (TermNodeDto child: root.getChildren()){
428
            uuidTermMap.put(child.getUuid(), child);
429
            if (child.getTerm() != null){
430
                getTreeDtoForUuid(child.getTree().getUuid()).addTerm(child.getTerm());
431
            }
432
            if (child.getChildren() != null && !child.getChildren().isEmpty()){
433
                addAllNodesToMap(child);
434
            }
435
        }
436
    }
437

    
438
    /**
439
     * @param term
440
     * @param treeUuid
441
     */
442
    @Override
443
    public boolean checkDuplicates(UUID termUuid, UUID treeUuid) {
444
        TermTreeDto tree = this.getTreeDtoForUuid(treeUuid);
445
        for (TermDto dto: tree.getTerms()){
446
            if (dto.getUuid().equals(termUuid)) {
447
                return true;
448
            }
449
        }
450
        return false;
451
    }
452

    
453
    protected void updateTrees(){
454
        uuidTermMap.clear();
455
        if (trees != null && !trees.isEmpty()){
456
            trees.clear();
457
        }
458
        if (trees == null){
459
            trees = new HashMap<>();
460
        }
461
        List<TermTreeDto> treeList = CdmStore.getService(ITermTreeService.class).listTermTreeDtosByTermType(getTermType());
462
        treeList.stream().forEach(tree -> trees.put(tree.getUuid(), tree));
463
//        trees.addAll(CdmStore.getService(ITermTreeService.class).listTermTreeDtosByTermType(getTermType()));
464
        for (TermTreeDto tree: trees.values()){
465
            addAllNodesToMap(tree.getRoot());
466
        }
467
        ((FeatureTreeContentProvider<T>)viewer.getContentProvider()).setUuidTermMap(uuidTermMap);
468
//        viewer.refresh();
469

    
470
    }
471

    
472
    public List<TermTreeDto> getTrees(){
473
        List<TermTreeDto> treeList = new ArrayList<>(trees.values());
474
        return treeList;
475
    }
476

    
477
    public void putTree(TermTreeDto tree){
478
       trees.put(tree.getUuid(), tree);
479

    
480
    }
481

    
482
    public void removeTree(TermTreeDto tree){
483
        trees.remove(tree.getUuid());
484

    
485
     }
486

    
487
    @Override
488
    public TermTreeDto getTreeDtoForUuid(UUID treeUuid){
489
        return trees.get(treeUuid);
490
    }
491

    
492
    @Override
493
    public void setTreeDtoForUuid(TermTreeDto tree){
494
        trees.put(tree.getUuid(), tree);
495
    }
496

    
497
    @Override
498
    public void setNodeDtoForUuid(TermNodeDto node){
499
        this.uuidTermMap.put(node.getUuid(), node);
500
    }
501

    
502
    @Override
503
    public void addOperation(AbstractPostOperation operation) {
504
        operationList.add(operation);
505
    }
506

    
507
    @Inject
508
    @Optional
509
    private void addSaveCandidate(@UIEventTopic(WorkbenchEventConstants.ADD_SAVE_CANDIDATE) UUID cdmbaseUuid) {
510
        for (UUID uuid: uuidTermMap.keySet()) {
511
            if (uuid.equals(cdmbaseUuid)){
512
                listToUpdate.add(uuidTermMap.get(uuid));
513
            }
514

    
515
        }
516
    }
517

    
518
    @Override
519
    public TermType getTermType() {
520
        return termType;
521
    }
522

    
523

    
524
}
(9-9/9)