Project

General

Profile

Download (17.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
package eu.etaxonomy.taxeditor.termtree.e4;
10

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

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

    
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.e4.core.di.annotations.Optional;
24
import org.eclipse.e4.ui.di.Focus;
25
import org.eclipse.e4.ui.di.Persist;
26
import org.eclipse.e4.ui.di.UIEventTopic;
27
import org.eclipse.e4.ui.di.UISynchronize;
28
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
29
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
30
import org.eclipse.e4.ui.services.EMenuService;
31
import org.eclipse.e4.ui.workbench.modeling.EPartService;
32
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
33
import org.eclipse.jface.util.LocalSelectionTransfer;
34
import org.eclipse.jface.viewers.ISelection;
35
import org.eclipse.jface.viewers.ISelectionChangedListener;
36
import org.eclipse.jface.viewers.IStructuredSelection;
37
import org.eclipse.jface.viewers.SelectionChangedEvent;
38
import org.eclipse.jface.viewers.StructuredSelection;
39
import org.eclipse.jface.viewers.TreeViewer;
40
import org.eclipse.swt.SWT;
41
import org.eclipse.swt.dnd.DND;
42
import org.eclipse.swt.dnd.Transfer;
43
import org.eclipse.swt.events.KeyAdapter;
44
import org.eclipse.swt.events.KeyEvent;
45
import org.eclipse.swt.layout.FillLayout;
46
import org.eclipse.swt.widgets.Composite;
47
import org.eclipse.ui.IMemento;
48

    
49
import eu.etaxonomy.cdm.api.service.ITermNodeService;
50
import eu.etaxonomy.cdm.api.service.ITermTreeService;
51
import eu.etaxonomy.cdm.api.service.UpdateResult;
52
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
53
import eu.etaxonomy.cdm.model.term.TermNode;
54
import eu.etaxonomy.cdm.model.term.TermType;
55
import eu.etaxonomy.cdm.persistence.dto.TermDto;
56
import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
57
import eu.etaxonomy.cdm.persistence.dto.TermTreeDto;
58
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
59
import eu.etaxonomy.taxeditor.editor.definedterm.TermTransfer;
60
import eu.etaxonomy.taxeditor.editor.definedterm.TermTreeViewerComparator;
61
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
62
import eu.etaxonomy.taxeditor.l10n.Messages;
63
import eu.etaxonomy.taxeditor.model.AbstractUtility;
64
import eu.etaxonomy.taxeditor.model.IContextListener;
65
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
66
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
67
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
68
import eu.etaxonomy.taxeditor.model.MessagingUtils;
69
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
70
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
71
import eu.etaxonomy.taxeditor.store.AppModelId;
72
import eu.etaxonomy.taxeditor.store.CdmStore;
73
import eu.etaxonomy.taxeditor.termtree.TermNodeDtoTransfer;
74
import eu.etaxonomy.taxeditor.termtree.TermTreeContentProvider;
75
import eu.etaxonomy.taxeditor.termtree.TermTreeLabelProvider;
76
import eu.etaxonomy.taxeditor.termtree.e4.operation.AddFeatureOperation;
77
import eu.etaxonomy.taxeditor.termtree.e4.operation.CreateFeatureTreeOperation;
78
import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
79

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

    
89
    public static final String OPEN_COMMAND_ID = "eu.etaxonomy.taxeditor.store.openTermTreeEditor";
90

    
91
    public static final List<String> TREE_PROPERTY_PATH = Arrays.asList(new String[] {
92
            "root", //$NON-NLS-1$
93
            "root.children", //$NON-NLS-1$
94
            "root.children.inapplicableIf", //$NON-NLS-1$
95
            "root.children.inapplicableIf.term", //$NON-NLS-1$
96
            "root.children.inapplicableIf.state", //$NON-NLS-1$
97
            "root.children.onlyApplicableIf", //$NON-NLS-1$
98
            "root.children.onlyApplicableIf.term", //$NON-NLS-1$
99
            "root.children.onlyApplicableIf.state", //$NON-NLS-1$
100
    });
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
    Map<UUID, CreateFeatureTreeOperation> createOperationList = 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
        TermTreeContentProvider<?> contentProvider = new TermTreeContentProvider<>();
143

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

    
147
        int ops = DND.DROP_COPY | DND.DROP_MOVE;
148
        Transfer[] transfers = new Transfer[] {
149
                TermNodeDtoTransfer.getInstance(),
150
                TermTransfer.getInstance(),
151
                LocalSelectionTransfer.getTransfer()};
152
        viewer.addDragSupport(ops, transfers, new TermNodeDtoDragListener(viewer));
153
        viewer.addDropSupport(ops, transfers, new TermTreeDtoDropAdapter(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 TermTreeViewerComparator());
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 TermTreeViewerComparator());
179
        viewer.setInput(getTrees());
180
        ((TermTreeContentProvider)viewer.getContentProvider()).setUuidTermMap(uuidTermMap);
181
        thisPart.setLabel(label);
182
    }
183

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

    
186
    public void paste(IStructuredSelection selection) {
187
        ISelection clipBoardSelection = LocalSelectionTransfer.getTransfer().getSelection();
188
        Object firstElement = selection.getFirstElement();
189
        TermNodeDto parentNode = null;
190
        if(firstElement instanceof TermNodeDto){
191
            parentNode = (TermNodeDto) firstElement;
192
        }
193
        else if(firstElement instanceof TermTreeDto){
194
            parentNode = ((TermTreeDto)firstElement).getRoot();
195
        }
196
        if(parentNode!=null){
197

    
198
        	TermNodeDto copiedNode = (TermNodeDto) ((IStructuredSelection)clipBoardSelection).getFirstElement();
199
        	boolean isDuplicate = this.checkDuplicates(copiedNode.getTerm().getUuid(), parentNode.getTree().getUuid());
200
            if (isDuplicate && !parentNode.getTree().isAllowDuplicate()){
201
                MessagingUtils.informationDialog(Messages.AddFeatureHandler_Duplicates_not_allowed, Messages.AddFeatureHandler_Duplicates_not_allowed_message +  "\n"+copiedNode.getTerm().getTitleCache());
202
                return;
203
            }
204
        	TermNodeDto newDto = new TermNodeDto(copiedNode.getTerm(), parentNode, 0, parentNode.getTree(), null, null, null);
205
        	this.refresh();
206
        	this.setDirty();
207
            AddFeatureOperation operation = new AddFeatureOperation(copiedNode.getTerm().getUuid(), parentNode, this, this);
208
//            AbstractUtility.executeOperation(operation, sync);
209
            this.addOperation(operation);
210
        }
211
    }
212

    
213
    public void copy(IStructuredSelection selection) {
214
        LocalSelectionTransfer.getTransfer().setSelection(selection);
215
    }
216

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

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

    
231
    @Override
232
    public boolean isDirty(){
233
        return dirty.isDirty();
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 void selectionChanged(SelectionChangedEvent event) {
245
		//propagate selection
246
		selService.setSelection(event.getSelection());
247
	}
248

    
249
	@Focus
250
	public void focus(){
251
	    if(viewer!=null){
252
	        viewer.getControl().setFocus();
253
	    }
254
        if(cdmEntitySession != null) {
255
            cdmEntitySession.bind();
256
        }
257
        if (viewer.getSelection().isEmpty()){
258
            viewer.setSelection(null);
259
        }
260
	}
261

    
262
	@Override
263
    public void refresh(){
264
	    viewer.refresh();
265
	}
266

    
267
	@Override
268
    public TreeViewer getViewer(){
269
	    return viewer;
270
	}
271

    
272
	@Override
273
	public IStructuredSelection getSelection() {
274
	    return (IStructuredSelection) viewer.getSelection();
275
	}
276

    
277
	
278

    
279
	@Override
280
    @Persist
281
	public void save(IProgressMonitor monitor){
282
        
283
        
284
        ISelection sel = this.viewer.getSelection();
285
        
286
        if (createOperationList != null && !createOperationList.isEmpty()){
287
            for (CreateFeatureTreeOperation operation: createOperationList.values()){
288
                TermTreeDto termDto = getTreeDtoForUuid(operation.getElementUuid());
289
                operation.getElement().setTitleCache(termDto.getTitleCache(), true);
290
                operation.getElement().setAllowDuplicates(termDto.isAllowDuplicate());
291
                operation.getElement().setFlat(termDto.isFlat());
292
                operation.getElement().setOrderRelevant(termDto.isOrderRelevant());
293
                AbstractUtility.executeOperation(operation, sync);
294
            }
295
            createOperationList.clear();
296
        }
297

    
298
        if (operationList != null && !operationList.isEmpty()){
299
            for (AbstractPostOperation<TermNode> operation: operationList){
300
                AbstractUtility.executeOperation(operation, sync);
301
            }
302
            operationList.clear();
303
        }
304

    
305
        CdmStore.getService(ITermNodeService.class).saveTermNodeDtoList(listToUpdate);
306
        listToUpdate.clear();
307
        List<TermTreeDto> rootEntities = getRootEntities();
308
        UpdateResult result = CdmStore.getService(ITermTreeService.class).saveOrUpdateTermTreeDtoList(rootEntities);
309
       
310
        this.setDirty(false);
311
        initializeTrees();
312
        this.viewer.setSelection(sel);
313
//        this.viewer.setExpandedElements(expandedElements);
314
	}
315

    
316
    private void initializeTrees() {
317
        Object[] expandedElements = viewer.getExpandedElements();
318
        viewer.getTree().removeAll();
319
        updateTrees();
320
        viewer.setInput(getTrees());
321
        viewer.setExpandedElements(expandedElements);
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
                "term", //$NON-NLS-1$
340
                "termTree", //$NON-NLS-1$
341
        });
342
        Map<Object, List<String>> propertyPathMap = new HashMap<>();
343
        propertyPathMap.put(TermNode.class,propertyPaths);
344
        return propertyPathMap;
345
    }
346

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

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

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

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

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

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

    
379
    @Override
380
    public void changed(Object element) {
381
        dirty.setDirty(true);
382
        viewer.refresh();
383
    }
384

    
385
    @Override
386
    public void forceDirty() {
387
        dirty.setDirty(true);
388
    }
389

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

    
405
    @Override
406
    public boolean onComplete() {
407
        return false;
408
    }
409

    
410
    @Override
411
    public TermNodeDto getNodeDtoForUuid(UUID nodeUuid){
412
        return uuidTermMap.get(nodeUuid);
413
    }
414

    
415
    protected void addAllNodesToMap(TermNodeDto root){
416
        if (!uuidTermMap.containsKey(root.getUuid())){
417
            uuidTermMap.put(root.getUuid(), root);
418
//            if (root.getTerm() != null){
419
//                getTreeDtoForUuid(root.getTree().getUuid()).addTerm(root.getTerm());
420
//            }
421
        }
422
        for (TermNodeDto child: root.getChildren()){
423
            uuidTermMap.put(child.getUuid(), child);
424
//            if (child.getTerm() != null){
425
//                getTreeDtoForUuid(child.getTree().getUuid()).addTerm(child.getTerm());
426
//            }
427
            if (child.getChildren() != null && !child.getChildren().isEmpty()){
428
                addAllNodesToMap(child);
429
            }
430
        }
431
    }
432

    
433
    @Override
434
    public boolean checkDuplicates(UUID termUuid, UUID treeUuid) {
435
        TermTreeDto tree = this.getTreeDtoForUuid(treeUuid);
436
        if (tree != null){
437
            for (TermDto dto: tree.getTerms()){
438
                if (dto != null && dto.getUuid().equals(termUuid)) {
439
                    return true;
440
                }
441
            }
442
        }
443
        return false;
444
    }
445

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

    
463
    public List<TermTreeDto> getTrees(){
464
        List<TermTreeDto> treeList = new ArrayList<>(trees.values());
465
        return treeList;
466
    }
467

    
468
    public void putTree(TermTreeDto tree){
469
       trees.put(tree.getUuid(), tree);
470
    }
471

    
472
    public void removeTree(TermTreeDto tree){
473
        trees.remove(tree.getUuid());
474
     }
475

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

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

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

    
491
    @Override
492
    public void addOperation(AbstractPostOperation operation) {
493
        if (operation instanceof CreateFeatureTreeOperation){
494
            createOperationList.put(((CreateFeatureTreeOperation)operation).getElementUuid(), (CreateFeatureTreeOperation)operation);
495
        }else{
496
            operationList.add(operation);
497
        }
498
    }
499

    
500
    @Inject
501
    @Optional
502
    private void addSaveCandidate(@UIEventTopic(WorkbenchEventConstants.ADD_SAVE_CANDIDATE) UUID cdmbaseUuid) {
503
        for (UUID uuid: uuidTermMap.keySet()) {
504
            if (uuid.equals(cdmbaseUuid)){
505
               listToUpdate.add(uuidTermMap.get(uuid));
506
            }
507
        }
508
    }
509

    
510
    @Override
511
    public TermType getTermType() {
512
        return termType;
513
    }
514
}
(8-8/10)