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