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