(no commit message)
[taxeditor.git] / 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.lang.reflect.InvocationTargetException;
14 import java.util.ArrayList;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import org.apache.log4j.Logger;
21 import org.eclipse.core.commands.Command;
22 import org.eclipse.core.commands.common.NotDefinedException;
23 import org.eclipse.core.runtime.IAdaptable;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
26 import org.eclipse.jface.operation.IRunnableWithProgress;
27 import org.eclipse.jface.viewers.DoubleClickEvent;
28 import org.eclipse.jface.viewers.TreePath;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.ui.IMemento;
31 import org.eclipse.ui.IViewSite;
32 import org.eclipse.ui.PartInitException;
33 import org.eclipse.ui.commands.ICommandService;
34 import org.eclipse.ui.handlers.IHandlerService;
35 import org.eclipse.ui.navigator.CommonNavigator;
36
37 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
38 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
39 import eu.etaxonomy.cdm.model.common.CdmBase;
40 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
41 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
42 import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
43 import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
44 import eu.etaxonomy.taxeditor.operations.IPostOperationEnabled;
45 import eu.etaxonomy.taxeditor.store.CdmStore;
46
47 /**
48 * Taxonomic tree implementation using Common Navigator Framework.
49 *
50 * @author p.ciardelli
51 * @created 02.06.2009
52 * @version 1.0
53 */
54 public class TaxonNavigator extends CommonNavigator implements IPostOperationEnabled, IConversationEnabled{
55 private static final Logger logger = Logger
56 .getLogger(TaxonNavigator.class);
57
58 public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator"; //$NON-NLS-1$
59
60 public static final String OPEN_COMMAND_ID = "eu.etaxonomy.taxeditor.navigation.command.editSelection";
61
62 private static final String TREE_PATH = "treepath";
63
64 private static final String TREE_PATHS = "treepaths";
65
66 private ConversationHolder conversation;
67
68 private IDataChangeBehavior dataChangeBehavior;
69
70 /* (non-Javadoc)
71 * @see org.eclipse.ui.navigator.CommonNavigator#getInitialInput()
72 */
73 @Override
74 protected IAdaptable getInitialInput() {
75 if(CdmStore.isActive()){
76 // TODO when closing and reopening the taxon navigator
77 // we do not preserve state. Closing the view, in contrary to closing the whole application
78 // should be handled by the state manager too
79 return new Root();
80 }
81 return new EmptyRoot();
82 }
83
84 /**
85 *
86 */
87 public void init(IViewSite site)
88 throws PartInitException {
89 super.init(site);
90 if(CdmStore.isActive() && conversation == null){
91 conversation = CdmStore.createConversation();
92 conversation.registerForDataStoreChanges(TaxonNavigator.this);
93 }
94 }
95
96 /**
97 * Refresh this navigators viewer
98 */
99 public void refresh(){
100 logger.warn("Refreshing navigator");
101 getConversationHolder().bind();
102 this.getCommonViewer().refresh();
103 }
104
105 /**
106 *
107 * @param memento
108 */
109 public void restore(final IMemento memento) {
110
111 ProgressMonitorDialog progressMonitorDialog = new ProgressMonitorDialog(NavigationUtil.getShell());
112 IRunnableWithProgress runnable = new IRunnableWithProgress() {
113
114 @Override
115 public void run(IProgressMonitor monitor) throws InvocationTargetException,
116 InterruptedException {
117 monitor.setTaskName("Restoring Taxon Navigator");
118 int mementoWork = 0;
119 Set<TreePath> treePaths = new HashSet<TreePath>();
120 IMemento[] treePathMementos = null;
121 if (memento != null) {
122
123
124 IMemento treePathsMemento = memento.getChild(TREE_PATHS);
125
126 if (treePathsMemento != null) {
127 treePathMementos = treePathsMemento.getChildren(TREE_PATH);
128 mementoWork = treePathMementos.length;
129 }
130 }
131 // begin the monitor with steps for all tree paths and steps for creating
132 // conversation s.o., refreshing the tree and setting the paths
133 monitor.beginTask("Restoring Taxon Navigator", 1 + mementoWork + 5);
134 monitor.worked(1);
135
136 conversation = CdmStore.createConversation();
137 monitor.worked(1);
138 conversation.registerForDataStoreChanges(TaxonNavigator.this);
139 monitor.worked(1);
140 TaxonNavigator.this.getCommonViewer().setInput(new Root());
141 monitor.worked(1);
142 TaxonNavigator.this.getCommonViewer().refresh();
143 monitor.worked(1);
144
145
146
147 if (treePathMementos != null && treePathMementos.length > 0) {
148 for (IMemento treePathMemento : treePathMementos) {
149 TreePath treePath = createTreePathFromString(treePathMemento.getID());
150 if (!monitor.isCanceled() && treePath != null) {
151 treePaths.add(treePath);
152 monitor.worked(1);
153 }
154 }
155 }
156 if (treePaths.size() > 0) {
157 TaxonNavigator.this.getCommonViewer().setExpandedTreePaths(treePaths.toArray(new TreePath[0]));
158 monitor.worked(1);
159 }
160 monitor.done();
161 }
162 };
163
164 try {
165 progressMonitorDialog.run(false, true, runnable);
166 } catch (InvocationTargetException e) {
167 logger.error("InvocationTargetException when trying to restore navigator", e);
168 } catch (InterruptedException e) {
169 logger.error("InterruptedException when trying to restore navigator", e);
170 }
171 }
172
173 /**
174 * @param string
175 * @return
176 */
177 private TreePath createTreePathFromString(String string) {
178
179 List<CdmBase> pathList = new ArrayList<CdmBase>();
180
181 if(string.length() == 0) return null;
182
183 for (String uuid : string.split(" ")) {
184 CdmBase cdmBaseObject = CdmStore.getTaxonTreeService().getTaxonNodeByUuid(UUID.fromString(uuid));
185 if (cdmBaseObject == null) {
186 // is this a tree uuid?
187 cdmBaseObject = CdmStore.getTaxonTreeService().getTaxonomicTreeByUuid(UUID.fromString(uuid));
188
189 if(cdmBaseObject == null) return null;
190 }
191 pathList.add(cdmBaseObject);
192 }
193 return new TreePath(pathList.toArray());
194 }
195
196
197 @Override
198 public void saveState(IMemento aMemento) {
199 //
200 }
201
202 public void saveTreeState(IMemento memento) {
203
204 if (memento != null) {
205 super.saveState(memento);
206
207 memento = memento.createChild(TREE_PATHS);
208 TreePath[] treePaths = this.getCommonViewer().getExpandedTreePaths();
209 for (TreePath treePath : treePaths) {
210 int pathLength = treePath.getSegmentCount();
211 String path = "";
212 for (int i = 0; i < pathLength; i++) {
213 Object segment = treePath.getSegment(i);
214 if (segment instanceof CdmBase) {
215 path += ((CdmBase) segment).getUuid().toString() + " ";
216 } else {
217 logger.warn("Non-taxon tree path segment " + segment);
218 }
219 }
220 logger.info("Creating memento child for path " + path.trim());
221 memento.createChild(TREE_PATH, path.trim());
222 }
223 } else {
224 logger.warn("TreeState could not be saved: Memento is null");
225 }
226 }
227
228 /**
229 * Activates the current view.
230 */
231 private void activateView() {
232 getSite().getPage().activate(this);
233 }
234
235 /* (non-Javadoc)
236 * @see org.eclipse.ui.navigator.CommonNavigator#createPartControl(org.eclipse.swt.widgets.Composite)
237 */
238 public void createPartControl(Composite aParent) {
239 super.createPartControl(aParent);
240
241 // It seems the workbench does not set the focus at the right time. This should fix this.
242 // getCommonViewer().addSelectionChangedListener(new ISelectionChangedListener() {
243 // public void selectionChanged(SelectionChangedEvent event) {
244 // activateView();
245 // }
246 // });
247 }
248
249
250 /* (non-Javadoc)
251 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
252 */
253 public ConversationHolder getConversationHolder() {
254 return conversation;
255 }
256
257 /* (non-Javadoc)
258 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
259 */
260 public void update(CdmDataChangeMap changeEvents) {
261 if(dataChangeBehavior == null){
262 dataChangeBehavior = new TaxonNavigatorDataChangeBehavior(this);
263 }
264
265 DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
266 }
267
268 public String getFrameToolTipText(Object element) {
269 if (element instanceof Root) {
270 return "Taxonomic Tree";
271 }
272 return super.getFrameToolTipText(element);
273 }
274
275 /* (non-Javadoc)
276 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
277 */
278 @Override
279 public void dispose() {
280 super.dispose();
281 dataChangeBehavior = null;
282 if(conversation != null){
283 conversation.unregisterForDataStoreChanges(this);
284 }
285 }
286
287 /* (non-Javadoc)
288 * @see org.eclipse.ui.navigator.CommonNavigator#setFocus()
289 */
290 @Override
291 public void setFocus() {
292 //logger.warn("Setting focus to navigator");
293 super.setFocus();
294 if(getConversationHolder() != null){
295 getConversationHolder().bind();
296 }
297 }
298
299 /* (non-Javadoc)
300 * @see eu.etaxonomy.taxeditor.operations.IPostOperationEnabled#postOperation(eu.etaxonomy.cdm.model.common.CdmBase)
301 */
302 public boolean postOperation(CdmBase objectAffectedByOperation) {
303 // nothing to do here
304 return true;
305 }
306
307 public void save(IMemento memento) {
308 saveTreeState(memento);
309 if(conversation != null){
310 conversation.unregisterForDataStoreChanges(this);
311 conversation = null;
312 }
313 // this.getCommonViewer().setInput(new EmptyRoot());
314 }
315
316 // @Override
317 // public ISelection getSelection() {
318 // return getCommonViewer().getSelection();
319 // }
320
321 /**
322 * @see http://www.eclipse.org/forums/index.php?t=msg&goto=512094&
323 */
324 @Override
325 protected void handleDoubleClick(DoubleClickEvent anEvent) {
326
327 ICommandService commandService = (ICommandService)getSite().getService(ICommandService.class);
328
329 Command command = commandService.getCommand(OPEN_COMMAND_ID);
330 if(command.isEnabled()) {
331 IHandlerService handlerService = (IHandlerService)getSite().getService(IHandlerService.class);
332 try {
333 handlerService.executeCommand(OPEN_COMMAND_ID, null);
334 } catch (NotDefinedException e) {
335 throw new RuntimeException("Could not find open command: " + OPEN_COMMAND_ID);
336 } catch (Exception e) {
337 logger.error("An exception occured while trying to open a selection", e);
338 }
339 }
340 // Pass the double click up to the super-class so it can expand/collapse trees
341 super.handleDoubleClick(anEvent);
342 }
343 }