Project

General

Profile

Download (12.8 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.navigation.navigator.e4;
11

    
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Comparator;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Observable;
20
import java.util.Observer;
21
import java.util.Set;
22
import java.util.UUID;
23

    
24
import javax.annotation.PostConstruct;
25
import javax.annotation.PreDestroy;
26
import javax.inject.Inject;
27

    
28
import org.eclipse.core.runtime.IAdaptable;
29
import org.eclipse.core.runtime.IProgressMonitor;
30
import org.eclipse.e4.ui.di.Focus;
31
import org.eclipse.e4.ui.services.EMenuService;
32
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
33
import org.eclipse.jface.viewers.ISelection;
34
import org.eclipse.jface.viewers.ISelectionChangedListener;
35
import org.eclipse.jface.viewers.IStructuredSelection;
36
import org.eclipse.jface.viewers.TreePath;
37
import org.eclipse.jface.viewers.TreeViewer;
38
import org.eclipse.swt.SWT;
39
import org.eclipse.swt.layout.FillLayout;
40
import org.eclipse.swt.widgets.Composite;
41
import org.eclipse.ui.IMemento;
42

    
43
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
44
import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
45
import eu.etaxonomy.cdm.api.application.ICdmChangeListener;
46
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
47
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
48
import eu.etaxonomy.cdm.api.service.IClassificationService;
49
import eu.etaxonomy.cdm.model.common.CdmBase;
50
import eu.etaxonomy.cdm.model.common.ICdmBase;
51
import eu.etaxonomy.cdm.model.common.ITreeNode;
52
import eu.etaxonomy.cdm.model.taxon.Classification;
53
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
54
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
55
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByNameComparator;
56
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByRankAndNameComparator;
57
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
58
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
59
import eu.etaxonomy.taxeditor.model.IContextListener;
60
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
61
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
62
import eu.etaxonomy.taxeditor.navigation.l10n.Messages;
63
import eu.etaxonomy.taxeditor.navigation.navigator.EmptyRoot;
64
import eu.etaxonomy.taxeditor.navigation.navigator.Root;
65
import eu.etaxonomy.taxeditor.navigation.navigator.TaxonNodeNavigatorComparator;
66
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
67
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
68
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
69
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
70
import eu.etaxonomy.taxeditor.store.CdmStore;
71
import eu.etaxonomy.taxeditor.store.LoginManager;
72
import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
73

    
74
/**
75
 *
76
 * @author pplitzner
77
 * @since Sep 7, 2017
78
 *
79
 */
80
public class TaxonNavigatorE4 implements
81
		IPostOperationEnabled, IConversationEnabled, Observer,
82
		ICdmEntitySessionEnabled, ICdmChangeListener, IContextListener {
83

    
84
    private static final String RESTORING_TAXON_NAVIGATOR = Messages.TaxonNavigator_RESTORE;
85

    
86
	private static final String TREE_PATH = "treepath"; //$NON-NLS-1$
87

    
88
	private static final String TREE_PATHS = "treepaths"; //$NON-NLS-1$
89

    
90
	private ConversationHolder conversation;
91

    
92
	private ICdmEntitySession cdmEntitySession;
93

    
94
	private IDataChangeBehavior dataChangeBehavior;
95

    
96
	private Root root;
97

    
98
	private TreeViewer viewer;
99

    
100
    @Inject
101
    private ESelectionService selService;
102

    
103
    private ISelectionChangedListener selectionChangedListener;
104

    
105
	@Inject
106
    public TaxonNavigatorE4() {
107
	    CdmStore.getContextManager().addContextListener(this);
108
    }
109

    
110
	@PostConstruct
111
	private void create(Composite parent, EMenuService menuService){
112
	    FillLayout layout = new FillLayout();
113
	    layout.marginHeight = 0;
114
	    layout.marginWidth = 0;
115
	    layout.type = SWT.VERTICAL;
116

    
117
	    parent.setLayout(layout);
118
	    viewer = new TreeViewer(parent);
119
	    viewer.getControl().setLayoutData(LayoutConstants.FILL());
120

    
121
	    viewer.setContentProvider(new TaxonNavigatorContentProviderE4());
122
        viewer.setLabelProvider(new TaxonNavigatorLabelProviderE4());
123
        viewer.addDoubleClickListener(event->{
124
            ISelection selection = event.getSelection();
125
            if(selection instanceof IStructuredSelection){
126
                Object firstElement = ((IStructuredSelection) selection).getFirstElement();
127
                if(firstElement instanceof ICdmBase){
128
                    NavigationUtil.openEditor((ICdmBase) firstElement, viewer.getControl().getShell());
129
                }
130
            }
131
        });
132

    
133
        //propagate selection
134
        selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
135
        viewer.addSelectionChangedListener(selectionChangedListener);
136

    
137
        //create context menu
138
        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.navigator.popupmenu.taxonnavigator");
139

    
140
	    init();
141
	}
142

    
143
	/** {@inheritDoc} */
144
	protected IAdaptable getInitialInput() {
145
		Comparator<TaxonNode> comparator;
146
		if (PreferencesUtil.getSortNodesNaturally()){
147
			comparator = new TaxonNaturalComparator();
148
		} else if (PreferencesUtil.getSortNodesStrictlyAlphabetically()){
149
			comparator = new TaxonNodeByNameComparator();
150
		}else {
151
			comparator = new TaxonNodeByRankAndNameComparator();
152
		}
153
		TaxonNodeNavigatorComparator viewerComparator = new TaxonNodeNavigatorComparator(comparator);
154
		viewer.setComparator(viewerComparator);
155
		//FIXME E4 migrate linking with editor
156
//        setLinkingEnabled(true);
157

    
158
		if (CdmStore.isActive()) {
159

    
160
			// TODO when closing and reopening the taxon navigator
161
			// we do not preserve state. Closing the view, in contrary to
162
			// closing the whole application
163
			// should be handled by the state manager too
164
		    root = new Root(conversation);
165

    
166
			return root;
167
		}
168
		return new EmptyRoot();
169
	}
170

    
171
	public void init() {
172
		if (CdmStore.isActive() && conversation == null) {
173
			conversation = CdmStore.createConversation();
174
			conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
175
		}
176
		if (CdmStore.isActive()) {
177
		    cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
178
		    CdmApplicationState.getCurrentDataChangeService().register(this);
179
		}
180
		CdmStore.getLoginManager().addObserver(this);
181
        viewer.setInput(getInitialInput());
182
	}
183

    
184
	/**
185
	 * Refresh this navigators viewer
186
	 */
187
	public void refresh() {
188
		if(getConversationHolder() != null){
189
			getConversationHolder().bind();
190
			//FIXME : Need to make sure this is a stable fix (ticket 3822)
191
			if(!getConversationHolder().isCompleted()){
192
			    getConversationHolder().commit();
193
			}
194
		}
195
		if(!viewer.getTree().isDisposed()){
196
		    viewer.refresh();
197
		}
198
	}
199

    
200
	/**
201
     * Refresh this navigators viewer
202
     */
203
    public void refresh(Set<?> objects) {
204
        for(Object obj : objects) {
205
            viewer.refresh(obj);
206
        }
207
    }
208

    
209
	/**
210
	 * Removes all content
211
	 */
212
	public void clear() {
213
	    viewer.setInput(new EmptyRoot());
214
	}
215

    
216
	public void restore(IMemento memento, IProgressMonitor monitor) {
217
	    root = new Root(conversation);
218
		if (memento == null) {
219
		    viewer.setInput(root);
220
			return;
221
		}
222
		int mementoWork = 0;
223
		Set<TreePath> treePaths = new HashSet<TreePath>();
224
		IMemento[] treePathMementos = null;
225

    
226
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
227

    
228
		if (treePathsMemento != null) {
229
			treePathMementos = treePathsMemento.getChildren(TREE_PATH);
230
			mementoWork = treePathMementos.length;
231
		}
232
		// begin the monitor with steps for all tree paths and steps for
233
		// creating
234
		// conversation s.o., refreshing the tree and setting the paths
235
		IProgressMonitor subProgressMonitor = NavigationUtil
236
				.getSubProgressMonitor(monitor, 1);
237

    
238
		subProgressMonitor.beginTask(RESTORING_TAXON_NAVIGATOR,
239
				1 + mementoWork + 5);
240
		subProgressMonitor.subTask(RESTORING_TAXON_NAVIGATOR);
241
		subProgressMonitor.worked(1);
242

    
243
		conversation = CdmStore.createConversation();
244
		subProgressMonitor.worked(1);
245
		conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
246
		subProgressMonitor.worked(1);
247
		viewer.setInput(root);
248
		subProgressMonitor.worked(1);
249
		viewer.refresh();
250
		subProgressMonitor.worked(1);
251

    
252
		if (treePathMementos != null && treePathMementos.length > 0) {
253
			for (IMemento treePathMemento : treePathMementos) {
254
				TreePath treePath = createTreePathFromString(treePathMemento
255
						.getID());
256
				if (!subProgressMonitor.isCanceled() && treePath != null) {
257
					treePaths.add(treePath);
258
					subProgressMonitor.worked(1);
259
				}
260
			}
261
		}
262
		if (treePaths.size() > 0) {
263
			TaxonNavigatorE4.this.viewer.setExpandedTreePaths(
264
					treePaths.toArray(new TreePath[0]));
265
			subProgressMonitor.worked(1);
266
		}
267
		subProgressMonitor.done();
268
	}
269

    
270
	private TreePath createTreePathFromString(String string) {
271

    
272
		List<CdmBase> pathList = new ArrayList<CdmBase>();
273

    
274
		if (string.length() == 0) {
275
            return null;
276
        }
277

    
278
		for (String uuid : string.split(" ")) { //$NON-NLS-1$
279
			CdmBase cdmBaseObject = CdmStore.getService(
280
					IClassificationService.class).getTaxonNodeByUuid(
281
					UUID.fromString(uuid));
282
			if (cdmBaseObject == null) {
283
				// is this a tree uuid?
284
				cdmBaseObject = CdmStore.getService(
285
						IClassificationService.class).load(
286
						UUID.fromString(uuid));
287

    
288
				if (cdmBaseObject == null) {
289
                    return null;
290
                }
291
			}
292
			pathList.add(cdmBaseObject);
293
		}
294
		return new TreePath(pathList.toArray());
295
	}
296

    
297
	@Override
298
	public ConversationHolder getConversationHolder() {
299
		return conversation;
300
	}
301

    
302
	/** {@inheritDoc} */
303
	@PreDestroy
304
	public void dispose() {
305
		dataChangeBehavior = null;
306
		if (conversation != null) {
307
			conversation.unregisterForDataStoreChanges(this);
308
		}
309
		if(cdmEntitySession != null) {
310
		    cdmEntitySession.dispose();
311
		}
312
		if(CdmApplicationState.getCurrentDataChangeService() != null) {
313
		    CdmApplicationState.getCurrentDataChangeService().unregister(this);
314
		}
315
	}
316

    
317
	/** {@inheritDoc} */
318
	@Focus
319
	public void setFocus() {
320
		if (getConversationHolder() != null) {
321
			getConversationHolder().bind();
322
		}
323
		if(cdmEntitySession != null) {
324
		    cdmEntitySession.bind();
325
		}
326
	}
327

    
328
	/** {@inheritDoc} */
329
	@Override
330
	public boolean postOperation(CdmBase objectAffectedByOperation) {
331
		// nothing to do here
332
		return true;
333
	}
334

    
335
	@Override
336
	public boolean onComplete() {
337
		return true;
338
	}
339

    
340
	@Override
341
	public void update(Observable o, Object arg) {
342
		if(o instanceof LoginManager){
343
			refresh();
344
		}
345
	}
346
	   /** {@inheritDoc} */
347
    @Override
348
    public void update(CdmDataChangeMap changeEvents) {
349
        if (dataChangeBehavior == null) {
350
            dataChangeBehavior = new TaxonNavigatorDataChangeBehaviorE4(this);
351
        }
352

    
353
        DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
354
    }
355

    
356
    @Override
357
    public ICdmEntitySession getCdmEntitySession() {
358
       return cdmEntitySession;
359
    }
360

    
361
    @Override
362
    public List<ITreeNode> getRootEntities() {
363
        if(root != null) {
364
            return root.getParentBeans();
365
        }
366
        return null;
367
    }
368

    
369
    @Override
370
    public void onChange(CdmChangeEvent event) {
371
        refresh();
372
        for(CdmBase cb : event.getChangedObjects()) {
373
        	if(cb instanceof TaxonNode) {
374
                TaxonNode tn = (TaxonNode)cb;
375
                if(tn.getTaxon() == null) {
376
                    viewer.refresh(tn.getClassification());
377
                } else {
378
                    viewer.refresh(cb);
379
                }
380
            } else if (cb instanceof Classification) {
381
                viewer.refresh();
382
            }
383
        }
384
    }
385

    
386
    @Override
387
    public Map<Object, List<String>> getPropertyPathsMap() {
388
        Map<Object, List<String>> propertyPathsMap = new HashMap<Object, List<String>>();
389
        List<String> taxonNodePropertyPaths = Arrays.asList(new String[] {
390
                "taxon.name" //$NON-NLS-1$
391
        });
392
         propertyPathsMap.put("childNodes", taxonNodePropertyPaths); //$NON-NLS-1$
393
        return propertyPathsMap;
394
    }
395

    
396
    /**
397
     * {@inheritDoc}
398
     */
399
    @Override
400
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
401
        // TODO Auto-generated method stub
402

    
403
    }
404

    
405
    /**
406
     * {@inheritDoc}
407
     */
408
    @Override
409
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
410
    }
411

    
412
    /**
413
     * {@inheritDoc}
414
     */
415
    @Override
416
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
417
        if(viewer!=null){
418
            init();
419
        }
420
    }
421

    
422
    /**
423
     * {@inheritDoc}
424
     */
425
    @Override
426
    public void contextRefresh(IProgressMonitor monitor) {
427
    }
428

    
429
    /**
430
     * {@inheritDoc}
431
     */
432
    @Override
433
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
434
    }
435
}
(3-3/4)