Project

General

Profile

Download (13.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.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
import eu.etaxonomy.cdm.model.taxon.Classification;
38
import eu.etaxonomy.cdm.model.taxon.TaxonComparatorSearch;
39
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
40
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
41
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
42
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
43
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
44
import eu.etaxonomy.taxeditor.model.MessagingUtils;
45
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
46
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
47
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
48
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
49
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
50
import eu.etaxonomy.taxeditor.store.CdmStore;
51
import eu.etaxonomy.taxeditor.store.LoginManager;
52

    
53
/**
54
 * Taxonomic tree implementation using Common Navigator Framework.
55
 *
56
 * @author p.ciardelli
57
 * @author n.hoffmann
58
 * @created 02.06.2009
59
 * @version 1.0
60
 */
61
public class TaxonNavigator extends CommonNavigator implements
62
		IPostOperationEnabled, IConversationEnabled, Observer, ICdmEntitySessionEnabled {
63

    
64
	/**
65
	 * Constant
66
	 * <code>ID="eu.etaxonomy.taxeditor.navigation.navig"{trunked}</code>
67
	 */
68
	public static final String ID = "eu.etaxonomy.taxeditor.navigation.navigator"; //$NON-NLS-1$
69

    
70
	private static final String TREE_PATH = "treepath";
71

    
72
	private static final String TREE_PATHS = "treepaths";
73

    
74
	private ConversationHolder conversation;
75

    
76
	private ICdmEntitySession cdmEntitySession;
77

    
78
	private String partNameCache;
79

    
80
	private IDataChangeBehavior dataChangeBehavior;
81

    
82
	private Root root;
83

    
84
	/*
85
	 * (non-Javadoc)
86
	 *
87
	 * @see org.eclipse.ui.navigator.CommonNavigator#getInitialInput()
88
	 */
89
	/** {@inheritDoc} */
90
	@Override
91
	protected IAdaptable getInitialInput() {
92
		Comparator comparator;
93
		if (PreferencesUtil.getSortNodesNaturally()){
94
			comparator = new TaxonNaturalComparator();
95
		} else{
96
			comparator = new TaxonComparatorSearch();
97
		}
98
		TaxonNodeComparator viewerComparator = new TaxonNodeComparator(comparator);
99
		this.getCommonViewer().setComparator(viewerComparator);
100
        setLinkingEnabled(true);
101
//		this.getCommonViewer().addSelectionChangedListener(new ISelectionChangedListener() {
102
//
103
//			@Override
104
//			public void selectionChanged(SelectionChangedEvent arg0) {
105
//				IStructuredSelection selection = (IStructuredSelection) getCommonViewer().getSelection();
106
//
107
//				Object firstElement =  selection.getFirstElement();
108
//				//
109
//				if (!(firstElement instanceof Classification)){
110
//					//NavigationUtil.selectInNavigator(firstElement, null);
111
//					NavigationUtil.openEditor(firstElement);
112
//				}
113
//
114
//			}
115
//		} );
116

    
117
		if (CdmStore.isActive()) {
118

    
119
			// TODO when closing and reopening the taxon navigator
120
			// we do not preserve state. Closing the view, in contrary to
121
			// closing the whole application
122
			// should be handled by the state manager too
123
		    root = new Root(conversation);
124
			return root;
125
		}
126
		return new EmptyRoot();
127
	}
128

    
129
	/** {@inheritDoc} */
130
	@Override
131
	public void init(IViewSite site) throws PartInitException {
132
		super.init(site);
133
		init();
134
	}
135

    
136
	/**
137
	 * <p>
138
	 * init
139
	 * </p>
140
	 */
141
	public void init() {
142

    
143
		if (CdmStore.isActive() && conversation == null) {
144
			conversation = CdmStore.createConversation();
145
			conversation.registerForDataStoreChanges(TaxonNavigator.this);
146
		}
147
		if (CdmStore.isActive() && cdmEntitySession == null) {
148
		    cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
149
		    CdmApplicationState.getCurrentDataChangeService().register(this);
150
		}
151
		CdmStore.getLoginManager().addObserver(this);
152
	}
153

    
154
	/**
155
	 * Refresh this navigators viewer
156
	 */
157
	public void refresh() {
158
		if(getConversationHolder() != null){
159
			getConversationHolder().bind();
160
			//FIXME : Need to make sure this is a stable fix (ticket 3822)
161
			if(!getConversationHolder().isCompleted()){
162
			    getConversationHolder().commit();
163
			}
164
		}
165
		if (cdmEntitySession != null) {
166
		    cdmEntitySession.fireNotifications();
167
		}
168
		getCommonViewer().refresh();
169
	}
170

    
171
	   /**
172
     * Refresh this navigators viewer
173
     */
174
    public void refresh(Set objects) {
175
        for(Object obj : objects) {
176
            getCommonViewer().refresh(obj);
177
        }
178
    }
179

    
180
	/**
181
	 * Removes all content
182
	 */
183
	public void clear() {
184
		getCommonViewer().setInput(new EmptyRoot());
185
	}
186

    
187
	/**
188
	 * <p>
189
	 * restore
190
	 * </p>
191
	 *
192
	 * @param memento
193
	 *            a {@link org.eclipse.ui.IMemento} object.
194
	 * @param monitor
195
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
196
	 */
197
	public void restore(IMemento memento, IProgressMonitor monitor) {
198
	    root = new Root(conversation);
199
		if (memento == null) {
200
			getCommonViewer().setInput(root);
201
			return;
202
		}
203
		int mementoWork = 0;
204
		Set<TreePath> treePaths = new HashSet<TreePath>();
205
		IMemento[] treePathMementos = null;
206

    
207
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
208

    
209
		if (treePathsMemento != null) {
210
			treePathMementos = treePathsMemento.getChildren(TREE_PATH);
211
			mementoWork = treePathMementos.length;
212
		}
213
		// begin the monitor with steps for all tree paths and steps for
214
		// creating
215
		// conversation s.o., refreshing the tree and setting the paths
216
		IProgressMonitor subProgressMonitor = NavigationUtil
217
				.getSubProgressMonitor(monitor, 1);
218

    
219
		subProgressMonitor.beginTask("Restoring Taxon Navigator",
220
				1 + mementoWork + 5);
221
		subProgressMonitor.subTask("Restoring Taxon Navigator");
222
		subProgressMonitor.worked(1);
223

    
224
		conversation = CdmStore.createConversation();
225
		subProgressMonitor.worked(1);
226
		conversation.registerForDataStoreChanges(TaxonNavigator.this);
227
		subProgressMonitor.worked(1);
228
		getCommonViewer().setInput(root);
229
		subProgressMonitor.worked(1);
230
		getCommonViewer().refresh();
231
		subProgressMonitor.worked(1);
232

    
233
		if (treePathMementos != null && treePathMementos.length > 0) {
234
			for (IMemento treePathMemento : treePathMementos) {
235
				TreePath treePath = createTreePathFromString(treePathMemento
236
						.getID());
237
				if (!subProgressMonitor.isCanceled() && treePath != null) {
238
					treePaths.add(treePath);
239
					subProgressMonitor.worked(1);
240
				}
241
			}
242
		}
243
		if (treePaths.size() > 0) {
244
			TaxonNavigator.this.getCommonViewer().setExpandedTreePaths(
245
					treePaths.toArray(new TreePath[0]));
246
			subProgressMonitor.worked(1);
247
		}
248
		subProgressMonitor.done();
249
	}
250

    
251
	/**
252
	 * @param string
253
	 * @return
254
	 */
255
	private TreePath createTreePathFromString(String string) {
256

    
257
		List<CdmBase> pathList = new ArrayList<CdmBase>();
258

    
259
		if (string.length() == 0) {
260
            return null;
261
        }
262

    
263
		for (String uuid : string.split(" ")) {
264
			CdmBase cdmBaseObject = CdmStore.getService(
265
					IClassificationService.class).getTaxonNodeByUuid(
266
					UUID.fromString(uuid));
267
			if (cdmBaseObject == null) {
268
				// is this a tree uuid?
269
				cdmBaseObject = CdmStore.getService(
270
						IClassificationService.class).load(
271
						UUID.fromString(uuid));
272

    
273
				if (cdmBaseObject == null) {
274
                    return null;
275
                }
276
			}
277
			pathList.add(cdmBaseObject);
278
		}
279
		return new TreePath(pathList.toArray());
280
	}
281

    
282
	/** {@inheritDoc} */
283
	@Override
284
	public void saveState(IMemento aMemento) {
285
		//
286
	}
287

    
288
	/**
289
	 * <p>
290
	 * saveTreeState
291
	 * </p>
292
	 *
293
	 * @param memento
294
	 *            a {@link org.eclipse.ui.IMemento} object.
295
	 * @param progressMonitor
296
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
297
	 */
298
	public void saveTreeState(IMemento memento, IProgressMonitor progressMonitor) {
299
		if (memento == null) {
300
			return;
301
		}
302
		IProgressMonitor monitor = NavigationUtil.getSubProgressMonitor(
303
				progressMonitor, 1);
304

    
305
		super.saveState(memento);
306

    
307
		memento = memento.createChild(TREE_PATHS);
308
		TreePath[] treePaths = this.getCommonViewer().getExpandedTreePaths();
309

    
310
		monitor.beginTask("Saving Taxon Navigator State", treePaths.length);
311

    
312
		for (TreePath treePath : treePaths) {
313
			int pathLength = treePath.getSegmentCount();
314
			String path = "";
315
			for (int i = 0; i < pathLength; i++) {
316
				Object segment = treePath.getSegment(i);
317
				if (segment instanceof CdmBase) {
318
					path += ((CdmBase) segment).getUuid().toString() + " ";
319
					monitor.worked(1);
320
				} else {
321
					MessagingUtils.warn(getClass(),
322
							"Non-taxon tree path segment " + segment);
323
				}
324
			}
325
			memento.createChild(TREE_PATH, path.trim());
326
		}
327
		monitor.done();
328
	}
329

    
330
	/*
331
	 * (non-Javadoc)
332
	 *
333
	 * @see
334
	 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
335
	 * ()
336
	 */
337
	/**
338
	 * <p>
339
	 * getConversationHolder
340
	 * </p>
341
	 *
342
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
343
	 *         object.
344
	 */
345
	@Override
346
	public ConversationHolder getConversationHolder() {
347
		return conversation;
348
	}
349

    
350
	/*
351
	 * (non-Javadoc)
352
	 *
353
	 * @see
354
	 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update
355
	 * (eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
356
	 */
357
	/** {@inheritDoc} */
358
	@Override
359
	public void update(CdmDataChangeMap changeEvents) {
360
		if (dataChangeBehavior == null) {
361
			dataChangeBehavior = new TaxonNavigatorDataChangeBehavior(this);
362
		}
363

    
364
		DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
365
	}
366

    
367
	/** {@inheritDoc} */
368
	@Override
369
	public String getFrameToolTipText(Object element) {
370
		if (element instanceof Root) {
371
			return "Taxonomic Tree";
372
		}
373
		return super.getFrameToolTipText(element);
374
	}
375

    
376
	/*
377
	 * (non-Javadoc)
378
	 *
379
	 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
380
	 */
381
	/** {@inheritDoc} */
382
	@Override
383
	public void dispose() {
384
		super.dispose();
385
		dataChangeBehavior = null;
386
		if (conversation != null) {
387
			conversation.unregisterForDataStoreChanges(this);
388
		}
389
		if(cdmEntitySession != null) {
390
		    cdmEntitySession.dispose();
391
		}
392
	}
393

    
394
	/*
395
	 * (non-Javadoc)
396
	 *
397
	 * @see org.eclipse.ui.navigator.CommonNavigator#setFocus()
398
	 */
399
	/** {@inheritDoc} */
400
	@Override
401
	public void setFocus() {
402
		// logger.warn("Setting focus to navigator");
403
		super.setFocus();
404
		if (getConversationHolder() != null) {
405
			getConversationHolder().bind();
406
		}
407
		if(cdmEntitySession != null) {
408
		    cdmEntitySession.bind();
409
		}
410
	}
411

    
412
	/*
413
	 * (non-Javadoc)
414
	 *
415
	 * @see
416
	 * eu.etaxonomy.taxeditor.operations.IPostOperationEnabled#postOperation
417
	 * (eu.etaxonomy.cdm.model.common.CdmBase)
418
	 */
419
	/** {@inheritDoc} */
420
	@Override
421
	public boolean postOperation(CdmBase objectAffectedByOperation) {
422
		// nothing to do here
423
		return true;
424
	}
425

    
426
	/**
427
	 * <p>
428
	 * save
429
	 * </p>
430
	 *
431
	 * @param memento
432
	 *            a {@link org.eclipse.ui.IMemento} object.
433
	 * @param monitor
434
	 *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
435
	 */
436
	public void save(IMemento memento, IProgressMonitor monitor) {
437
		saveTreeState(memento, monitor);
438
		if (conversation != null) {
439
			conversation.unregisterForDataStoreChanges(this);
440
			conversation = null;
441
		}
442
	}
443

    
444
	/** {@inheritDoc} */
445
	@Override
446
	protected void handleDoubleClick(DoubleClickEvent anEvent) {
447
		NavigationUtil.executeEditHandler();
448
		// If the double click is passed up to the super-class it will
449
		// expand/collapse trees.
450
		// We do not want that
451
		// super.handleDoubleClick(anEvent);
452
	}
453

    
454
	/**
455
	 * <p>
456
	 * onComplete
457
	 * </p>
458
	 *
459
	 * @return a boolean.
460
	 */
461
	@Override
462
	public boolean onComplete() {
463
		return true;
464
	}
465

    
466
	/*
467
	 * (non-Javadoc)
468
	 *
469
	 * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
470
	 */
471
	/** {@inheritDoc} */
472
	@Override
473
	public void showBusy(boolean busy) {
474
		super.showBusy(busy);
475
		getCommonViewer().getControl().setEnabled(!busy);
476
		if (busy) {
477
			partNameCache = getPartName();
478
			setPartName("Loading datasources");
479
		} else {
480
			if (partNameCache != null) {
481
				setPartName(partNameCache);
482
			}
483
		}
484
	}
485

    
486

    
487
	/* (non-Javadoc)
488
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
489
	 */
490
	@Override
491
	public void update(Observable o, Object arg) {
492
		if(o instanceof LoginManager){
493
			refresh();
494
		}
495

    
496
	}
497

    
498
    /* (non-Javadoc)
499
     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getCdmEntitySession()
500
     */
501
    @Override
502
    public ICdmEntitySession getCdmEntitySession() {
503
       return cdmEntitySession;
504
    }
505

    
506
    /* (non-Javadoc)
507
     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getRootEntities()
508
     */
509
    @Override
510
    public List<Classification> getRootEntities() {
511
        if(root != null) {
512
            return root.getParentBeans();
513
        }
514
        return null;
515
    }
516

    
517
    /* (non-Javadoc)
518
     * @see eu.etaxonomy.cdm.api.application.ICdmChangeListener#onChange(eu.etaxonomy.cdm.api.application.CdmChangeEvent)
519
     */
520
    @Override
521
    public void onChange(CdmChangeEvent event) {
522
        for(CdmBase cb : event.getChangedObjects()) {
523
            if(cb instanceof TaxonNode) {
524
                getCommonViewer().refresh(cb);
525
            }
526
        }
527

    
528
    }
529
}
(9-9/16)