Project

General

Profile

Download (24.5 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.taxeditor.editor.view.derivate;
10

    
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.Collection;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import javax.annotation.PostConstruct;
23
import javax.annotation.PreDestroy;
24
import javax.inject.Inject;
25
import javax.inject.Named;
26

    
27
import org.eclipse.core.commands.ExecutionException;
28
import org.eclipse.core.commands.operations.IOperationHistory;
29
import org.eclipse.core.runtime.IAdaptable;
30
import org.eclipse.core.runtime.IProgressMonitor;
31
import org.eclipse.core.runtime.IStatus;
32
import org.eclipse.core.runtime.NullProgressMonitor;
33
import org.eclipse.core.runtime.Status;
34
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
35
import org.eclipse.e4.core.contexts.IEclipseContext;
36
import org.eclipse.e4.core.di.annotations.Optional;
37
import org.eclipse.e4.core.services.events.IEventBroker;
38
import org.eclipse.e4.ui.di.Focus;
39
import org.eclipse.e4.ui.di.Persist;
40
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
41
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
42
import org.eclipse.e4.ui.services.EMenuService;
43
import org.eclipse.e4.ui.services.IServiceConstants;
44
import org.eclipse.e4.ui.workbench.modeling.EPartService;
45
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
46
import org.eclipse.jface.util.LocalSelectionTransfer;
47
import org.eclipse.jface.viewers.ISelectionChangedListener;
48
import org.eclipse.jface.viewers.IStructuredSelection;
49
import org.eclipse.jface.viewers.StructuredSelection;
50
import org.eclipse.jface.viewers.TreeNode;
51
import org.eclipse.jface.viewers.TreeSelection;
52
import org.eclipse.jface.viewers.TreeViewer;
53
import org.eclipse.jface.viewers.Viewer;
54
import org.eclipse.jface.viewers.ViewerComparator;
55
import org.eclipse.swt.SWT;
56
import org.eclipse.swt.dnd.DND;
57
import org.eclipse.swt.dnd.Transfer;
58
import org.eclipse.swt.layout.GridData;
59
import org.eclipse.swt.layout.GridLayout;
60
import org.eclipse.swt.widgets.Composite;
61
import org.eclipse.swt.widgets.Tree;
62
import org.eclipse.ui.IMemento;
63
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
64

    
65
import eu.etaxonomy.cdm.api.service.IOccurrenceService;
66
import eu.etaxonomy.cdm.api.service.ITaxonService;
67
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
68
import eu.etaxonomy.cdm.model.molecular.SingleRead;
69
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
70
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
71
import eu.etaxonomy.cdm.model.taxon.Taxon;
72
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
73
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
74
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
75
import eu.etaxonomy.taxeditor.editor.EditorUtil;
76
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
77
import eu.etaxonomy.taxeditor.editor.name.e4.TaxonEditor;
78
import eu.etaxonomy.taxeditor.editor.view.derivate.searchFilter.DerivateSearchCompositeController;
79
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
80
import eu.etaxonomy.taxeditor.model.AbstractUtility;
81
import eu.etaxonomy.taxeditor.model.IContextListener;
82
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
83
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
84
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
85
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
86
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
87
import eu.etaxonomy.taxeditor.model.MessagingUtils;
88
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
89
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
90
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
91
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
92
import eu.etaxonomy.taxeditor.store.CdmStore;
93
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
94
import eu.etaxonomy.taxeditor.view.search.derivative.DerivateContentProvider;
95
import eu.etaxonomy.taxeditor.view.search.derivative.DerivateLabelProvider;
96
import eu.etaxonomy.taxeditor.workbench.part.ICollapsableExpandable;
97
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
98

    
99
/**
100
 * Displays the derivate hierarchy of the specimen specified in the editor input.
101
 */
102
public class DerivateView implements IPartContentHasFactualData,
103
        ICdmEntitySessionEnabled<SpecimenOrObservationBase<?>>, IDirtyMarkable, IPostOperationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
104
        IContextListener, IE4SavablePart, ICollapsableExpandable {
105

    
106
    private static final String SPECIMEN_EDITOR = Messages.DerivateView_SPECIMEN_EDITOR;
107

    
108
    public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView"; //$NON-NLS-1$
109
    public static final String INPUT_ID = ID+".editorInput"; //$NON-NLS-1$
110

    
111
    public static final String YOU_NEED_TO_SAVE_BEFORE_PERFORMING_THIS_ACTION = Messages.DerivateView_YOU_NEED_TO_SAVE;
112
    public static final String VIEW_HAS_UNSAVED_CHANGES = Messages.DerivateView_UNSAVED_CHANGES;
113

    
114
    private static final List<String> SPECIMEN_INIT_STRATEGY = Arrays.asList(new String[] {
115
            "descriptions", //$NON-NLS-1$
116
            "annotations", //$NON-NLS-1$
117
            "markers", //$NON-NLS-1$
118
            "credits", //$NON-NLS-1$
119
            "extensions", //$NON-NLS-1$
120
            "rights", //$NON-NLS-1$
121
            "sources", //$NON-NLS-1$
122
            "derivationEvents.derivatives.annotations", //$NON-NLS-1$
123
            "derivationEvents.derivatives.markers", //$NON-NLS-1$
124
            "derivationEvents.derivatives.credits", //$NON-NLS-1$
125
            "derivationEvents.derivatives.extensions", //$NON-NLS-1$
126
            "derivationEvents.derivatives.rights", //$NON-NLS-1$
127
            "derivationEvents.derivatives.sources" //$NON-NLS-1$
128
    });
129

    
130
	private static final int WARN_THRESHOLD = 200;
131

    
132
	private TreeViewer viewer;
133

    
134
    private final int dndOperations = DND.DROP_MOVE;
135

    
136
    private DerivateLabelProvider labelProvider;
137

    
138
    private DerivateContentProvider contentProvider;
139

    
140
    private DerivateSearchCompositeController derivateSearchCompositeController;
141

    
142
    @Inject
143
    private IEventBroker eventBroker;
144

    
145
    /**
146
     * A map with keys being the derivative entities belonging to the {@link UUID}s passed to the constructor
147
     * and values being the root elements of the hierarchy (may be the same objects as the derivative entities)
148
     */
149
    private Map<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>> derivateToRootEntityMap;
150

    
151
    /**
152
     * The set of root elements
153
     */
154
    private Set<SpecimenOrObservationBase<?>> rootElements;
155

    
156
    private ICdmEntitySession cdmEntitySession;
157

    
158
    /**
159
     * <code>true</code> if this view is listening to selection  changes
160
     */
161
    private boolean listenToSelectionChange;
162

    
163
    private Taxon selectedTaxon;
164

    
165
    @Inject
166
    private ESelectionService selService;
167

    
168
    @Inject
169
    private MDirtyable dirty;
170

    
171
    private ISelectionChangedListener selectionChangedListener;
172

    
173
    private Set<AbstractPostOperation> operations = new HashSet<>();
174

    
175
    @Inject
176
    private MPart thisPart;
177

    
178
    /**
179
     * Default constructor
180
     */
181
    @Inject
182
    public DerivateView() {
183
    }
184

    
185
    public void init(DerivateViewEditorInput editorInput){
186
        this.derivateToRootEntityMap = new HashMap<>();
187
        this.rootElements = new HashSet<>();
188

    
189
        //init tree
190
        Collection<UUID> derivativeUuids = editorInput.getDerivativeUuids();
191
        checkWarnThreshold(derivativeUuids);
192
        updateRootEntities(derivativeUuids);
193
        //set taxon filter
194
        derivateSearchCompositeController.setTaxonFilter(editorInput.getTaxonUuid());
195
        //reset status bar
196
        //TODO e4
197
//        getEditorSite().getActionBars().getStatusLineManager().setMessage(""); //$NON-NLS-1$
198
    }
199

    
200
    @PostConstruct
201
    public void createPartControl(Composite parent, EMenuService menuService,
202
            IEclipseContext context) {
203
        if (CdmStore.isActive()){
204
            if(cdmEntitySession == null){
205
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
206
            }
207
        }
208
        else{
209
            return;
210
        }
211
        //listen to context changes
212
        CdmStore.getContextManager().addContextListener(this);
213

    
214
        parent.setLayout(new GridLayout());
215

    
216
        //---search and filter---
217
        derivateSearchCompositeController = new DerivateSearchCompositeController(parent, this);
218
        GridData gridDataSearchBar = new GridData();
219
        gridDataSearchBar.horizontalAlignment = GridData.FILL;
220
        gridDataSearchBar.grabExcessHorizontalSpace = true;
221
        derivateSearchCompositeController.setLayoutData(gridDataSearchBar);
222
        derivateSearchCompositeController.setEnabled(CdmStore.isActive());
223

    
224
        //---tree viewer---
225
        viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
226
        GridData gridDataTree = new GridData();
227
        gridDataTree.horizontalAlignment = GridData.FILL;
228
        gridDataTree.verticalAlignment = GridData.FILL;
229
        gridDataTree.grabExcessVerticalSpace = true;
230
        gridDataTree.grabExcessHorizontalSpace = true;
231
        viewer.getTree().setLayoutData(gridDataTree);
232
        contentProvider = new DerivateContentProvider();
233
        viewer.setContentProvider(contentProvider);
234
        labelProvider = new DerivateLabelProvider();
235

    
236
        viewer.setLabelProvider(labelProvider);
237
        viewer.getTree().setEnabled(CdmStore.isActive());
238

    
239
        //propagate selection
240
        selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
241
        viewer.addSelectionChangedListener(selectionChangedListener);
242

    
243
        //create context menu
244
        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.editor.popupmenu.specimeneditor");
245

    
246
        //add drag'n'drop support
247
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
248
        viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
249
        DerivateDropListener dropListener = new DerivateDropListener(this);
250
        ContextInjectionFactory.inject(dropListener, context);
251
        viewer.addDropSupport(dndOperations, transfers, dropListener);
252
    }
253

    
254
    public void updateRootEntities() {
255
        updateRootEntities((Collection)null);
256
    }
257

    
258
    public void updateRootEntities(Collection<UUID> derivativeUuids) {
259

    
260
        /*
261
         * If the active session is not the session of the Derivative Editor
262
         * then we will save the active session for later, bind temporarily
263
         * to our session and rebind to the original session when we are
264
         * done. This happens e.g. if a selection change happens in the
265
         * taxon editor and "Link with editor" is enabled. The selection
266
         * change event and thus the loading in updateRootEntities() happens
267
         * in the session of the taxon editor.
268
         */
269
        ICdmEntitySession previousCdmEntitySession = CdmStore.getCurrentSessionManager().getActiveSession();
270
        if(cdmEntitySession != null) {
271
            cdmEntitySession.bind();
272
        }
273
        eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
274
        List<SpecimenOrObservationBase> derivates = null;
275
        if(derivativeUuids!=null){
276
            this.derivateToRootEntityMap = new HashMap<>();
277
            this.rootElements = new HashSet<>();
278
            derivates = CdmStore.getService(IOccurrenceService.class).load(new ArrayList(derivativeUuids), SPECIMEN_INIT_STRATEGY);
279
        }
280
        updateRootEntities(derivates);
281
        if(previousCdmEntitySession!=null){
282
            previousCdmEntitySession.bind();
283
        }
284

    
285
    }
286

    
287
    public void updateRootEntities(List<SpecimenOrObservationBase> derivates) {
288
        if(derivates!=null){
289
            eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
290
            this.derivateToRootEntityMap = new HashMap<>();
291
            this.rootElements = new HashSet<>();
292
            for (SpecimenOrObservationBase<?> derivate : derivates) {
293

    
294
                if(derivate instanceof FieldUnit){
295
                    derivateToRootEntityMap.put(derivate, derivate);
296
                }
297
                else {
298
                    SpecimenOrObservationBase<?> topMostDerivate = EditorUtil.getTopMostDerivate(derivate);
299
                    if(topMostDerivate!=null){
300
                        derivateToRootEntityMap.put(derivate, topMostDerivate);
301
                    }
302
                    else{
303
                        derivateToRootEntityMap.put(derivate, derivate);
304
                    }
305
                }
306
            }
307
            for (SpecimenOrObservationBase<?> specimen : derivateToRootEntityMap.values()) {
308
                rootElements.add(specimen);
309
            }
310
        }
311
        labelProvider.updateLabelCache(rootElements);
312
        viewer.setInput(rootElements);
313
        viewer.setComparator(new ViewerComparator() {
314
        	@Override
315
            public int compare(Viewer testViewer, Object e1, Object e2) {
316
	    		if (((TreeNode)e1).getValue() instanceof SpecimenOrObservationBase){
317
	    			return ((SpecimenOrObservationBase)((TreeNode)e1).getValue()).getTitleCache().compareTo(((SpecimenOrObservationBase)((TreeNode)e2).getValue()).getTitleCache());
318
	    		}else{
319
	    			return e1.toString().compareTo(e2.toString());
320
	    		}
321
	    		//return (((SpecimenOrObservationBase) e1).getTitleCache()).compareTo(((SpecimenOrObservationBase) e2).getTitleCache());
322
    		}
323
    	});
324

    
325
        //TODO e4
326
        //            getEditorSite().getActionBars().getStatusLineManager().setMessage(String.format(Messages.DerivateView_CNT_DERIVATIVES_FOUND, rootElements.size()));
327

    
328
        //set selection to derivatives if the filter criteria
329
        //taxon assignment or derivative type are set
330
        if(derivates!=null && !derivateSearchCompositeController.isDefaultSearch()){
331
            List<TreeNode> nodesToSelect = new ArrayList<>();
332
            for (SpecimenOrObservationBase<?> specimenOrObservationBase : derivates) {
333
                nodesToSelect.add(new TreeNode(specimenOrObservationBase));
334
            }
335
            setSelection(new StructuredSelection(nodesToSelect));
336
        }
337
        else{
338
            setSelection(null);
339
        }
340
    }
341

    
342
    private void setSelection(StructuredSelection selection){
343
        viewer.removeSelectionChangedListener(selectionChangedListener);
344
        viewer.setSelection(selection);
345
        viewer.addSelectionChangedListener(selectionChangedListener);
346
    }
347

    
348
    public void updateLabelCache(){
349
        labelProvider.updateLabelCache(rootElements);
350
    }
351

    
352
    @Persist
353
    @Override
354
    public void save(IProgressMonitor monitor) {
355
        String taskName = Messages.DerivateView_SAVING_HIERARCHY;
356
        monitor.beginTask(taskName, 3);
357

    
358
        if (!cdmEntitySession.isActive()){
359
        	cdmEntitySession.bind();
360
        }
361

    
362
        monitor.worked(1);
363

    
364
        for(AbstractPostOperation entry:operations){
365
            IStatus status = Status.CANCEL_STATUS;
366
            final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
367
                    .getUIInfoAdapter(AbstractUtility.getShell());
368
            String operationlabel = entry.getLabel();
369
            try {
370
                entry.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
371
                status = entry.execute(new NullProgressMonitor(), uiInfoAdapter);
372
            } catch (ExecutionException e) {
373

    
374
                MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
375

    
376
            }
377

    
378
            String statusString = status.equals(Status.OK_STATUS) ? "completed"
379
                    : "cancelled";
380

    
381
            IPostOperationEnabled postOperationEnabled = entry
382
                    .getPostOperationEnabled();
383
            if (postOperationEnabled != null) {
384
                postOperationEnabled.onComplete();
385
            }
386

    
387

    
388
            //AbstractUtility.executeOperation(entry,sync);
389
        }
390

    
391
        operations.clear();
392
        CdmStore.getService(IOccurrenceService.class).merge(new ArrayList<>(rootElements), true);
393

    
394
        monitor.worked(1);
395

    
396
        this.setDirty(false);
397
        monitor.worked(1);
398
        monitor.done();
399
        dirty.setDirty(false);
400
        refreshTree();
401
    }
402

    
403
    /**
404
     * @param isDirty the isDirty to set
405
     */
406
    public void setDirty(boolean isDirty) {
407
        dirty.setDirty(isDirty);
408
    }
409

    
410
    public Set<AbstractPostOperation> getOperations() {
411
        return operations;
412
    }
413

    
414
    public void addOperation(AbstractPostOperation operation) {
415
        this.operations.add(operation);
416
    }
417

    
418
    @Focus
419
    public void setFocus() {
420
        //make sure to bind again if maybe in another view the session was unbound
421

    
422
        if(cdmEntitySession != null) {
423
            cdmEntitySession.bind();
424
        }
425
        if(viewer!=null && !viewer.getControl().isDisposed()) {
426
            viewer.getControl().setFocus();
427
            selService.setSelection(viewer.getSelection());
428
        }
429
    }
430

    
431
    @Override
432
    public void changed(Object element) {
433
        setDirty(true);
434
        viewer.update(new TreeNode(element), null);
435
        viewer.refresh();
436
    }
437

    
438
    @Override
439
    public void forceDirty() {
440
        changed(null);
441
    }
442

    
443
    @Override
444
    public Map<Object, List<String>> getPropertyPathsMap() {
445
        List<String> specimenPropertyPaths = Arrays.asList(new String[] {
446
                "descriptions", //$NON-NLS-1$
447
                "derivationEvents.derivates", //$NON-NLS-1$
448
                "annotations", //$NON-NLS-1$
449
                "markers", //$NON-NLS-1$
450
                "credits", //$NON-NLS-1$
451
                "extensions", //$NON-NLS-1$
452
                "rights", //$NON-NLS-1$
453
                "sources" //$NON-NLS-1$
454
        });
455
        Map<Object, List<String>> specimenPropertyPathMap =
456
                new HashMap<>();
457
        specimenPropertyPathMap.put(SpecimenOrObservationBase.class,specimenPropertyPaths);
458
        return specimenPropertyPathMap;
459
    }
460

    
461
    /**
462
     * Refreshes the derivate hierarchy tree and expands the tree
463
     * to show and select the given object.
464
     *
465
     * @param expandTo the object to which the tree should be expanded
466
     */
467
    public void refreshTree(Object expandTo){
468
        refreshTree();
469
        TreeSelection selection = (TreeSelection) viewer.getSelection();
470
        viewer.expandToLevel(selection.getFirstElement(), 1);
471
        viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
472
    }
473

    
474
    /**
475
     * Refreshes the derivate hierarchy tree
476
     */
477
    public void refreshTree(){
478
    	if(!viewer.getTree().isDisposed()){
479
    		viewer.refresh();
480
    	}
481
    }
482

    
483
    //FIXME:Remoting hack to make this work for remoting
484
    //This should actually be resolved using remoting post operations
485
    public void remove(Object obj) {
486
        if (obj instanceof TreeNode){
487
            obj = ((TreeNode)obj).getValue();
488
        }
489
        rootElements.remove(obj);
490
        this.derivateToRootEntityMap.remove(obj);
491
        viewer.setInput(rootElements);
492
    }
493

    
494
    /**
495
     * @return a set of {@link SingleRead}s that have multiple parents
496
     */
497
    public Set<SingleRead> getMultiLinkSingleReads() {
498
        return DerivateLabelProvider.getMultiLinkSingleReads();
499
    }
500

    
501
    public Object getSelectionInput() {
502
        return selectedTaxon;
503
    }
504

    
505
    public DerivateLabelProvider getLabelProvider() {
506
        return labelProvider;
507
    }
508

    
509
    @Override
510
    public boolean postOperation(Object objectAffectedByOperation) {
511
        refreshTree();
512
        if(objectAffectedByOperation!=null){
513
            changed(objectAffectedByOperation);
514
        }
515
        return true;
516
    }
517

    
518
    @Override
519
    public boolean onComplete() {
520
        return true;
521
    }
522

    
523

    
524
    @Override
525
    public boolean canAttachMedia() {
526
        return true;
527
    }
528

    
529
    public void addFieldUnit(FieldUnit fieldUnit) {
530
        rootElements.add(fieldUnit);
531
        derivateToRootEntityMap.put(fieldUnit, fieldUnit);
532
    }
533

    
534
    @Override
535
    public ICdmEntitySession getCdmEntitySession() {
536
        return cdmEntitySession;
537
    }
538

    
539
    @PreDestroy
540
    public void dispose() {
541
    	if(cdmEntitySession != null) {
542
            cdmEntitySession.dispose();
543
            cdmEntitySession = null;
544
        }
545
        dirty.setDirty(false);
546
    }
547

    
548

    
549
    @Inject
550
    @Optional
551
    public void selectionChanged(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) IStructuredSelection selection,
552
            @Named(IServiceConstants.ACTIVE_PART) MPart activePart, MPart thisPart){
553
        if(activePart == thisPart || viewer==null){
554
            return;
555
        }
556
        if(viewer.getTree().isDisposed()){
557
            return;
558
        }
559
        if(listenToSelectionChange){
560
            selectedTaxon = null;
561
            if(activePart.getObject() instanceof TaxonEditor){
562
                selectedTaxon = ((TaxonEditor) activePart.getObject()).getTaxon();
563
            }
564
            else if(selection != null){
565
                Object selectedElement = selection.getFirstElement();
566
                if(selectedElement instanceof TaxonNodeDto){
567
                    TaxonBase<?> taxonBase = CdmStore.getService(ITaxonService.class).load(((TaxonNodeDto)selectedElement).getTaxonUuid());
568
                    if(HibernateProxyHelper.isInstanceOf(taxonBase, Taxon.class)){
569
                        selectedTaxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
570
                    }
571
                    else if(selectedElement instanceof TaxonNode){
572
                        selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, TaxonNode.class).getTaxon();
573
                    }
574
                    else if(selectedElement instanceof Taxon){
575
                        selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, Taxon.class);
576
                    }
577
                }
578
            }
579
            if(selectedTaxon!=null){
580
                Collection<FieldUnit> fieldUnits = CdmStore.getService(IOccurrenceService.class).listRootUnitsByAssociatedTaxon(FieldUnit.class, selectedTaxon, null, null);
581
                Collection<UUID> uuids = new HashSet<>();
582
                for (SpecimenOrObservationBase<?> specimenOrObservationBase : fieldUnits) {
583
                    uuids.add(specimenOrObservationBase.getUuid());
584
                }
585
                checkWarnThreshold(uuids);
586
                updateRootEntities(uuids);
587

    
588
                thisPart.setLabel(SPECIMEN_EDITOR+": " + selectedTaxon.getName()); //$NON-NLS-1$
589
            }
590
            else{
591
                updateRootEntities((Collection<UUID>)Collections.EMPTY_LIST);
592
            }
593
        }
594
    }
595

    
596
	private void checkWarnThreshold(Collection<UUID> uuids) {
597
		if(uuids!=null && uuids.size()>WARN_THRESHOLD){
598
			MessagingUtils.warningDialog(Messages.DerivateView_PERF_WARNING, this.getClass(), String.format(Messages.DerivateView_PERF_WARNING_MESSAGE, uuids.size()));
599
			uuids.clear();
600
		}
601
	}
602

    
603
    public TreeViewer getViewer() {
604
        return viewer;
605
    }
606

    
607
    @Override
608
    public List<SpecimenOrObservationBase<?>> getRootEntities() {
609
        return new ArrayList<>(rootElements);
610
    }
611

    
612
    public void toggleListenToSelectionChange(MPart part) {
613
        listenToSelectionChange = !listenToSelectionChange;
614
        derivateSearchCompositeController.setEnabled(!listenToSelectionChange);
615
        if(!listenToSelectionChange){
616
            selectedTaxon = null;
617
            part.setLabel(SPECIMEN_EDITOR);
618
        }
619
        else if(selectedTaxon==null){
620
            part.setLabel(SPECIMEN_EDITOR+Messages.DerivateView_NO_TAXON_SELECTED);
621
        }
622
    }
623

    
624
    public DerivateSearchCompositeController getSearchController() {
625
    	return derivateSearchCompositeController;
626
    }
627

    
628
    public boolean isListenToSelectionChange(){
629
        return listenToSelectionChange;
630
    }
631

    
632
    @Override
633
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
634
    }
635

    
636
    @Override
637
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
638
        //close view when workbench closes
639
        try{
640
            thisPart.getContext().get(EPartService.class).hidePart(thisPart);
641
        }
642
        catch(Exception e){
643
            //nothing
644
        }
645
    }
646

    
647
    @Override
648
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
649
    }
650

    
651
    @Override
652
    public void contextRefresh(IProgressMonitor monitor) {
653
    }
654

    
655
    @Override
656
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
657
    }
658

    
659
    @Override
660
    public boolean isDirty() {
661
        return dirty.isDirty();
662
    }
663

    
664
    @Override
665
    public void collapse() {
666
        viewer.collapseAll();
667
    }
668

    
669
    @Override
670
    public void expand() {
671
        viewer.expandAll();
672
    }
673
}
(3-3/6)