Project

General

Profile

Download (12.9 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
        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.store.menu.import");
140

    
141
	    init();
142
	}
143

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

    
159
		if (CdmStore.isActive()) {
160

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

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

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

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

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

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

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

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

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

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

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

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

    
271
	private TreePath createTreePathFromString(String string) {
272

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
404
    }
405

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

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

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

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