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