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