Project

General

Profile

Download (13.3 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.ITreeNode;
51
import eu.etaxonomy.cdm.model.taxon.Classification;
52
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
53
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
54
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByNameComparator;
55
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByRankAndNameComparator;
56
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
57
import eu.etaxonomy.taxeditor.editor.EditorUtil;
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
 * Taxonomic tree implementation using Common Navigator Framework.
76
 *
77
 * @author p.ciardelli
78
 * @author n.hoffmann
79
 * @created 02.06.2009
80
 * @version 1.0+-
81
 */
82
public class TaxonNavigatorE4 implements
83
		IPostOperationEnabled, IConversationEnabled, Observer,
84
		ICdmEntitySessionEnabled, ICdmChangeListener, IContextListener {
85

    
86
    private static final String RESTORING_TAXON_NAVIGATOR = Messages.TaxonNavigator_RESTORE;
87

    
88
	private static final String TREE_PATH = "treepath"; //$NON-NLS-1$
89

    
90
	private static final String TREE_PATHS = "treepaths"; //$NON-NLS-1$
91

    
92
	private ConversationHolder conversation;
93

    
94
	private ICdmEntitySession cdmEntitySession;
95

    
96
	private String partNameCache;
97

    
98
	private IDataChangeBehavior dataChangeBehavior;
99

    
100
	private Root root;
101

    
102
	private TreeViewer viewer;
103

    
104
    @Inject
105
    private ESelectionService selService;
106

    
107
    private ISelectionChangedListener selectionChangedListener;
108

    
109
	@Inject
110
    public TaxonNavigatorE4() {
111
	    CdmStore.getContextManager().addContextListener(this);
112
    }
113

    
114
	@PostConstruct
115
	private void create(Composite parent, EMenuService menuService){
116
	    FillLayout layout = new FillLayout();
117
	    layout.marginHeight = 0;
118
	    layout.marginWidth = 0;
119
	    layout.type = SWT.VERTICAL;
120

    
121
	    parent.setLayout(layout);
122
	    viewer = new TreeViewer(parent);
123
	    viewer.getControl().setLayoutData(LayoutConstants.FILL());
124

    
125
	    viewer.setContentProvider(new TaxonNavigatorContentProviderE4());
126
        viewer.setLabelProvider(new TaxonNavigatorLabelProviderE4());
127
        viewer.addDoubleClickListener(event->{
128
            ISelection selection = event.getSelection();
129
            if(selection instanceof IStructuredSelection){
130
                Object firstElement = ((IStructuredSelection) selection).getFirstElement();
131
                    try {
132
                        if(firstElement instanceof TaxonNode){
133
                            EditorUtil.openTaxonNodeE4(((TaxonNode) firstElement).getUuid());
134
                        }
135
                        else if(firstElement instanceof Classification){
136
                            NavigationUtil.openClassificationWizard((Classification) firstElement, viewer.getControl().getShell());
137
                        }
138
                    } catch (Exception e) {
139
                        // TODO Auto-generated catch block
140
                        e.printStackTrace();
141
                    }
142
            }
143
        });
144

    
145
        //propagate selection
146
        selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
147
        viewer.addSelectionChangedListener(selectionChangedListener);
148

    
149
        //create context menu
150
        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.navigator.popupmenu.taxonnavigator");
151

    
152
	    init();
153
	}
154

    
155
	/** {@inheritDoc} */
156
	protected IAdaptable getInitialInput() {
157
		Comparator<TaxonNode> comparator;
158
		if (PreferencesUtil.getSortNodesNaturally()){
159
			comparator = new TaxonNaturalComparator();
160
		} else if (PreferencesUtil.getSortNodesStrictlyAlphabetically()){
161
			comparator = new TaxonNodeByNameComparator();
162
		}else {
163
			comparator = new TaxonNodeByRankAndNameComparator();
164
		}
165
		TaxonNodeNavigatorComparator viewerComparator = new TaxonNodeNavigatorComparator(comparator);
166
		viewer.setComparator(viewerComparator);
167
		//FIXME E4 migrate linking with editor
168
//        setLinkingEnabled(true);
169

    
170
		if (CdmStore.isActive()) {
171

    
172
			// TODO when closing and reopening the taxon navigator
173
			// we do not preserve state. Closing the view, in contrary to
174
			// closing the whole application
175
			// should be handled by the state manager too
176
		    root = new Root(conversation);
177

    
178
			return root;
179
		}
180
		return new EmptyRoot();
181
	}
182

    
183
	public void init() {
184
		if (CdmStore.isActive() && conversation == null) {
185
			conversation = CdmStore.createConversation();
186
			conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
187
		}
188
		if (CdmStore.isActive()) {
189
		    cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
190
		    CdmApplicationState.getCurrentDataChangeService().register(this);
191
		}
192
		CdmStore.getLoginManager().addObserver(this);
193
        viewer.setInput(getInitialInput());
194
	}
195

    
196
	/**
197
	 * Refresh this navigators viewer
198
	 */
199
	public void refresh() {
200
		if(getConversationHolder() != null){
201
			getConversationHolder().bind();
202
			//FIXME : Need to make sure this is a stable fix (ticket 3822)
203
			if(!getConversationHolder().isCompleted()){
204
			    getConversationHolder().commit();
205
			}
206
		}
207
		if(!viewer.getTree().isDisposed()){
208
		    viewer.refresh();
209
		}
210
	}
211

    
212
	/**
213
     * Refresh this navigators viewer
214
     */
215
    public void refresh(Set<?> objects) {
216
        for(Object obj : objects) {
217
            viewer.refresh(obj);
218
        }
219
    }
220

    
221
	/**
222
	 * Removes all content
223
	 */
224
	public void clear() {
225
	    viewer.setInput(new EmptyRoot());
226
	}
227

    
228
	public void restore(IMemento memento, IProgressMonitor monitor) {
229
	    root = new Root(conversation);
230
		if (memento == null) {
231
		    viewer.setInput(root);
232
			return;
233
		}
234
		int mementoWork = 0;
235
		Set<TreePath> treePaths = new HashSet<TreePath>();
236
		IMemento[] treePathMementos = null;
237

    
238
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
239

    
240
		if (treePathsMemento != null) {
241
			treePathMementos = treePathsMemento.getChildren(TREE_PATH);
242
			mementoWork = treePathMementos.length;
243
		}
244
		// begin the monitor with steps for all tree paths and steps for
245
		// creating
246
		// conversation s.o., refreshing the tree and setting the paths
247
		IProgressMonitor subProgressMonitor = NavigationUtil
248
				.getSubProgressMonitor(monitor, 1);
249

    
250
		subProgressMonitor.beginTask(RESTORING_TAXON_NAVIGATOR,
251
				1 + mementoWork + 5);
252
		subProgressMonitor.subTask(RESTORING_TAXON_NAVIGATOR);
253
		subProgressMonitor.worked(1);
254

    
255
		conversation = CdmStore.createConversation();
256
		subProgressMonitor.worked(1);
257
		conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
258
		subProgressMonitor.worked(1);
259
		viewer.setInput(root);
260
		subProgressMonitor.worked(1);
261
		viewer.refresh();
262
		subProgressMonitor.worked(1);
263

    
264
		if (treePathMementos != null && treePathMementos.length > 0) {
265
			for (IMemento treePathMemento : treePathMementos) {
266
				TreePath treePath = createTreePathFromString(treePathMemento
267
						.getID());
268
				if (!subProgressMonitor.isCanceled() && treePath != null) {
269
					treePaths.add(treePath);
270
					subProgressMonitor.worked(1);
271
				}
272
			}
273
		}
274
		if (treePaths.size() > 0) {
275
			TaxonNavigatorE4.this.viewer.setExpandedTreePaths(
276
					treePaths.toArray(new TreePath[0]));
277
			subProgressMonitor.worked(1);
278
		}
279
		subProgressMonitor.done();
280
	}
281

    
282
	private TreePath createTreePathFromString(String string) {
283

    
284
		List<CdmBase> pathList = new ArrayList<CdmBase>();
285

    
286
		if (string.length() == 0) {
287
            return null;
288
        }
289

    
290
		for (String uuid : string.split(" ")) { //$NON-NLS-1$
291
			CdmBase cdmBaseObject = CdmStore.getService(
292
					IClassificationService.class).getTaxonNodeByUuid(
293
					UUID.fromString(uuid));
294
			if (cdmBaseObject == null) {
295
				// is this a tree uuid?
296
				cdmBaseObject = CdmStore.getService(
297
						IClassificationService.class).load(
298
						UUID.fromString(uuid));
299

    
300
				if (cdmBaseObject == null) {
301
                    return null;
302
                }
303
			}
304
			pathList.add(cdmBaseObject);
305
		}
306
		return new TreePath(pathList.toArray());
307
	}
308

    
309
	@Override
310
	public ConversationHolder getConversationHolder() {
311
		return conversation;
312
	}
313

    
314
	/** {@inheritDoc} */
315
	@PreDestroy
316
	public void dispose() {
317
		dataChangeBehavior = null;
318
		if (conversation != null) {
319
			conversation.unregisterForDataStoreChanges(this);
320
		}
321
		if(cdmEntitySession != null) {
322
		    cdmEntitySession.dispose();
323
		}
324
		if(CdmApplicationState.getCurrentDataChangeService() != null) {
325
		    CdmApplicationState.getCurrentDataChangeService().unregister(this);
326
		}
327
	}
328

    
329
	/** {@inheritDoc} */
330
	@Focus
331
	public void setFocus() {
332
		if (getConversationHolder() != null) {
333
			getConversationHolder().bind();
334
		}
335
		if(cdmEntitySession != null) {
336
		    cdmEntitySession.bind();
337
		}
338
	}
339

    
340
	/** {@inheritDoc} */
341
	@Override
342
	public boolean postOperation(CdmBase objectAffectedByOperation) {
343
		// nothing to do here
344
		return true;
345
	}
346

    
347
	@Override
348
	public boolean onComplete() {
349
		return true;
350
	}
351

    
352
	@Override
353
	public void update(Observable o, Object arg) {
354
		if(o instanceof LoginManager){
355
			refresh();
356
		}
357
	}
358
	   /** {@inheritDoc} */
359
    @Override
360
    public void update(CdmDataChangeMap changeEvents) {
361
        if (dataChangeBehavior == null) {
362
            dataChangeBehavior = new TaxonNavigatorDataChangeBehaviorE4(this);
363
        }
364

    
365
        DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
366
    }
367

    
368
    @Override
369
    public ICdmEntitySession getCdmEntitySession() {
370
       return cdmEntitySession;
371
    }
372

    
373
    @Override
374
    public List<ITreeNode> getRootEntities() {
375
        if(root != null) {
376
            return root.getParentBeans();
377
        }
378
        return null;
379
    }
380

    
381
    @Override
382
    public void onChange(CdmChangeEvent event) {
383
        refresh();
384
        for(CdmBase cb : event.getChangedObjects()) {
385
        	if(cb instanceof TaxonNode) {
386
                TaxonNode tn = (TaxonNode)cb;
387
                if(tn.getTaxon() == null) {
388
                    viewer.refresh(tn.getClassification());
389
                } else {
390
                    viewer.refresh(cb);
391
                }
392
            } else if (cb instanceof Classification) {
393
                viewer.refresh();
394
            }
395
        }
396
    }
397

    
398
    @Override
399
    public Map<Object, List<String>> getPropertyPathsMap() {
400
        Map<Object, List<String>> propertyPathsMap = new HashMap<Object, List<String>>();
401
        List<String> taxonNodePropertyPaths = Arrays.asList(new String[] {
402
                "taxon.name" //$NON-NLS-1$
403
        });
404
         propertyPathsMap.put("childNodes", taxonNodePropertyPaths); //$NON-NLS-1$
405
        return propertyPathsMap;
406
    }
407

    
408
    /**
409
     * {@inheritDoc}
410
     */
411
    @Override
412
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
413
        // TODO Auto-generated method stub
414

    
415
    }
416

    
417
    /**
418
     * {@inheritDoc}
419
     */
420
    @Override
421
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
422
    }
423

    
424
    /**
425
     * {@inheritDoc}
426
     */
427
    @Override
428
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
429
        if(viewer!=null){
430
            init();
431
        }
432
    }
433

    
434
    /**
435
     * {@inheritDoc}
436
     */
437
    @Override
438
    public void contextRefresh(IProgressMonitor monitor) {
439
    }
440

    
441
    /**
442
     * {@inheritDoc}
443
     */
444
    @Override
445
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
446
    }
447
}
(3-3/4)