- not running imports and exports deleted from menu
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / navigator / TaxonNavigator.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.taxeditor.navigation.navigator;
12
13 import java.util.ArrayList;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Observable;
17 import java.util.Observer;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.eclipse.core.runtime.IAdaptable;
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.jface.viewers.DoubleClickEvent;
24 import org.eclipse.jface.viewers.IStructuredSelection;
25 import org.eclipse.jface.viewers.SelectionChangedEvent;
26 import org.eclipse.jface.viewers.TreePath;
27 import org.eclipse.ui.IMemento;
28 import org.eclipse.ui.IViewSite;
29 import org.eclipse.ui.PartInitException;
30 import org.eclipse.ui.navigator.CommonNavigator;
31 import org.eclipse.jface.viewers.ISelectionChangedListener;
32
33 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
34 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
35 import eu.etaxonomy.cdm.api.service.IClassificationService;
36 import eu.etaxonomy.cdm.model.common.CdmBase;
37 import eu.etaxonomy.cdm.model.description.FeatureTree;
38 import eu.etaxonomy.cdm.model.taxon.TaxonComparatorSearch;
39 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
40 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
41 import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
42 import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
43 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
44 import eu.etaxonomy.taxeditor.store.CdmStore;
45 import eu.etaxonomy.taxeditor.store.LoginManager;
46
47 /**
48 * Taxonomic tree implementation using Common Navigator Framework.
49 *
50 * @author p.ciardelli
51 * @author n.hoffmann
52 * @created 02.06.2009
53 * @version 1.0
54 */
55 public class TaxonNavigator extends CommonNavigator implements
56 IPostOperationEnabled, IConversationEnabled, Observer {
57
58 /**
59 * Constant
60 * <code>ID="eu.etaxonomy.taxeditor.navigation.navig"{trunked}</code>
61 */
62 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator"; //$NON-NLS-1$
63
64 private static final String TREE_PATH = "treepath";
65
66 private static final String TREE_PATHS = "treepaths";
67
68 private ConversationHolder conversation;
69
70 private String partNameCache;
71
72 private IDataChangeBehavior dataChangeBehavior;
73
74 /*
75 * (non-Javadoc)
76 *
77 * @see org.eclipse.ui.navigator.CommonNavigator#getInitialInput()
78 */
79 /** {@inheritDoc} */
80 @Override
81 protected IAdaptable getInitialInput() {
82
83 TaxonComparatorSearch comparator = new TaxonComparatorSearch();
84 TaxonNodeComparator viewerComparator = new TaxonNodeComparator(comparator);
85 this.getCommonViewer().setComparator(viewerComparator);
86 this.getCommonViewer().addSelectionChangedListener(new ISelectionChangedListener() {
87
88 @Override
89 public void selectionChanged(SelectionChangedEvent arg0) {
90 IStructuredSelection selection = (IStructuredSelection) getCommonViewer().getSelection();
91
92 Object firstElement = selection.getFirstElement();
93 NavigationUtil.executeEditHandler();
94
95 }
96 } );
97
98 if (CdmStore.isActive()) {
99
100 // TODO when closing and reopening the taxon navigator
101 // we do not preserve state. Closing the view, in contrary to
102 // closing the whole application
103 // should be handled by the state manager too
104
105 return new Root(conversation);
106 }
107 return new EmptyRoot();
108 }
109
110 /** {@inheritDoc} */
111 @Override
112 public void init(IViewSite site) throws PartInitException {
113 super.init(site);
114 init();
115
116 }
117
118 /**
119 * <p>
120 * init
121 * </p>
122 */
123 public void init() {
124 if (CdmStore.isActive() && conversation == null) {
125 conversation = CdmStore.createConversation();
126 conversation.registerForDataStoreChanges(TaxonNavigator.this);
127 }
128 CdmStore.getLoginManager().addObserver(this);
129
130 }
131
132 /**
133 * Refresh this navigators viewer
134 */
135 public void refresh() {
136 if(getConversationHolder() != null){
137 getConversationHolder().bind();
138 //FIXME : Need to make sure this is a stable fix (ticket 3822)
139 if(!getConversationHolder().isCompleted()){
140 getConversationHolder().commit();
141 }
142 }
143 getCommonViewer().refresh();
144 }
145
146 /**
147 * Removes all content
148 */
149 public void clear() {
150 getCommonViewer().setInput(new EmptyRoot());
151 }
152
153 /**
154 * <p>
155 * restore
156 * </p>
157 *
158 * @param memento
159 * a {@link org.eclipse.ui.IMemento} object.
160 * @param monitor
161 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
162 */
163 public void restore(IMemento memento, IProgressMonitor monitor) {
164 if (memento == null) {
165 getCommonViewer().setInput(new Root(conversation));
166 return;
167 }
168 int mementoWork = 0;
169 Set<TreePath> treePaths = new HashSet<TreePath>();
170 IMemento[] treePathMementos = null;
171
172 IMemento treePathsMemento = memento.getChild(TREE_PATHS);
173
174 if (treePathsMemento != null) {
175 treePathMementos = treePathsMemento.getChildren(TREE_PATH);
176 mementoWork = treePathMementos.length;
177 }
178 // begin the monitor with steps for all tree paths and steps for
179 // creating
180 // conversation s.o., refreshing the tree and setting the paths
181 IProgressMonitor subProgressMonitor = NavigationUtil
182 .getSubProgressMonitor(monitor, 1);
183
184 subProgressMonitor.beginTask("Restoring Taxon Navigator",
185 1 + mementoWork + 5);
186 subProgressMonitor.subTask("Restoring Taxon Navigator");
187 subProgressMonitor.worked(1);
188
189 conversation = CdmStore.createConversation();
190 subProgressMonitor.worked(1);
191 conversation.registerForDataStoreChanges(TaxonNavigator.this);
192 subProgressMonitor.worked(1);
193 getCommonViewer().setInput(new Root(conversation));
194 subProgressMonitor.worked(1);
195 getCommonViewer().refresh();
196 subProgressMonitor.worked(1);
197
198 if (treePathMementos != null && treePathMementos.length > 0) {
199 for (IMemento treePathMemento : treePathMementos) {
200 TreePath treePath = createTreePathFromString(treePathMemento
201 .getID());
202 if (!subProgressMonitor.isCanceled() && treePath != null) {
203 treePaths.add(treePath);
204 subProgressMonitor.worked(1);
205 }
206 }
207 }
208 if (treePaths.size() > 0) {
209 TaxonNavigator.this.getCommonViewer().setExpandedTreePaths(
210 treePaths.toArray(new TreePath[0]));
211 subProgressMonitor.worked(1);
212 }
213 subProgressMonitor.done();
214 }
215
216 /**
217 * @param string
218 * @return
219 */
220 private TreePath createTreePathFromString(String string) {
221
222 List<CdmBase> pathList = new ArrayList<CdmBase>();
223
224 if (string.length() == 0) {
225 return null;
226 }
227
228 for (String uuid : string.split(" ")) {
229 CdmBase cdmBaseObject = CdmStore.getService(
230 IClassificationService.class).getTaxonNodeByUuid(
231 UUID.fromString(uuid));
232 if (cdmBaseObject == null) {
233 // is this a tree uuid?
234 cdmBaseObject = CdmStore.getService(
235 IClassificationService.class).load(
236 UUID.fromString(uuid));
237
238 if (cdmBaseObject == null) {
239 return null;
240 }
241 }
242 pathList.add(cdmBaseObject);
243 }
244 return new TreePath(pathList.toArray());
245 }
246
247 /** {@inheritDoc} */
248 @Override
249 public void saveState(IMemento aMemento) {
250 //
251 }
252
253 /**
254 * <p>
255 * saveTreeState
256 * </p>
257 *
258 * @param memento
259 * a {@link org.eclipse.ui.IMemento} object.
260 * @param progressMonitor
261 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
262 */
263 public void saveTreeState(IMemento memento, IProgressMonitor progressMonitor) {
264 if (memento == null) {
265 return;
266 }
267 IProgressMonitor monitor = NavigationUtil.getSubProgressMonitor(
268 progressMonitor, 1);
269
270 super.saveState(memento);
271
272 memento = memento.createChild(TREE_PATHS);
273 TreePath[] treePaths = this.getCommonViewer().getExpandedTreePaths();
274
275 monitor.beginTask("Saving Taxon Navigator State", treePaths.length);
276
277 for (TreePath treePath : treePaths) {
278 int pathLength = treePath.getSegmentCount();
279 String path = "";
280 for (int i = 0; i < pathLength; i++) {
281 Object segment = treePath.getSegment(i);
282 if (segment instanceof CdmBase) {
283 path += ((CdmBase) segment).getUuid().toString() + " ";
284 monitor.worked(1);
285 } else {
286 NavigationUtil.warn(getClass(),
287 "Non-taxon tree path segment " + segment);
288 }
289 }
290 memento.createChild(TREE_PATH, path.trim());
291 }
292 monitor.done();
293 }
294
295 /*
296 * (non-Javadoc)
297 *
298 * @see
299 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
300 * ()
301 */
302 /**
303 * <p>
304 * getConversationHolder
305 * </p>
306 *
307 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
308 * object.
309 */
310 @Override
311 public ConversationHolder getConversationHolder() {
312 return conversation;
313 }
314
315 /*
316 * (non-Javadoc)
317 *
318 * @see
319 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update
320 * (eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
321 */
322 /** {@inheritDoc} */
323 @Override
324 public void update(CdmDataChangeMap changeEvents) {
325 if (dataChangeBehavior == null) {
326 dataChangeBehavior = new TaxonNavigatorDataChangeBehavior(this);
327 }
328
329 DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
330 }
331
332 /** {@inheritDoc} */
333 @Override
334 public String getFrameToolTipText(Object element) {
335 if (element instanceof Root) {
336 return "Taxonomic Tree";
337 }
338 return super.getFrameToolTipText(element);
339 }
340
341 /*
342 * (non-Javadoc)
343 *
344 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
345 */
346 /** {@inheritDoc} */
347 @Override
348 public void dispose() {
349 super.dispose();
350 dataChangeBehavior = null;
351 if (conversation != null) {
352 conversation.unregisterForDataStoreChanges(this);
353 }
354 }
355
356 /*
357 * (non-Javadoc)
358 *
359 * @see org.eclipse.ui.navigator.CommonNavigator#setFocus()
360 */
361 /** {@inheritDoc} */
362 @Override
363 public void setFocus() {
364 // logger.warn("Setting focus to navigator");
365 super.setFocus();
366 if (getConversationHolder() != null) {
367 getConversationHolder().bind();
368 }
369 }
370
371 /*
372 * (non-Javadoc)
373 *
374 * @see
375 * eu.etaxonomy.taxeditor.operations.IPostOperationEnabled#postOperation
376 * (eu.etaxonomy.cdm.model.common.CdmBase)
377 */
378 /** {@inheritDoc} */
379 @Override
380 public boolean postOperation(CdmBase objectAffectedByOperation) {
381 // nothing to do here
382 return true;
383 }
384
385 /**
386 * <p>
387 * save
388 * </p>
389 *
390 * @param memento
391 * a {@link org.eclipse.ui.IMemento} object.
392 * @param monitor
393 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
394 */
395 public void save(IMemento memento, IProgressMonitor monitor) {
396 saveTreeState(memento, monitor);
397 if (conversation != null) {
398 conversation.unregisterForDataStoreChanges(this);
399 conversation = null;
400 }
401 }
402
403 /** {@inheritDoc} */
404 @Override
405 protected void handleDoubleClick(DoubleClickEvent anEvent) {
406 NavigationUtil.executeEditHandler();
407 // If the double click is passed up to the super-class it will
408 // expand/collapse trees.
409 // We do not want that
410 // super.handleDoubleClick(anEvent);
411 }
412
413 /**
414 * <p>
415 * onComplete
416 * </p>
417 *
418 * @return a boolean.
419 */
420 @Override
421 public boolean onComplete() {
422 return true;
423 }
424
425 /*
426 * (non-Javadoc)
427 *
428 * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
429 */
430 /** {@inheritDoc} */
431 @Override
432 public void showBusy(boolean busy) {
433 super.showBusy(busy);
434 getCommonViewer().getControl().setEnabled(!busy);
435 if (busy) {
436 partNameCache = getPartName();
437 setPartName("Loading datasources");
438 } else {
439 if (partNameCache != null) {
440 setPartName(partNameCache);
441 }
442 }
443 }
444
445
446 /* (non-Javadoc)
447 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
448 */
449 @Override
450 public void update(Observable o, Object arg) {
451 if(o instanceof LoginManager){
452 refresh();
453 }
454
455 }
456 }