ref #9359 upgrade TaxEditor to log4j2
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / view / e4 / AbstractCdmEditorPartE4.java
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;import org.apache.logging.log4j.Logger;
19 import org.eclipse.e4.core.contexts.IEclipseContext;
20 import org.eclipse.e4.core.di.annotations.Optional;
21 import org.eclipse.e4.ui.di.PersistState;
22 import org.eclipse.e4.ui.di.UISynchronize;
23 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
24 import org.eclipse.e4.ui.services.IServiceConstants;
25 import org.eclipse.e4.ui.workbench.modeling.EPartService;
26 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
27 import org.eclipse.jface.viewers.ISelectionChangedListener;
28 import org.eclipse.jface.viewers.IStructuredSelection;
29 import org.eclipse.jface.viewers.StructuredSelection;
30 import org.eclipse.jface.viewers.Viewer;
31 import org.eclipse.swt.SWTException;
32 import org.springframework.security.core.GrantedAuthority;
33
34 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
35 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
36 import eu.etaxonomy.cdm.api.service.ITermNodeService;
37 import eu.etaxonomy.cdm.api.service.ITermService;
38 import eu.etaxonomy.cdm.api.service.IVocabularyService;
39 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
40 import eu.etaxonomy.cdm.model.common.CdmBase;
41 import eu.etaxonomy.cdm.model.name.TaxonName;
42 import eu.etaxonomy.cdm.model.taxon.Taxon;
43 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
44 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
45 import eu.etaxonomy.cdm.persistence.dto.TermDto;
46 import eu.etaxonomy.cdm.persistence.dto.TermNodeDto;
47 import eu.etaxonomy.cdm.persistence.dto.TermVocabularyDto;
48 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
49 import eu.etaxonomy.taxeditor.editor.IBulkEditor;
50 import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
51 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
52 import eu.etaxonomy.taxeditor.model.MessagingUtils;
53 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
54 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
55 import eu.etaxonomy.taxeditor.security.RequiredPermissions;
56 import eu.etaxonomy.taxeditor.store.CdmStore;
57 import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
58 import eu.etaxonomy.taxeditor.view.e4.details.DetailsViewerE4;
59 import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
60 import eu.etaxonomy.taxeditor.workbench.part.ISelectionElementEditingPart;
61
62 /**
63 * @author pplitzner
64 * @since Aug 10, 2017
65 */
66 public abstract class AbstractCdmEditorPartE4
67 implements IConversationEnabled, IDirtyMarkable, ISelectionElementEditingPart, IPostOperationEnabled{
68
69 private static final Logger logger = LogManager.getLogger(AbstractCdmEditorPartE4.class);
70
71 private DelaySelection delaySelection = null;
72 /**
73 * This is the monitor for the DelaySelection runnable.
74 * If it is <code>true</code> then it is currently delaying a selection.
75 */
76 private boolean isInDelay;
77 private boolean isEnabled = true;
78
79 /**
80 * This class invokes internal_selectionChanged() in a separate thread.
81 * This allows an asynchronous and/or delayed handling of selection changes
82 */
83 private class DelaySelection implements Runnable{
84 private Object selection;
85 private MPart activePart;
86 private MPart thisPart;
87
88 public DelaySelection(Object selection, MPart activePart, MPart thisPart) {
89 super();
90 this.selection = selection;
91 this.activePart= activePart;
92 this.thisPart = thisPart;
93 }
94
95 @Override
96 public void run() {
97 try{
98 selectionChanged_internal(selection, activePart, thisPart);
99 }
100 finally{
101 isInDelay = false;
102 }
103 }
104
105 public synchronized void setSelection(Object selection) {
106 this.selection = selection;
107 }
108
109 public synchronized void setActivePart(MPart activePart) {
110 this.activePart = activePart;
111 }
112
113 public synchronized void setThisPart(MPart thisPart) {
114 this.thisPart = thisPart;
115 }
116 }
117
118 protected Viewer viewer;
119
120 protected MPart thisPart;
121
122 protected MPart selectionProvidingPart;
123
124 protected Object previousSelection;
125
126 protected ISelectionChangedListener selectionChangedListener;
127
128 public ISelectionChangedListener getSelectionChangedListener() {
129 return selectionChangedListener;
130 }
131
132 @Inject
133 protected ESelectionService selService;
134
135 @Inject
136 protected IEclipseContext context;
137
138 protected abstract void selectionChanged_internal(Object selection, MPart activePart, MPart thisPart);
139
140 protected boolean showEmptyIfNoActiveEditor(){
141 return true;
142 }
143
144 @Inject
145 public void selectionChanged(
146 @Optional@Named(IServiceConstants.ACTIVE_SELECTION)Object selection,
147 @Optional@Named(IServiceConstants.ACTIVE_PART)MPart activePart,
148 MPart thisPart, UISynchronize sync, EPartService partService){
149 //multiple selections are not supported
150 if(activePart!=null
151 && thisPart!=null
152 && !activePart.equals(thisPart)
153 && selection instanceof IStructuredSelection
154 && ((IStructuredSelection) selection).size()>1){
155 showEmptyPage();
156 return;
157 }
158 // no active editor found
159 if(activePart==thisPart && WorkbenchUtility.getActiveEditorPart(partService)==null && showEmptyIfNoActiveEditor()){
160 showEmptyPage();
161 return;
162 }
163 if (viewer != null && viewer.getControl()!= null && viewer.getInput() != null && !viewer.getControl().isDisposed()){
164 try{
165 viewer.getControl().setEnabled(isEnabled);
166 }catch(SWTException e){
167 logger.debug("Something went wrong for viewer.getControl().setEnabled(true) in " + this.getClass().getSimpleName(), e);
168 }
169 }
170
171 if((previousSelection!=null && selection!=null)
172 && (activePart != null && selectionProvidingPart != null && activePart.equals(selectionProvidingPart))
173 && (previousSelection==selection
174 || previousSelection.equals(selection)
175 || new StructuredSelection(selection).equals(previousSelection))
176 ) {
177 return;
178 }
179 if(delaySelection==null){
180 delaySelection = new DelaySelection(selection, activePart, thisPart);
181 }else{
182 delaySelection.setSelection(selection);
183 delaySelection.setActivePart(activePart);
184 delaySelection.setThisPart(thisPart);
185 }
186 if(!isInDelay){
187 isInDelay = true;
188 sync.asyncExec(delaySelection);
189 previousSelection = selection;
190 }
191 }
192
193 @Override
194 public void changed(Object object) {
195 if(selectionProvidingPart!=null){
196 Object part = selectionProvidingPart.getObject();
197 if(part instanceof IDirtyMarkable){
198 ((IDirtyMarkable) part).changed(object);
199 }
200 if (part instanceof IBulkEditor){
201 ((IBulkEditor)part).setSelection(createSelection(object));
202 }
203 }
204 }
205
206 public Viewer getViewer() {
207 return viewer;
208 }
209
210 public boolean isEnabled() {
211 return isEnabled;
212 }
213
214 public void setEnabled(boolean isEnabled) {
215 this.isEnabled = isEnabled;
216 }
217
218 protected void showViewer(IStructuredSelection selection, MPart activePart, Viewer viewer){
219 if(CdmStore.getCurrentSessionManager().getActiveSession()==null){
220 return;
221 }
222 if(viewer!=null && viewer.getControl()!=null && !viewer.getControl().isDisposed()){
223 Object element = selection.getFirstElement();
224 Object part = createPartObject(activePart);
225 if (viewer.getControl().isDisposed()){
226 return;
227 }
228 viewer.getControl().setEnabled(true);
229 if(element != null){
230 if (element instanceof Taxon){
231
232 Taxon taxon = HibernateProxyHelper.deproxy(element, Taxon.class);
233 if (part instanceof ITaxonEditor){
234 TaxonNode node = ((ITaxonEditor) part).getTaxonNode();
235 if (node != null){
236 boolean doEnable = CdmStore.currentAuthentiationHasPermission(node,
237 RequiredPermissions.TAXON_EDIT);
238 if (!doEnable){
239 //check whether there are explicit TaxonNode rights
240 boolean taxonnodePermissionExists = false;
241 Collection<? extends GrantedAuthority> authorities = CdmStore.getCurrentAuthentiation().getAuthorities();
242 for (GrantedAuthority grantedAuthority: authorities){
243 if (grantedAuthority.getAuthority().startsWith("TAXONNODE")){
244 taxonnodePermissionExists = true;
245 }
246 }
247 if (!taxonnodePermissionExists){
248 doEnable = true;
249 }
250 }
251
252 //TODO: differ between the views
253 this.isEnabled = doEnable;
254 }
255 }
256 if (taxon.isMisapplication() || taxon.isProparteSynonym() ){
257
258 if(part instanceof ITaxonEditor){
259 Taxon accepted = ((ITaxonEditor) part).getTaxon();
260
261 Set<TaxonRelationship> rels = taxon.getTaxonRelations(accepted);
262
263 if (rels != null && rels.iterator().hasNext() && !taxon.equals(accepted)){
264 TaxonRelationship rel = rels.iterator().next();
265 if ((rel.getType().isMisappliedName() || rel.getType().isAnySynonym()) && !rel.getFromTaxon().equals(((ITaxonEditor) part).getTaxon())){
266 viewer.setInput(rel);
267 selectionProvidingPart = activePart;
268 return;
269 }
270 }
271 }
272 }
273 }
274
275 //unwrap term DTOs
276 if(element instanceof TermDto){
277 element = CdmStore.getService(ITermService.class).load(((TermDto) element).getUuid());
278 }
279 else if(element instanceof TermVocabularyDto){
280 element = CdmStore.getService(IVocabularyService.class).load(((TermVocabularyDto) element).getUuid());
281 }
282
283
284 selectionProvidingPart = activePart;
285 if (viewer instanceof DetailsViewerE4){
286
287 if (selectionProvidingPart.getElementId().equals("eu.etaxonomy.taxeditor.editor.view.checklist.e4.DistributionEditorPart")){
288 ((DetailsViewerE4)viewer).setDetailsEnabled(false);
289 }else{
290 ((DetailsViewerE4)viewer).setDetailsEnabled(isEnabled);
291 }
292 ((DetailsViewerE4)viewer).setInput(element, part);
293
294 }
295
296 else{
297 if(element instanceof TermNodeDto){
298 element = CdmStore.getService(ITermNodeService.class).load(((TermNodeDto) element).getUuid());
299 }
300 if (activePart.getObject() instanceof DetailsPartE4 && element instanceof TaxonName){
301 selectionProvidingPart = ((DetailsPartE4)activePart.getObject()).getSelectionProvidingPart();
302 }
303
304 viewer.setInput(element);
305 viewer.getControl().setEnabled(isEnabled);
306 }
307 }
308 }
309
310 }
311
312 protected Object createPartObject(MPart activePart) {
313 Object partObject = activePart;
314 Object wrappedPart = WorkbenchUtility.getE4WrappedPart(activePart);
315 if(wrappedPart!=null){
316 partObject = wrappedPart;
317 }
318 return partObject;
319 }
320
321 protected void showEmptyPage() {
322 if(viewer!=null && viewer.getControl()!=null && !viewer.getControl().isDisposed() ){
323 viewer.setInput(null);
324 try{
325 if (!viewer.getControl().isDisposed()){
326 viewer.getControl().setEnabled(false);
327 }
328 }catch(SWTException e){
329 if (PreferencesUtil.isShowUpWidgetIsDisposedMessages() && e.getMessage().equals("Widget is disposed")){
330 MessagingUtils.errorDialog("Widget is disposed",
331 null,
332 MessagingUtils.WIDGET_IS_DISPOSED_MESSAGE,
333 null,
334 e,
335 true);
336 }
337 }
338 }
339
340 reset();
341 if(thisPart!=null){
342 thisPart.setLabel(getViewName());
343 }
344 }
345
346 protected IStructuredSelection createSelection(Object selection) {
347 if(selection==null){
348 return null;
349 }
350 IStructuredSelection structuredSelection;
351 if(!(selection instanceof IStructuredSelection)){
352 structuredSelection = new StructuredSelection(selection);
353 }
354 else{
355 structuredSelection = (IStructuredSelection) selection;
356 }
357 return structuredSelection;
358 }
359
360 @Override
361 public ConversationHolder getConversationHolder() {
362 if(selectionProvidingPart != null && selectionProvidingPart instanceof IConversationEnabled) {
363 return ((IConversationEnabled) selectionProvidingPart).getConversationHolder();
364 }
365 return null;
366 }
367
368 @Override
369 public boolean postOperation(Object objectAffectedByOperation) {
370 changed(objectAffectedByOperation);
371 // Object part = selectionProvidingPart.getObject();
372 // if (part instanceof IBulkEditor){
373 // ((IBulkEditor)part).setSelection(createSelection(objectAffectedByOperation));
374 // }
375 return true;
376 }
377
378 @Override
379 public boolean onComplete() {
380 viewer.refresh();
381 return true;
382 }
383
384 @Override
385 public MPart getSelectionProvidingPart() {
386 return selectionProvidingPart;
387 }
388
389 @PreDestroy
390 private void dispose() {
391 }
392
393 private void reset(){
394 previousSelection = null;
395 selectionProvidingPart = null;
396 delaySelection = null;
397 context.deactivate();
398 }
399
400 @PersistState
401 private void persistState(){
402
403 }
404
405 @Override
406 public void update(CdmDataChangeMap arg0) {
407 }
408
409 @Override
410 public void forceDirty() {
411 }
412
413 protected abstract String getViewName();
414
415 }