Project

General

Profile

Download (16 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.persistence.dto.TermDto;
57
import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
58
import eu.etaxonomy.cdm.persistence.dto.TermTreeDto;
59
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
60
import eu.etaxonomy.taxeditor.editor.definedterm.FeatureTreeViewerComparator;
61
import eu.etaxonomy.taxeditor.editor.definedterm.TermTransfer;
62
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
63
import eu.etaxonomy.taxeditor.featuretree.FeatureNodeDtoTransfer;
64
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
65
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
66
import eu.etaxonomy.taxeditor.featuretree.e4.operation.AddFeatureOperation;
67
import eu.etaxonomy.taxeditor.model.AbstractUtility;
68
import eu.etaxonomy.taxeditor.model.IContextListener;
69
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
70
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
71
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
72
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
73
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
74
import eu.etaxonomy.taxeditor.store.AppModelId;
75
import eu.etaxonomy.taxeditor.store.CdmStore;
76
import eu.etaxonomy.taxeditor.store.StoreUtil;
77
import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
78

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

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

    
100
    private ConversationHolder conversation;
101

    
102
    private ICdmEntitySession cdmEntitySession;
103

    
104
    @Inject
105
    private ESelectionService selService;
106

    
107
    @Inject
108
    private MDirtyable dirty;
109

    
110
    @Inject
111
    private UISynchronize sync;
112

    
113
    @Inject
114
    private MPart thisPart;
115

    
116
    private TreeViewer viewer;
117

    
118
    Map<UUID,TermTreeDto> trees;
119

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

    
124
    @Inject
125
    public AbstractTermTreeEditor() {
126
        CdmStore.getContextManager().addContextListener(this);
127
    }
128

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

    
141
        viewer.setContentProvider(contentProvider);
142
        viewer.setLabelProvider(new FeatureTreeLabelProvider());
143

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

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

    
172
//    protected abstract List<TermTreeDto> getTrees();
173

    
174
    public void paste(IStructuredSelection selection) {
175
        if (StoreUtil.promptCheckIsDirty(this)) {
176
            return;
177
        }
178

    
179
        ISelection clipBoardSelection = LocalSelectionTransfer.getTransfer().getSelection();
180
        Object firstElement = selection.getFirstElement();
181
        TermNodeDto parentNode = null;
182
        if(firstElement instanceof TermNodeDto){
183
            parentNode = (TermNodeDto) firstElement;
184
        }
185
        else if(firstElement instanceof TermTreeDto){
186
            parentNode = ((TermTreeDto)firstElement).getRoot();
187
        }
188
        if(parentNode!=null){
189
        	TermNodeDto copiedNode = (TermNodeDto) ((IStructuredSelection)clipBoardSelection).getFirstElement();
190

    
191
            AddFeatureOperation operation = new AddFeatureOperation(copiedNode.getUuid(), parentNode, this, this);
192
//            AbstractUtility.executeOperation(operation, sync);
193
            this.addOperation(operation);
194
        }
195

    
196
    }
197

    
198
    public void copy(IStructuredSelection selection) {
199
        LocalSelectionTransfer.getTransfer().setSelection(selection);
200
    }
201

    
202
    private void initSession(){
203
        if(conversation == null){
204
            conversation = CdmStore.createConversation();
205
        }
206
        if(cdmEntitySession==null){
207
            cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
208
        }
209
    }
210

    
211
    private void clearSession() {
212
        if(conversation!=null){
213
            conversation.close();
214
            conversation = null;
215
        }
216
        if(cdmEntitySession != null) {
217
            cdmEntitySession.dispose();
218
            cdmEntitySession = null;
219
        }
220
        dirty.setDirty(false);
221
    }
222

    
223
	public void setDirty(boolean isDirty){
224
	    this.dirty.setDirty(isDirty);
225
	}
226
	@Override
227
    public void setDirty(){
228
        this.dirty.setDirty(true);
229
    }
230

    
231
	@Override
232
    public boolean isDirty(){
233
	    return dirty.isDirty();
234
	}
235

    
236
	@Override
237
	public void selectionChanged(SelectionChangedEvent event) {
238
		//propagate selection
239
		selService.setSelection(event.getSelection());
240
	}
241

    
242
	@Focus
243
	public void focus(){
244
	    if(viewer!=null){
245
	        viewer.getControl().setFocus();
246
	    }
247
        if(conversation!=null && !conversation.isBound()){
248
            conversation.bind();
249
        }
250
        if(cdmEntitySession != null) {
251
            cdmEntitySession.bind();
252
        }
253
	}
254

    
255
	@Override
256
    public void refresh(){
257
	    viewer.refresh();
258
	}
259

    
260
	@Override
261
    public TreeViewer getViewer(){
262
	    return viewer;
263
	}
264

    
265
	@Override
266
	public IStructuredSelection getSelection() {
267
	    return (IStructuredSelection) viewer.getSelection();
268
	}
269

    
270
	@Override
271
	public ConversationHolder getConversationHolder() {
272
	    return conversation;
273
	}
274

    
275
	@Override
276
    @Persist
277
	public void save(IProgressMonitor monitor){
278
        if (!conversation.isBound()) {
279
            conversation.bind();
280
        }
281

    
282
        // commit the conversation and start a new transaction immediately
283
        Object[] expandedElements = this.viewer.getExpandedElements();
284
        conversation.commit(true);
285
        if (operationList != null && !operationList.isEmpty()){
286
            for (AbstractPostOperation<TermNode> operation: operationList){
287
                AbstractUtility.executeOperation(operation, sync);
288
            }
289
            operationList.clear();
290
        }
291

    
292
        CdmStore.getService(ITermNodeService.class).saveTermNodeDtoList(listToUpdate);
293
        listToUpdate.clear();
294
        List<TermTreeDto> rootEntities = getRootEntities();
295
        CdmStore.getService(ITermTreeService.class).saveOrUpdateTermTreeDtoList(rootEntities);
296
        initializeTrees();
297
        conversation.commit(true);
298

    
299
        this.setDirty(false);
300
//        this.viewer.setExpandedElements(expandedElements);
301
	}
302

    
303
    private void initializeTrees() {
304
        Object[] expandedElements = viewer.getExpandedElements();
305
        viewer.getTree().removeAll();
306
        updateTrees();
307
        viewer.setInput(getTrees());
308
        viewer.setExpandedElements(expandedElements);
309
    }
310

    
311
	@PreDestroy
312
	public void dispose(){
313
	    selService.setSelection(null);
314
	    clearSession();
315
	}
316

    
317
    @Override
318
    public ICdmEntitySession getCdmEntitySession() {
319
        return cdmEntitySession;
320
    }
321

    
322
    @Override
323
    public Map<Object, List<String>> getPropertyPathsMap() {
324
        List<String> propertyPaths = Arrays.asList(new String[] {
325
                "children", //$NON-NLS-1$
326
                "feature", //$NON-NLS-1$
327
                "featureTree", //$NON-NLS-1$
328
        });
329
        Map<Object, List<String>> propertyPathMap =
330
                new HashMap<Object, List<String>>();
331
        propertyPathMap.put(TermNode.class,propertyPaths);
332
        return propertyPathMap;
333
    }
334

    
335
    @Override
336
    public List<TermTreeDto> getRootEntities() {
337
        return (List<TermTreeDto>) viewer.getInput();
338
    }
339

    
340
    @Override
341
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
342
    }
343

    
344
    @Override
345
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
346
        //close view when workbench closes
347
        try{
348
            thisPart.getContext().get(EPartService.class).hidePart(thisPart);
349
        }
350
        catch(Exception e){
351
            //nothing
352
        }
353
    }
354

    
355
    @Override
356
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
357
    }
358

    
359
    @Override
360
    public void contextRefresh(IProgressMonitor monitor) {
361
    }
362

    
363
    @Override
364
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
365
    }
366

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

    
371
    @Override
372
    public void changed(Object element) {
373
        dirty.setDirty(true);
374
        viewer.refresh();
375
    }
376

    
377
    @Override
378
    public void forceDirty() {
379
        dirty.setDirty(true);
380
    }
381

    
382
    @Override
383
    public boolean postOperation(Object objectAffectedByOperation) {
384
        initializeTrees();
385
        viewer.refresh();
386
        if(objectAffectedByOperation instanceof TermNodeDto){
387
        	TermNodeDto node = (TermNodeDto)objectAffectedByOperation;
388
//            viewer.expandToLevel(((TermRelationBase) node).getGraph(), 1); find a solution for dto editor
389
        }
390
        if(objectAffectedByOperation!=null){
391
            StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
392
            viewer.setSelection(selection);
393
        }
394
        return true;
395
    }
396

    
397
    @Override
398
    public boolean onComplete() {
399
        return false;
400
    }
401

    
402
    @Override
403
    public TermNodeDto getNodeDtoForUuid(UUID nodeUuid){
404
        return uuidTermMap.get(nodeUuid);
405
    }
406

    
407
    protected void addAllNodesToMap(TermNodeDto root){
408
        if (!uuidTermMap.containsKey(root.getUuid())){
409
            uuidTermMap.put(root.getUuid(), root);
410
            if (root.getTerm() != null){
411
                getTreeDtoForUuid(root.getTree().getUuid()).addTerm(root.getTerm());
412
            }
413
        }
414
        for (TermNodeDto child: root.getChildren()){
415
            uuidTermMap.put(child.getUuid(), child);
416
            if (child.getTerm() != null){
417
                getTreeDtoForUuid(child.getTree().getUuid()).addTerm(child.getTerm());
418
            }
419
            if (child.getChildren() != null && !child.getChildren().isEmpty()){
420
                addAllNodesToMap(child);
421
            }
422
        }
423
    }
424

    
425
    /**
426
     * @param term
427
     * @param treeUuid
428
     */
429
    @Override
430
    public boolean checkDuplicates(UUID termUuid, UUID treeUuid) {
431
        TermTreeDto tree = this.getTreeDtoForUuid(treeUuid);
432
        for (TermDto dto: tree.getTerms()){
433
            if (dto.getUuid().equals(termUuid)) {
434
                return true;
435
            }
436
        }
437
        return false;
438
    }
439

    
440
    protected void updateTrees(){
441
        uuidTermMap.clear();
442
        if (trees != null && !trees.isEmpty()){
443
            trees.clear();
444
        }
445
        if (trees == null){
446
            trees = new HashMap<>();
447
        }
448
        List<TermTreeDto> treeList = CdmStore.getService(ITermTreeService.class).listTermTreeDtosByTermType(getTermType());
449
        treeList.stream().forEach(tree -> trees.put(tree.getUuid(), tree));
450
//        trees.addAll(CdmStore.getService(ITermTreeService.class).listTermTreeDtosByTermType(getTermType()));
451
        for (TermTreeDto tree: trees.values()){
452
            addAllNodesToMap(tree.getRoot());
453
        }
454
        ((FeatureTreeContentProvider<T>)viewer.getContentProvider()).setUuidTermMap(uuidTermMap);
455
//        viewer.refresh();
456

    
457
    }
458

    
459
    public List<TermTreeDto> getTrees(){
460
        List<TermTreeDto> treeList = new ArrayList<>(trees.values());
461
        return treeList;
462
    }
463

    
464
    public void putTree(TermTreeDto tree){
465
       trees.put(tree.getUuid(), tree);
466

    
467
    }
468

    
469
    public void removeTree(TermTreeDto tree){
470
        trees.remove(tree.getUuid());
471

    
472
     }
473

    
474
    @Override
475
    public TermTreeDto getTreeDtoForUuid(UUID treeUuid){
476
        return trees.get(treeUuid);
477
    }
478

    
479
    @Override
480
    public void setTreeDtoForUuid(TermTreeDto tree){
481
        trees.put(tree.getUuid(), tree);
482
    }
483

    
484
    @Override
485
    public void setNodeDtoForUuid(TermNodeDto node){
486
        this.uuidTermMap.put(node.getUuid(), node);
487
    }
488

    
489
    @Override
490
    public void addOperation(AbstractPostOperation operation) {
491
        operationList.add(operation);
492
    }
493

    
494
    @Inject
495
    @Optional
496
    private void addSaveCandidate(@UIEventTopic(WorkbenchEventConstants.ADD_SAVE_CANDIDATE) UUID cdmbaseUuid) {
497
        for (UUID uuid: uuidTermMap.keySet()) {
498
            if (uuid.equals(cdmbaseUuid)){
499
                listToUpdate.add(uuidTermMap.get(uuid));
500
            }
501

    
502
        }
503
    }
504

    
505
}
(1-1/16)