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