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