e10a6488ebc67b0c259c24d621cb80d624b9ab6b
[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.TreePath;
25 import org.eclipse.ui.IMemento;
26 import org.eclipse.ui.IViewSite;
27 import org.eclipse.ui.PartInitException;
28 import org.eclipse.ui.navigator.CommonNavigator;
29
30 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
31 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
32 import eu.etaxonomy.cdm.api.service.IClassificationService;
33 import eu.etaxonomy.cdm.model.common.CdmBase;
34 import eu.etaxonomy.cdm.model.taxon.TaxonComparatorSearch;
35 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
36 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
37 import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
38 import eu.etaxonomy.taxeditor.model.MessagingUtils;
39 import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
40 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
41 import eu.etaxonomy.taxeditor.store.CdmStore;
42 import eu.etaxonomy.taxeditor.store.LoginManager;
43
44 /**
45 * Taxonomic tree implementation using Common Navigator Framework.
46 *
47 * @author p.ciardelli
48 * @author n.hoffmann
49 * @created 02.06.2009
50 * @version 1.0
51 */
52 public class TaxonNavigator extends CommonNavigator implements
53 IPostOperationEnabled, IConversationEnabled, Observer {
54
55 /**
56 * Constant
57 * <code>ID="eu.etaxonomy.taxeditor.navigation.navig"{trunked}</code>
58 */
59 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator"; //$NON-NLS-1$
60
61 private static final String TREE_PATH = "treepath";
62
63 private static final String TREE_PATHS = "treepaths";
64
65 private ConversationHolder conversation;
66
67 private String partNameCache;
68
69 private IDataChangeBehavior dataChangeBehavior;
70
71 /*
72 * (non-Javadoc)
73 *
74 * @see org.eclipse.ui.navigator.CommonNavigator#getInitialInput()
75 */
76 /** {@inheritDoc} */
77 @Override
78 protected IAdaptable getInitialInput() {
79
80 TaxonComparatorSearch comparator = new TaxonComparatorSearch();
81 TaxonNodeComparator viewerComparator = new TaxonNodeComparator(comparator);
82 this.getCommonViewer().setComparator(viewerComparator);
83 setLinkingEnabled(true);
84 // this.getCommonViewer().addSelectionChangedListener(new ISelectionChangedListener() {
85 //
86 // @Override
87 // public void selectionChanged(SelectionChangedEvent arg0) {
88 // IStructuredSelection selection = (IStructuredSelection) getCommonViewer().getSelection();
89 //
90 // Object firstElement = selection.getFirstElement();
91 // //
92 // if (!(firstElement instanceof Classification)){
93 // //NavigationUtil.selectInNavigator(firstElement, null);
94 // NavigationUtil.openEditor(firstElement);
95 // }
96 //
97 // }
98 // } );
99
100 if (CdmStore.isActive()) {
101
102 // TODO when closing and reopening the taxon navigator
103 // we do not preserve state. Closing the view, in contrary to
104 // closing the whole application
105 // should be handled by the state manager too
106
107 return new Root(conversation);
108 }
109 return new EmptyRoot();
110 }
111
112 /** {@inheritDoc} */
113 @Override
114 public void init(IViewSite site) throws PartInitException {
115 super.init(site);
116 init();
117 }
118
119 /**
120 * <p>
121 * init
122 * </p>
123 */
124 public void init() {
125 if (CdmStore.isActive() && conversation == null) {
126 conversation = CdmStore.createConversation();
127 conversation.registerForDataStoreChanges(TaxonNavigator.this);
128 }
129 CdmStore.getLoginManager().addObserver(this);
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 MessagingUtils.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 }