Project

General

Profile

Download (14.5 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
		CdmApplicationState.getCurrentDataChangeService().unregister(this);
395
	}
396

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

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

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

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

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

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

    
489

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

    
499
	}
500

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

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

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

    
533
    }
534

    
535
    /* (non-Javadoc)
536
     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getPropertyPathsMap()
537
     */
538
    @Override
539
    public Map<Object, List<String>> getPropertyPathsMap() {
540
        Map<Object, List<String>> propertyPathsMap = new HashMap<Object, List<String>>();
541
        List<String> taxonNodePropertyPaths = Arrays.asList(new String[] {
542
                "taxon.name"
543
        });
544
         propertyPathsMap.put("childNodes", taxonNodePropertyPaths);
545
        return propertyPathsMap;
546
    }
547
}
(9-9/16)