ref #6909 Remove unused class variable
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / navigator / e4 / TaxonNavigatorE4.java
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 }