Project

General

Profile

Download (11.8 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.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.conversation.ConversationHolder;
32
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
33
import eu.etaxonomy.cdm.api.service.IClassificationService;
34
import eu.etaxonomy.cdm.model.common.CdmBase;
35
import eu.etaxonomy.cdm.model.taxon.TaxonComparator;
36
import eu.etaxonomy.cdm.model.taxon.TaxonComparatorSearch;
37
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
38
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
39
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
40
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
41
import eu.etaxonomy.taxeditor.model.MessagingUtils;
42
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
43
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
44
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
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
		Comparator comparator;
84
		if (PreferencesUtil.getSortNodesNaturally()){
85
			comparator = new TaxonNaturalComparator();
86
		} else{
87
			comparator = new TaxonComparatorSearch();
88
		}
89
		TaxonNodeComparator viewerComparator = new TaxonNodeComparator(comparator);
90
		this.getCommonViewer().setComparator(viewerComparator);
91
        setLinkingEnabled(true);
92
//		this.getCommonViewer().addSelectionChangedListener(new ISelectionChangedListener() {
93
//
94
//			@Override
95
//			public void selectionChanged(SelectionChangedEvent arg0) {
96
//				IStructuredSelection selection = (IStructuredSelection) getCommonViewer().getSelection();
97
//
98
//				Object firstElement =  selection.getFirstElement();
99
//				//
100
//				if (!(firstElement instanceof Classification)){
101
//					//NavigationUtil.selectInNavigator(firstElement, null);
102
//					NavigationUtil.openEditor(firstElement);
103
//				}
104
//
105
//			}
106
//		} );
107

    
108
		if (CdmStore.isActive()) {
109

    
110
			// TODO when closing and reopening the taxon navigator
111
			// we do not preserve state. Closing the view, in contrary to
112
			// closing the whole application
113
			// should be handled by the state manager too
114

    
115
			return new Root(conversation);
116
		}
117
		return new EmptyRoot();
118
	}
119

    
120
	/** {@inheritDoc} */
121
	@Override
122
	public void init(IViewSite site) throws PartInitException {
123
		super.init(site);
124
		init();
125
	}
126

    
127
	/**
128
	 * <p>
129
	 * init
130
	 * </p>
131
	 */
132
	public void init() {
133
		if (CdmStore.isActive() && conversation == null) {
134
			conversation = CdmStore.createConversation();
135
			conversation.registerForDataStoreChanges(TaxonNavigator.this);
136
		}
137
		CdmStore.getLoginManager().addObserver(this);
138
	}
139

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

    
154
	/**
155
	 * Removes all content
156
	 */
157
	public void clear() {
158
		getCommonViewer().setInput(new EmptyRoot());
159
	}
160

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

    
180
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
181

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

    
192
		subProgressMonitor.beginTask("Restoring Taxon Navigator",
193
				1 + mementoWork + 5);
194
		subProgressMonitor.subTask("Restoring Taxon Navigator");
195
		subProgressMonitor.worked(1);
196

    
197
		conversation = CdmStore.createConversation();
198
		subProgressMonitor.worked(1);
199
		conversation.registerForDataStoreChanges(TaxonNavigator.this);
200
		subProgressMonitor.worked(1);
201
		getCommonViewer().setInput(new Root(conversation));
202
		subProgressMonitor.worked(1);
203
		getCommonViewer().refresh();
204
		subProgressMonitor.worked(1);
205

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

    
224
	/**
225
	 * @param string
226
	 * @return
227
	 */
228
	private TreePath createTreePathFromString(String string) {
229

    
230
		List<CdmBase> pathList = new ArrayList<CdmBase>();
231

    
232
		if (string.length() == 0) {
233
            return null;
234
        }
235

    
236
		for (String uuid : string.split(" ")) {
237
			CdmBase cdmBaseObject = CdmStore.getService(
238
					IClassificationService.class).getTaxonNodeByUuid(
239
					UUID.fromString(uuid));
240
			if (cdmBaseObject == null) {
241
				// is this a tree uuid?
242
				cdmBaseObject = CdmStore.getService(
243
						IClassificationService.class).load(
244
						UUID.fromString(uuid));
245

    
246
				if (cdmBaseObject == null) {
247
                    return null;
248
                }
249
			}
250
			pathList.add(cdmBaseObject);
251
		}
252
		return new TreePath(pathList.toArray());
253
	}
254

    
255
	/** {@inheritDoc} */
256
	@Override
257
	public void saveState(IMemento aMemento) {
258
		//
259
	}
260

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

    
278
		super.saveState(memento);
279

    
280
		memento = memento.createChild(TREE_PATHS);
281
		TreePath[] treePaths = this.getCommonViewer().getExpandedTreePaths();
282

    
283
		monitor.beginTask("Saving Taxon Navigator State", treePaths.length);
284

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

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

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

    
337
		DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
338
	}
339

    
340
	/** {@inheritDoc} */
341
	@Override
342
	public String getFrameToolTipText(Object element) {
343
		if (element instanceof Root) {
344
			return "Taxonomic Tree";
345
		}
346
		return super.getFrameToolTipText(element);
347
	}
348

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

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

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

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

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

    
421
	/**
422
	 * <p>
423
	 * onComplete
424
	 * </p>
425
	 *
426
	 * @return a boolean.
427
	 */
428
	@Override
429
	public boolean onComplete() {
430
		return true;
431
	}
432

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

    
453

    
454
	/* (non-Javadoc)
455
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
456
	 */
457
	@Override
458
	public void update(Observable o, Object arg) {
459
		if(o instanceof LoginManager){
460
			refresh();
461
		}
462

    
463
	}
464
}
(9-9/15)