Project

General

Profile

Download (11.7 KB) Statistics
| Branch: | Tag: | Revision:
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.ISelectionChangedListener;
25
import org.eclipse.jface.viewers.IStructuredSelection;
26
import org.eclipse.jface.viewers.SelectionChangedEvent;
27
import org.eclipse.jface.viewers.TreePath;
28
import org.eclipse.ui.IMemento;
29
import org.eclipse.ui.IViewSite;
30
import org.eclipse.ui.PartInitException;
31
import org.eclipse.ui.navigator.CommonNavigator;
32

    
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
import eu.etaxonomy.cdm.model.taxon.Classification;
38
import eu.etaxonomy.cdm.model.taxon.TaxonComparatorSearch;
39
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
40
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
41
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
42
import eu.etaxonomy.taxeditor.model.MessagingUtils;
43
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
44
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
45
import eu.etaxonomy.taxeditor.store.CdmStore;
46
import eu.etaxonomy.taxeditor.store.LoginManager;
47

    
48
/**
49
 * Taxonomic tree implementation using Common Navigator Framework.
50
 *
51
 * @author p.ciardelli
52
 * @author n.hoffmann
53
 * @created 02.06.2009
54
 * @version 1.0
55
 */
56
public class TaxonNavigator extends CommonNavigator implements
57
		IPostOperationEnabled, IConversationEnabled, Observer {
58

    
59
	/**
60
	 * Constant
61
	 * <code>ID="eu.etaxonomy.taxeditor.navigation.navig"{trunked}</code>
62
	 */
63
	public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator"; //$NON-NLS-1$
64

    
65
	private static final String TREE_PATH = "treepath";
66

    
67
	private static final String TREE_PATHS = "treepaths";
68

    
69
	private ConversationHolder conversation;
70

    
71
	private String partNameCache;
72

    
73
	private IDataChangeBehavior dataChangeBehavior;
74

    
75
	/*
76
	 * (non-Javadoc)
77
	 *
78
	 * @see org.eclipse.ui.navigator.CommonNavigator#getInitialInput()
79
	 */
80
	/** {@inheritDoc} */
81
	@Override
82
	protected IAdaptable getInitialInput() {
83
		
84
		TaxonComparatorSearch comparator = new TaxonComparatorSearch();
85
		TaxonNodeComparator viewerComparator = new TaxonNodeComparator(comparator);
86
		this.getCommonViewer().setComparator(viewerComparator);
87
//		this.getCommonViewer().addSelectionChangedListener(new ISelectionChangedListener() {
88
//			
89
//			@Override
90
//			public void selectionChanged(SelectionChangedEvent arg0) {
91
//				IStructuredSelection selection = (IStructuredSelection) getCommonViewer().getSelection();
92
//				
93
//				Object firstElement =  selection.getFirstElement();
94
//				//
95
//				if (!(firstElement instanceof Classification)){
96
//					//NavigationUtil.selectInNavigator(firstElement, null);
97
//					NavigationUtil.openEditor(firstElement);
98
//				}
99
//				
100
//			}
101
//		} );
102
		
103
		if (CdmStore.isActive()) {
104
			
105
			// TODO when closing and reopening the taxon navigator
106
			// we do not preserve state. Closing the view, in contrary to
107
			// closing the whole application
108
			// should be handled by the state manager too
109

    
110
			return new Root(conversation);
111
		}
112
		return new EmptyRoot();
113
	}
114

    
115
	/** {@inheritDoc} */
116
	@Override
117
	public void init(IViewSite site) throws PartInitException {
118
		super.init(site);
119
		init();
120
	}
121

    
122
	/**
123
	 * <p>
124
	 * init
125
	 * </p>
126
	 */
127
	public void init() {
128
		if (CdmStore.isActive() && conversation == null) {
129
			conversation = CdmStore.createConversation();
130
			conversation.registerForDataStoreChanges(TaxonNavigator.this);
131
		}
132
		CdmStore.getLoginManager().addObserver(this);
133
	}
134

    
135
	/**
136
	 * Refresh this navigators viewer
137
	 */
138
	public void refresh() {
139
		if(getConversationHolder() != null){
140
			getConversationHolder().bind();
141
			//FIXME : Need to make sure this is a stable fix (ticket 3822)
142
			if(!getConversationHolder().isCompleted()){
143
			    getConversationHolder().commit();
144
			}
145
		}
146
		getCommonViewer().refresh();
147
	}
148

    
149
	/**
150
	 * Removes all content
151
	 */
152
	public void clear() {
153
		getCommonViewer().setInput(new EmptyRoot());
154
	}
155

    
156
	/**
157
	 * <p>
158
	 * restore
159
	 * </p>
160
	 *
161
	 * @param memento
162
	 *            a {@link org.eclipse.ui.IMemento} object.
163
	 * @param monitor
164
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
165
	 */
166
	public void restore(IMemento memento, IProgressMonitor monitor) {
167
		if (memento == null) {
168
			getCommonViewer().setInput(new Root(conversation));
169
			return;
170
		}
171
		int mementoWork = 0;
172
		Set<TreePath> treePaths = new HashSet<TreePath>();
173
		IMemento[] treePathMementos = null;
174

    
175
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
176

    
177
		if (treePathsMemento != null) {
178
			treePathMementos = treePathsMemento.getChildren(TREE_PATH);
179
			mementoWork = treePathMementos.length;
180
		}
181
		// begin the monitor with steps for all tree paths and steps for
182
		// creating
183
		// conversation s.o., refreshing the tree and setting the paths
184
		IProgressMonitor subProgressMonitor = NavigationUtil
185
				.getSubProgressMonitor(monitor, 1);
186

    
187
		subProgressMonitor.beginTask("Restoring Taxon Navigator",
188
				1 + mementoWork + 5);
189
		subProgressMonitor.subTask("Restoring Taxon Navigator");
190
		subProgressMonitor.worked(1);
191

    
192
		conversation = CdmStore.createConversation();
193
		subProgressMonitor.worked(1);
194
		conversation.registerForDataStoreChanges(TaxonNavigator.this);
195
		subProgressMonitor.worked(1);
196
		getCommonViewer().setInput(new Root(conversation));
197
		subProgressMonitor.worked(1);
198
		getCommonViewer().refresh();
199
		subProgressMonitor.worked(1);
200

    
201
		if (treePathMementos != null && treePathMementos.length > 0) {
202
			for (IMemento treePathMemento : treePathMementos) {
203
				TreePath treePath = createTreePathFromString(treePathMemento
204
						.getID());
205
				if (!subProgressMonitor.isCanceled() && treePath != null) {
206
					treePaths.add(treePath);
207
					subProgressMonitor.worked(1);
208
				}
209
			}
210
		}
211
		if (treePaths.size() > 0) {
212
			TaxonNavigator.this.getCommonViewer().setExpandedTreePaths(
213
					treePaths.toArray(new TreePath[0]));
214
			subProgressMonitor.worked(1);
215
		}
216
		subProgressMonitor.done();
217
	}
218

    
219
	/**
220
	 * @param string
221
	 * @return
222
	 */
223
	private TreePath createTreePathFromString(String string) {
224

    
225
		List<CdmBase> pathList = new ArrayList<CdmBase>();
226

    
227
		if (string.length() == 0) {
228
            return null;
229
        }
230

    
231
		for (String uuid : string.split(" ")) {
232
			CdmBase cdmBaseObject = CdmStore.getService(
233
					IClassificationService.class).getTaxonNodeByUuid(
234
					UUID.fromString(uuid));
235
			if (cdmBaseObject == null) {
236
				// is this a tree uuid?
237
				cdmBaseObject = CdmStore.getService(
238
						IClassificationService.class).load(
239
						UUID.fromString(uuid));
240

    
241
				if (cdmBaseObject == null) {
242
                    return null;
243
                }
244
			}
245
			pathList.add(cdmBaseObject);
246
		}
247
		return new TreePath(pathList.toArray());
248
	}
249

    
250
	/** {@inheritDoc} */
251
	@Override
252
	public void saveState(IMemento aMemento) {
253
		//
254
	}
255

    
256
	/**
257
	 * <p>
258
	 * saveTreeState
259
	 * </p>
260
	 *
261
	 * @param memento
262
	 *            a {@link org.eclipse.ui.IMemento} object.
263
	 * @param progressMonitor
264
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
265
	 */
266
	public void saveTreeState(IMemento memento, IProgressMonitor progressMonitor) {
267
		if (memento == null) {
268
			return;
269
		}
270
		IProgressMonitor monitor = NavigationUtil.getSubProgressMonitor(
271
				progressMonitor, 1);
272

    
273
		super.saveState(memento);
274

    
275
		memento = memento.createChild(TREE_PATHS);
276
		TreePath[] treePaths = this.getCommonViewer().getExpandedTreePaths();
277

    
278
		monitor.beginTask("Saving Taxon Navigator State", treePaths.length);
279

    
280
		for (TreePath treePath : treePaths) {
281
			int pathLength = treePath.getSegmentCount();
282
			String path = "";
283
			for (int i = 0; i < pathLength; i++) {
284
				Object segment = treePath.getSegment(i);
285
				if (segment instanceof CdmBase) {
286
					path += ((CdmBase) segment).getUuid().toString() + " ";
287
					monitor.worked(1);
288
				} else {
289
					MessagingUtils.warn(getClass(),
290
							"Non-taxon tree path segment " + segment);
291
				}
292
			}
293
			memento.createChild(TREE_PATH, path.trim());
294
		}
295
		monitor.done();
296
	}
297

    
298
	/*
299
	 * (non-Javadoc)
300
	 *
301
	 * @see
302
	 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
303
	 * ()
304
	 */
305
	/**
306
	 * <p>
307
	 * getConversationHolder
308
	 * </p>
309
	 *
310
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
311
	 *         object.
312
	 */
313
	@Override
314
	public ConversationHolder getConversationHolder() {
315
		return conversation;
316
	}
317

    
318
	/*
319
	 * (non-Javadoc)
320
	 *
321
	 * @see
322
	 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update
323
	 * (eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
324
	 */
325
	/** {@inheritDoc} */
326
	@Override
327
	public void update(CdmDataChangeMap changeEvents) {
328
		if (dataChangeBehavior == null) {
329
			dataChangeBehavior = new TaxonNavigatorDataChangeBehavior(this);
330
		}
331

    
332
		DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
333
	}
334

    
335
	/** {@inheritDoc} */
336
	@Override
337
	public String getFrameToolTipText(Object element) {
338
		if (element instanceof Root) {
339
			return "Taxonomic Tree";
340
		}
341
		return super.getFrameToolTipText(element);
342
	}
343

    
344
	/*
345
	 * (non-Javadoc)
346
	 *
347
	 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
348
	 */
349
	/** {@inheritDoc} */
350
	@Override
351
	public void dispose() {
352
		super.dispose();
353
		dataChangeBehavior = null;
354
		if (conversation != null) {
355
			conversation.unregisterForDataStoreChanges(this);
356
		}
357
	}
358

    
359
	/*
360
	 * (non-Javadoc)
361
	 *
362
	 * @see org.eclipse.ui.navigator.CommonNavigator#setFocus()
363
	 */
364
	/** {@inheritDoc} */
365
	@Override
366
	public void setFocus() {
367
		// logger.warn("Setting focus to navigator");
368
		super.setFocus();
369
		if (getConversationHolder() != null) {
370
			getConversationHolder().bind();
371
		}
372
	}
373

    
374
	/*
375
	 * (non-Javadoc)
376
	 *
377
	 * @see
378
	 * eu.etaxonomy.taxeditor.operations.IPostOperationEnabled#postOperation
379
	 * (eu.etaxonomy.cdm.model.common.CdmBase)
380
	 */
381
	/** {@inheritDoc} */
382
	@Override
383
	public boolean postOperation(CdmBase objectAffectedByOperation) {
384
		// nothing to do here
385
		return true;
386
	}
387

    
388
	/**
389
	 * <p>
390
	 * save
391
	 * </p>
392
	 *
393
	 * @param memento
394
	 *            a {@link org.eclipse.ui.IMemento} object.
395
	 * @param monitor
396
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
397
	 */
398
	public void save(IMemento memento, IProgressMonitor monitor) {
399
		saveTreeState(memento, monitor);
400
		if (conversation != null) {
401
			conversation.unregisterForDataStoreChanges(this);
402
			conversation = null;
403
		}
404
	}
405

    
406
	/** {@inheritDoc} */
407
	@Override
408
	protected void handleDoubleClick(DoubleClickEvent anEvent) {
409
		NavigationUtil.executeEditHandler();
410
		// If the double click is passed up to the super-class it will
411
		// expand/collapse trees.
412
		// We do not want that
413
		// super.handleDoubleClick(anEvent);
414
	}
415

    
416
	/**
417
	 * <p>
418
	 * onComplete
419
	 * </p>
420
	 *
421
	 * @return a boolean.
422
	 */
423
	@Override
424
	public boolean onComplete() {
425
		return true;
426
	}
427

    
428
	/*
429
	 * (non-Javadoc)
430
	 *
431
	 * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
432
	 */
433
	/** {@inheritDoc} */
434
	@Override
435
	public void showBusy(boolean busy) {
436
		super.showBusy(busy);
437
		getCommonViewer().getControl().setEnabled(!busy);
438
		if (busy) {
439
			partNameCache = getPartName();
440
			setPartName("Loading datasources");
441
		} else {
442
			if (partNameCache != null) {
443
				setPartName(partNameCache);
444
			}
445
		}
446
	}
447

    
448

    
449
	/* (non-Javadoc)
450
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
451
	 */
452
	@Override
453
	public void update(Observable o, Object arg) {
454
		if(o instanceof LoginManager){
455
			refresh();
456
		}
457

    
458
	}
459
}
(9-9/15)