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