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