Project

General

Profile

Download (14.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.Arrays;
15
import java.util.Comparator;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Observable;
21
import java.util.Observer;
22
import java.util.Set;
23
import java.util.UUID;
24

    
25
import org.eclipse.core.runtime.IAdaptable;
26
import org.eclipse.core.runtime.IProgressMonitor;
27
import org.eclipse.jface.viewers.DoubleClickEvent;
28
import org.eclipse.jface.viewers.TreePath;
29
import org.eclipse.ui.IMemento;
30
import org.eclipse.ui.IViewSite;
31
import org.eclipse.ui.PartInitException;
32
import org.eclipse.ui.navigator.CommonNavigator;
33

    
34
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
35
import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
36
import eu.etaxonomy.cdm.api.application.ICdmChangeListener;
37
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
38
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
39
import eu.etaxonomy.cdm.api.service.IClassificationService;
40
import eu.etaxonomy.cdm.model.common.CdmBase;
41
import eu.etaxonomy.cdm.model.taxon.Classification;
42
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
43
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
44
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByRankAndNameComparator;
45
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
46
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
47
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
48
import eu.etaxonomy.taxeditor.model.MessagingUtils;
49
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
50
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
51
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
52
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
53
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
54
import eu.etaxonomy.taxeditor.store.CdmStore;
55
import eu.etaxonomy.taxeditor.store.LoginManager;
56

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

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

    
75
	private static final String TREE_PATH = "treepath";
76

    
77
	private static final String TREE_PATHS = "treepaths";
78

    
79
	private ConversationHolder conversation;
80

    
81
	private ICdmEntitySession cdmEntitySession;
82

    
83
	private String partNameCache;
84

    
85
	private IDataChangeBehavior dataChangeBehavior;
86

    
87
	private Root root;
88

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

    
122
		if (CdmStore.isActive()) {
123

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

    
134
	/** {@inheritDoc} */
135
	@Override
136
	public void init(IViewSite site) throws PartInitException {
137
		super.init(site);
138
		init();
139
	}
140

    
141
	/**
142
	 * <p>
143
	 * init
144
	 * </p>
145
	 */
146
	public void init() {
147

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

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

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

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

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

    
209
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
210

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

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

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

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

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

    
259
		List<CdmBase> pathList = new ArrayList<CdmBase>();
260

    
261
		if (string.length() == 0) {
262
            return null;
263
        }
264

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

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

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

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

    
307
		super.saveState(memento);
308

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

    
312
		monitor.beginTask("Saving Taxon Navigator State", treePaths.length);
313

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

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

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

    
366
		DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
367
	}
368

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

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

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

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

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

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

    
459
	/**
460
	 * <p>
461
	 * onComplete
462
	 * </p>
463
	 *
464
	 * @return a boolean.
465
	 */
466
	@Override
467
	public boolean onComplete() {
468
		return true;
469
	}
470

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

    
491

    
492
	/* (non-Javadoc)
493
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
494
	 */
495
	@Override
496
	public void update(Observable o, Object arg) {
497
		if(o instanceof LoginManager){
498
			refresh();
499
		}
500

    
501
	}
502

    
503
    /* (non-Javadoc)
504
     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getCdmEntitySession()
505
     */
506
    @Override
507
    public ICdmEntitySession getCdmEntitySession() {
508
       return cdmEntitySession;
509
    }
510

    
511
    /* (non-Javadoc)
512
     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getRootEntities()
513
     */
514
    @Override
515
    public List<Classification> getRootEntities() {
516
        if(root != null) {
517
            return root.getParentBeans();
518
        }
519
        return null;
520
    }
521

    
522
    /* (non-Javadoc)
523
     * @see eu.etaxonomy.cdm.api.application.ICdmChangeListener#onChange(eu.etaxonomy.cdm.api.application.CdmChangeEvent)
524
     */
525
    @Override
526
    public void onChange(CdmChangeEvent event) {
527
        for(CdmBase cb : event.getChangedObjects()) {
528
            if(cb instanceof TaxonNode) {
529
                TaxonNode tn = (TaxonNode)cb;
530
                if(tn.getTaxon() == null) {
531
                    getCommonViewer().refresh(tn.getClassification());
532
                } else {
533
                    getCommonViewer().refresh(cb);
534
                }
535
            } else if (cb instanceof Classification) {
536
                getCommonViewer().refresh();
537
            }
538
        }
539

    
540
    }
541

    
542
    /* (non-Javadoc)
543
     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getPropertyPathsMap()
544
     */
545
    @Override
546
    public Map<Object, List<String>> getPropertyPathsMap() {
547
        Map<Object, List<String>> propertyPathsMap = new HashMap<Object, List<String>>();
548
        List<String> taxonNodePropertyPaths = Arrays.asList(new String[] {
549
                "taxon.name"
550
        });
551
         propertyPathsMap.put("childNodes", taxonNodePropertyPaths);
552
        return propertyPathsMap;
553
    }
554
}
(9-9/16)