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.view.e4;
10

    
11
import java.util.Collection;
12
import java.util.Set;
13

    
14
import javax.annotation.PreDestroy;
15
import javax.inject.Inject;
16
import javax.inject.Named;
17

    
18
import org.apache.logging.log4j.LogManager;
19
import org.apache.logging.log4j.Logger;
20
import org.eclipse.e4.core.contexts.IEclipseContext;
21
import org.eclipse.e4.core.di.annotations.Optional;
22
import org.eclipse.e4.ui.di.PersistState;
23
import org.eclipse.e4.ui.di.UISynchronize;
24
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
25
import org.eclipse.e4.ui.services.IServiceConstants;
26
import org.eclipse.e4.ui.workbench.modeling.EPartService;
27
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
28
import org.eclipse.jface.viewers.ISelectionChangedListener;
29
import org.eclipse.jface.viewers.IStructuredSelection;
30
import org.eclipse.jface.viewers.StructuredSelection;
31
import org.eclipse.jface.viewers.Viewer;
32
import org.eclipse.swt.SWTException;
33
import org.springframework.security.core.GrantedAuthority;
34

    
35
import eu.etaxonomy.cdm.api.service.ITermNodeService;
36
import eu.etaxonomy.cdm.api.service.ITermService;
37
import eu.etaxonomy.cdm.api.service.IVocabularyService;
38
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
39
import eu.etaxonomy.cdm.model.name.TaxonName;
40
import eu.etaxonomy.cdm.model.taxon.Taxon;
41
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
42
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
43
import eu.etaxonomy.cdm.persistence.dto.TermDto;
44
import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
45
import eu.etaxonomy.cdm.persistence.dto.TermVocabularyDto;
46
import eu.etaxonomy.taxeditor.editor.IBulkEditor;
47
import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
48
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
49
import eu.etaxonomy.taxeditor.model.MessagingUtils;
50
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
51
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
52
import eu.etaxonomy.taxeditor.security.RequiredPermissions;
53
import eu.etaxonomy.taxeditor.store.CdmStore;
54
import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
55
import eu.etaxonomy.taxeditor.view.e4.details.DetailsViewerE4;
56
import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
57
import eu.etaxonomy.taxeditor.workbench.part.ISelectionElementEditingPart;
58

    
59
/**
60
 * @author pplitzner
61
 * @since Aug 10, 2017
62
 */
63
public abstract class AbstractCdmEditorPart<V extends Viewer>
64
        implements IDirtyMarkable, ISelectionElementEditingPart, IPostOperationEnabled{
65

    
66
	private static final Logger logger = LogManager.getLogger();
67

    
68
	private DelaySelection delaySelection = null;
69

    
70
    /**
71
     * This is the monitor for the DelaySelection runnable.
72
     * If it is <code>true</code> then it is currently delaying a selection.
73
     */
74
    private boolean isInDelay;
75
    private boolean isEnabled = true;
76

    
77
    /**
78
     * This class invokes internal_selectionChanged() in a separate thread.
79
     * This allows an asynchronous and/or delayed handling of selection changes
80
     */
81
    private class DelaySelection implements Runnable{
82
        private Object selection;
83
        private MPart activePart;
84
        private MPart thisPart;
85
        private EPartService partService;
86

    
87
        public DelaySelection(Object selection, MPart activePart, MPart thisPart, EPartService partService) {
88
            this.selection = selection;
89
            this.activePart= activePart;
90
            this.thisPart = thisPart;
91
            this.partService = partService;
92
        }
93

    
94
        @Override
95
        public void run() {
96
            //multiple selections are not supported
97
            if(activePart != null
98
                    && thisPart != null
99
                    && !activePart.equals(thisPart)
100
                    && selection instanceof IStructuredSelection
101
                    && ((IStructuredSelection) selection).size()>1){
102
                showEmptyPage();
103
                return;
104
            }
105

    
106
            // no active editor found
107
            if(activePart == thisPart && WorkbenchUtility.getActiveEditorPart(partService) == null && showEmptyIfNoActiveEditor()){
108
                showEmptyPage();
109
                return;
110
            }
111

    
112
            if (viewer != null && viewer.getControl()!= null && viewer.getInput() != null && !viewer.getControl().isDisposed()){
113
               try{
114
                   viewer.getControl().setEnabled(isEnabled);
115
               }catch(SWTException e){
116
                   System.out.println("...exception3 ("+ (thisPart == null? "":thisPart.getLabel()) + ")");
117
                   logger.debug("Something went wrong for viewer.getControl().setEnabled(true) in " + this.getClass().getSimpleName(), e);
118
               }
119
            }
120

    
121
            //same as previous selection? => return
122
            if((previousSelection != null && selection != null)
123
                    && (activePart != null && selectionProvidingPart != null
124
                        && activePart.equals(selectionProvidingPart))
125
                    && (previousSelection == selection
126
                         || previousSelection.equals(selection)
127
                         || new StructuredSelection(selection).equals(previousSelection))
128
                     ) {
129
                 isInDelay = false;
130
                 return;
131
            }
132

    
133
            try{
134
                selectionChanged_internal(selection, activePart, thisPart);
135
            }catch (Exception ex){
136
                logger.error("Error during selectionChanged_internal", ex);
137
            }
138
            finally{
139
                previousSelection = selection;
140
                isInDelay = false;
141
            }
142
        }
143

    
144
        public synchronized void setSelection(Object selection) {
145
            this.selection = selection;
146
        }
147

    
148
        public synchronized void setActivePart(MPart activePart) {
149
            this.activePart = activePart;
150
        }
151

    
152
        public synchronized void setThisPart(MPart thisPart) {
153
            this.thisPart = thisPart;
154
        }
155

    
156
        public synchronized void setThisPartService(EPartService partService) {
157
            this.partService = partService;
158
        }
159
    }
160

    
161
    protected V viewer;
162

    
163
    protected MPart thisPart;
164

    
165
    protected MPart selectionProvidingPart;
166

    
167
    protected Object previousSelection;
168

    
169
    protected ISelectionChangedListener selectionChangedListener;
170

    
171
    public ISelectionChangedListener getSelectionChangedListener() {
172
        return selectionChangedListener;
173
    }
174

    
175
    @Inject
176
    protected ESelectionService selService;
177

    
178
    @Inject
179
    protected IEclipseContext context;
180

    
181
    protected abstract void selectionChanged_internal(Object selection, MPart activePart, MPart thisPart);
182

    
183
    protected boolean showEmptyIfNoActiveEditor(){
184
        return true;
185
    }
186

    
187
    @Inject
188
    public void selectionChanged(
189
            @Optional@Named(IServiceConstants.ACTIVE_SELECTION)Object selection,
190
            @Optional@Named(IServiceConstants.ACTIVE_PART)MPart activePart,
191
            MPart thisPart, UISynchronize sync, EPartService partService){
192

    
193
        //set the delay selection which puts the change handling to the end
194
        if(delaySelection == null){
195
            delaySelection = new DelaySelection(selection, activePart, thisPart, partService);
196
        }else{
197
            delaySelection.setSelection(selection);
198
            delaySelection.setActivePart(activePart);
199
            delaySelection.setThisPart(thisPart);
200
            delaySelection.setThisPartService(partService);
201
        }
202

    
203
        //as long as the delay thread is running,
204
        if(!isInDelay){
205
        	isInDelay = true;
206
            sync.asyncExec(delaySelection);
207
        }
208
    }
209

    
210
    @Override
211
    public void changed(Object object) {
212
        if(selectionProvidingPart != null){
213
            Object part = selectionProvidingPart.getObject();
214
            if(part instanceof IDirtyMarkable){
215
                ((IDirtyMarkable) part).changed(object);
216
            }
217
            if (part instanceof IBulkEditor){
218
            	((IBulkEditor)part).setSelection(createSelection(object));
219
            }
220
//            if (part instanceof ITaxonEditor){
221
//            	((ITaxonEditor)part).setDetailsChanged();
222
//            }
223
        }
224
    }
225

    
226
    public V getViewer() {
227
        return viewer;
228
    }
229

    
230
    public boolean isEnabled() {
231
        return isEnabled;
232
    }
233

    
234
    public void setEnabled(boolean isEnabled) {
235
        this.isEnabled = isEnabled;
236
    }
237

    
238
    protected void showViewer(IStructuredSelection selection, MPart activePart, Viewer viewer){
239
        if(CdmStore.getCurrentSessionManager().getActiveSession() == null){
240
            return;
241
        }
242
        if(viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed()){
243
            Object element = selection.getFirstElement();
244
            Object part = getPartObject(activePart);
245
            if (viewer.getControl().isDisposed()){
246
                return;
247
            }
248
            viewer.getControl().setEnabled(true);
249
            if(element != null){
250
                if (element instanceof Taxon){
251

    
252
                    Taxon taxon = HibernateProxyHelper.deproxy(element, Taxon.class);
253
                    if (part instanceof ITaxonEditor){
254
                        TaxonNode node = ((ITaxonEditor) part).getTaxonNode();
255
                        if (node != null){
256
                            boolean doEnable = CdmStore.currentAuthentiationHasPermission(node,
257
                                    RequiredPermissions.TAXON_EDIT);
258
                            if (!doEnable){
259
                                 //check whether there are explicit TaxonNode rights
260
                                 boolean taxonnodePermissionExists = false;
261
                                 Collection<? extends GrantedAuthority> authorities = CdmStore.getCurrentAuthentiation().getAuthorities();
262
                                 for (GrantedAuthority grantedAuthority: authorities){
263
                                     if (grantedAuthority.getAuthority().startsWith("TAXONNODE")){
264
                                         taxonnodePermissionExists = true;
265
                                     }
266
                                 }
267
                                 if (!taxonnodePermissionExists){
268
                                     doEnable = true;
269
                                 }
270
                            }
271

    
272
                            //TODO: differ between the views
273
                            this.isEnabled = doEnable;
274
                        }
275
                    }
276

    
277
                    if (taxon.isMisapplication() || taxon.isProparteSynonym() ){
278

    
279
                        if(part instanceof ITaxonEditor){
280
                            Taxon accepted = ((ITaxonEditor) part).getTaxon();
281

    
282
                            Set<TaxonRelationship> rels =  taxon.getTaxonRelations(accepted);
283

    
284
                            if (rels != null && rels.iterator().hasNext() && !taxon.equals(accepted)){
285
                                TaxonRelationship rel = rels.iterator().next();
286
                                if ((rel.getType().isMisappliedName() || rel.getType().isAnySynonym()) && !rel.getFromTaxon().equals(((ITaxonEditor) part).getTaxon())){
287
                                    viewer.setInput(rel);
288
                                    selectionProvidingPart = activePart;
289
                                    return;
290
                                }
291
                            }
292
                        }
293
                    }
294
                }
295

    
296
                //unwrap term DTOs
297
                if(element instanceof TermDto){
298
                    element = CdmStore.getService(ITermService.class).load(((TermDto) element).getUuid());
299
                }
300
                else if(element instanceof TermVocabularyDto){
301
                    element = CdmStore.getService(IVocabularyService.class).load(((TermVocabularyDto) element).getUuid());
302
                }
303

    
304
                selectionProvidingPart = activePart;
305
                if (viewer instanceof DetailsViewerE4){
306

    
307
                    if (selectionProvidingPart.getElementId().equals("eu.etaxonomy.taxeditor.editor.view.checklist.e4.DistributionEditorPart")){
308
                        ((DetailsViewerE4)viewer).setDetailsEnabled(false);
309
                    }else{
310
                        ((DetailsViewerE4)viewer).setDetailsEnabled(isEnabled);
311
                    }
312
                    ((DetailsViewerE4)viewer).setInput(element, part);
313
                }
314
                else{
315
                    if(element instanceof TermNodeDto){
316
                        element = CdmStore.getService(ITermNodeService.class).load(((TermNodeDto) element).getUuid());
317
                    }
318
                    if (activePart.getObject() instanceof DetailsPartE4 && element instanceof TaxonName){
319
                        selectionProvidingPart = ((DetailsPartE4)activePart.getObject()).getSelectionProvidingPart();
320
                    }
321

    
322
                    viewer.setInput(element);
323
                    viewer.getControl().setEnabled(isEnabled);
324
                }
325
            }
326
        }
327
    }
328

    
329
    protected Object getPartObject(MPart activePart) {
330
        Object partObject = activePart;
331
        Object wrappedPart = WorkbenchUtility.getE4WrappedPart(activePart);
332
        if(wrappedPart != null){
333
            partObject = wrappedPart;
334
        }
335
        return partObject;
336
    }
337

    
338
    protected void showEmptyPage() {
339
        if(viewer!=null && viewer.getControl()!=null && !viewer.getControl().isDisposed() ){
340
            viewer.setInput(null);
341
            try{
342
	            if (!viewer.getControl().isDisposed()){
343
	                viewer.getControl().setEnabled(false);
344
	            }
345
            }catch(SWTException e){
346
            	if (PreferencesUtil.isShowUpWidgetIsDisposedMessages() && e.getMessage().equals("Widget is disposed")){
347
                    MessagingUtils.errorDialog("Widget is disposed",
348
                            null,
349
                            MessagingUtils.WIDGET_IS_DISPOSED_MESSAGE,
350
                            null,
351
                            e,
352
                            true);
353
                }
354
            }
355
        }
356

    
357
        reset();
358
        if(thisPart!=null){
359
            thisPart.setLabel(getViewName());
360
        }
361
    }
362

    
363
    protected IStructuredSelection createSelection(Object selection) {
364
        if(selection==null){
365
            return null;
366
        }
367
        IStructuredSelection structuredSelection;
368
        if(!(selection instanceof IStructuredSelection)){
369
            structuredSelection = new StructuredSelection(selection);
370
        }
371
        else{
372
            structuredSelection = (IStructuredSelection) selection;
373
        }
374
        return structuredSelection;
375
    }
376

    
377

    
378
    @Override
379
    public boolean postOperation(Object objectAffectedByOperation) {
380
        changed(objectAffectedByOperation);
381
        return true;
382
    }
383

    
384
    @Override
385
    public boolean onComplete() {
386
        viewer.refresh();
387
        return true;
388
    }
389

    
390
    @Override
391
    public MPart getSelectionProvidingPart() {
392
        return selectionProvidingPart;
393
    }
394

    
395
    @PreDestroy
396
    private void dispose() {
397
    }
398

    
399
    private void reset(){
400
        previousSelection = null;
401
        selectionProvidingPart = null;
402
        delaySelection = null;
403
        context.deactivate();
404
    }
405

    
406
    @PersistState
407
    private void persistState(){
408

    
409
    }
410

    
411
    @Override
412
    public void forceDirty() {
413
    }
414

    
415
    protected abstract String getViewName();
416

    
417
}
(2-2/2)