Project

General

Profile

Download (13.9 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.application.ICdmChangeListener;
34
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
35
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
36
import eu.etaxonomy.cdm.api.service.IClassificationService;
37
import eu.etaxonomy.cdm.model.common.CdmBase;
38
import eu.etaxonomy.cdm.model.taxon.Classification;
39
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
40
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
41
import eu.etaxonomy.cdm.model.taxon.TaxonNodeComparator;
42
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
43
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
44
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
45
import eu.etaxonomy.taxeditor.model.MessagingUtils;
46
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
47
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
48
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
49
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
50
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
51
import eu.etaxonomy.taxeditor.store.CdmStore;
52
import eu.etaxonomy.taxeditor.store.LoginManager;
53

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

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

    
72
	private static final String TREE_PATH = "treepath";
73

    
74
	private static final String TREE_PATHS = "treepaths";
75

    
76
	private ConversationHolder conversation;
77

    
78
	private ICdmEntitySession cdmEntitySession;
79

    
80
	private String partNameCache;
81

    
82
	private IDataChangeBehavior dataChangeBehavior;
83

    
84
	private Root root;
85

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

    
119
		if (CdmStore.isActive()) {
120

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
304
		super.saveState(memento);
305

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

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

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

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

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

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

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

    
375
	/*
376
	 * (non-Javadoc)
377
	 *
378
	 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
379
	 */
380
	/** {@inheritDoc} */
381
	@Override
382
	public void dispose() {
383
		super.dispose();
384
		dataChangeBehavior = null;
385
		if (conversation != null) {
386
			conversation.unregisterForDataStoreChanges(this);
387
		}
388
		if(cdmEntitySession != null) {
389
		    cdmEntitySession.dispose();
390
		}
391
		CdmApplicationState.getCurrentDataChangeService().unregister(this);
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
            } else if (cb instanceof Classification) {
526
                getCommonViewer().refresh();
527
            }
528
        }
529

    
530
    }
531
}
(9-9/16)