Merge branch 'release/5.19.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / derivate / DerivateView.java
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.conversation.ConversationHolder;
66 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
67 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
68 import eu.etaxonomy.cdm.api.service.ITaxonService;
69 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
70 import eu.etaxonomy.cdm.model.molecular.SingleRead;
71 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
72 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
73 import eu.etaxonomy.cdm.model.taxon.Taxon;
74 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
75 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
76 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
77 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
78 import eu.etaxonomy.taxeditor.editor.EditorUtil;
79 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
80 import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
81 import eu.etaxonomy.taxeditor.editor.view.derivate.searchFilter.DerivateSearchCompositeController;
82 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
83 import eu.etaxonomy.taxeditor.model.AbstractUtility;
84 import eu.etaxonomy.taxeditor.model.IContextListener;
85 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
86 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
87 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
88 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
89 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
90 import eu.etaxonomy.taxeditor.model.MessagingUtils;
91 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
92 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
93 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
94 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
95 import eu.etaxonomy.taxeditor.store.CdmStore;
96 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
97 import eu.etaxonomy.taxeditor.view.search.derivative.DerivateContentProvider;
98 import eu.etaxonomy.taxeditor.view.search.derivative.DerivateLabelProvider;
99 import eu.etaxonomy.taxeditor.workbench.part.ICollapsableExpandable;
100 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
101
102 /**
103 * Displays the derivate hierarchy of the specimen specified in the editor input.
104 */
105 public class DerivateView implements IPartContentHasFactualData, IConversationEnabled,
106 ICdmEntitySessionEnabled<SpecimenOrObservationBase<?>>, IDirtyMarkable, IPostOperationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
107 IContextListener, IE4SavablePart, ICollapsableExpandable {
108
109 private static final String SPECIMEN_EDITOR = Messages.DerivateView_SPECIMEN_EDITOR;
110
111 public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView"; //$NON-NLS-1$
112 public static final String INPUT_ID = ID+".editorInput"; //$NON-NLS-1$
113
114 public static final String YOU_NEED_TO_SAVE_BEFORE_PERFORMING_THIS_ACTION = Messages.DerivateView_YOU_NEED_TO_SAVE;
115 public static final String VIEW_HAS_UNSAVED_CHANGES = Messages.DerivateView_UNSAVED_CHANGES;
116
117 private static final List<String> SPECIMEN_INIT_STRATEGY = Arrays.asList(new String[] {
118 "descriptions", //$NON-NLS-1$
119 "annotations", //$NON-NLS-1$
120 "markers", //$NON-NLS-1$
121 "credits", //$NON-NLS-1$
122 "extensions", //$NON-NLS-1$
123 "rights", //$NON-NLS-1$
124 "sources", //$NON-NLS-1$
125 "derivationEvents.derivatives.annotations", //$NON-NLS-1$
126 "derivationEvents.derivatives.markers", //$NON-NLS-1$
127 "derivationEvents.derivatives.credits", //$NON-NLS-1$
128 "derivationEvents.derivatives.extensions", //$NON-NLS-1$
129 "derivationEvents.derivatives.rights", //$NON-NLS-1$
130 "derivationEvents.derivatives.sources" //$NON-NLS-1$
131 });
132
133 private static final int WARN_THRESHOLD = 200;
134
135
136 private ConversationHolder conversation;
137
138 private TreeViewer viewer;
139
140 private final int dndOperations = DND.DROP_MOVE;
141
142 private DerivateLabelProvider labelProvider;
143
144 private DerivateContentProvider contentProvider;
145
146 private DerivateSearchCompositeController derivateSearchCompositeController;
147
148 @Inject
149 private IEventBroker eventBroker;
150
151 /**
152 * A map with keys being the derivative entities belonging to the {@link UUID}s passed to the constructor
153 * and values being the root elements of the hierarchy (may be the same objects as the derivative entities)
154 */
155 private Map<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>> derivateToRootEntityMap;
156
157 /**
158 * The set of root elements
159 */
160 private Set<SpecimenOrObservationBase<?>> rootElements;
161
162 private ICdmEntitySession cdmEntitySession;
163
164 /**
165 * <code>true</code> if this view is listening to selection changes
166 */
167 private boolean listenToSelectionChange;
168
169 private Taxon selectedTaxon;
170
171 @Inject
172 private ESelectionService selService;
173
174 @Inject
175 private MDirtyable dirty;
176
177 private ISelectionChangedListener selectionChangedListener;
178
179 private Set<AbstractPostOperation> operations = new HashSet<>();
180
181 @Inject
182 private MPart thisPart;
183
184 /**
185 * Default constructor
186 */
187 @Inject
188 public DerivateView() {
189 }
190
191 public void init(DerivateViewEditorInput editorInput){
192 this.derivateToRootEntityMap = new HashMap<>();
193 this.rootElements = new HashSet<>();
194
195 //init tree
196 Collection<UUID> derivativeUuids = editorInput.getDerivativeUuids();
197 checkWarnThreshold(derivativeUuids);
198 updateRootEntities(derivativeUuids);
199 //set taxon filter
200 derivateSearchCompositeController.setTaxonFilter(editorInput.getTaxonUuid());
201 //reset status bar
202 //TODO e4
203 // getEditorSite().getActionBars().getStatusLineManager().setMessage(""); //$NON-NLS-1$
204 }
205
206 @PostConstruct
207 public void createPartControl(Composite parent, EMenuService menuService,
208 IEclipseContext context) {
209 if (CdmStore.isActive()){
210 if(conversation == null){
211 conversation = CdmStore.createConversation();
212 }
213 if(cdmEntitySession == null){
214 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
215 }
216 }
217 else{
218 return;
219 }
220 //listen to context changes
221 CdmStore.getContextManager().addContextListener(this);
222
223 parent.setLayout(new GridLayout());
224
225 //---search and filter---
226 derivateSearchCompositeController = new DerivateSearchCompositeController(parent, this);
227 GridData gridDataSearchBar = new GridData();
228 gridDataSearchBar.horizontalAlignment = GridData.FILL;
229 gridDataSearchBar.grabExcessHorizontalSpace = true;
230 derivateSearchCompositeController.setLayoutData(gridDataSearchBar);
231 derivateSearchCompositeController.setEnabled(CdmStore.isActive());
232
233 //---tree viewer---
234 viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
235 GridData gridDataTree = new GridData();
236 gridDataTree.horizontalAlignment = GridData.FILL;
237 gridDataTree.verticalAlignment = GridData.FILL;
238 gridDataTree.grabExcessVerticalSpace = true;
239 gridDataTree.grabExcessHorizontalSpace = true;
240 viewer.getTree().setLayoutData(gridDataTree);
241 contentProvider = new DerivateContentProvider();
242 viewer.setContentProvider(contentProvider);
243 labelProvider = new DerivateLabelProvider();
244 labelProvider.setConversation(conversation);
245 viewer.setLabelProvider(labelProvider);
246 viewer.getTree().setEnabled(CdmStore.isActive());
247
248 //propagate selection
249 selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
250 viewer.addSelectionChangedListener(selectionChangedListener);
251
252 //create context menu
253 menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.editor.popupmenu.specimeneditor");
254
255 //add drag'n'drop support
256 Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
257 viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
258 DerivateDropListener dropListener = new DerivateDropListener(this);
259 ContextInjectionFactory.inject(dropListener, context);
260 viewer.addDropSupport(dndOperations, transfers, dropListener);
261 }
262
263 public void updateRootEntities() {
264 updateRootEntities((Collection)null);
265 }
266
267 public void updateRootEntities(Collection<UUID> derivativeUuids) {
268 if(conversation!=null){
269 if (!conversation.isBound()) {
270 conversation.bind();
271 }
272 /*
273 * If the active session is not the session of the Derivative Editor
274 * then we will save the active session for later, bind temporarily
275 * to our session and rebind to the original session when we are
276 * done. This happens e.g. if a selection change happens in the
277 * taxon editor and "Link with editor" is enabled. The selection
278 * change event and thus the loading in updateRootEntities() happens
279 * in the session of the taxon editor.
280 */
281 ICdmEntitySession previousCdmEntitySession = CdmStore.getCurrentSessionManager().getActiveSession();
282 if(cdmEntitySession != null) {
283 cdmEntitySession.bind();
284 }
285 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
286 List<SpecimenOrObservationBase> derivates = null;
287 if(derivativeUuids!=null){
288 this.derivateToRootEntityMap = new HashMap<>();
289 this.rootElements = new HashSet<>();
290 derivates = CdmStore.getService(IOccurrenceService.class).load(new ArrayList(derivativeUuids), SPECIMEN_INIT_STRATEGY);
291 }
292 updateRootEntities(derivates);
293 if(previousCdmEntitySession!=null){
294 previousCdmEntitySession.bind();
295 }
296 }
297 }
298
299 public void updateRootEntities(List<SpecimenOrObservationBase> derivates) {
300 if(derivates!=null){
301 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
302 this.derivateToRootEntityMap = new HashMap<>();
303 this.rootElements = new HashSet<>();
304 for (SpecimenOrObservationBase<?> derivate : derivates) {
305
306 if(derivate instanceof FieldUnit){
307 derivateToRootEntityMap.put(derivate, derivate);
308 }
309 else {
310 SpecimenOrObservationBase<?> topMostDerivate = EditorUtil.getTopMostDerivate(derivate);
311 if(topMostDerivate!=null){
312 derivateToRootEntityMap.put(derivate, topMostDerivate);
313 }
314 else{
315 derivateToRootEntityMap.put(derivate, derivate);
316 }
317 }
318 }
319 for (SpecimenOrObservationBase<?> specimen : derivateToRootEntityMap.values()) {
320 rootElements.add(specimen);
321 }
322 }
323 labelProvider.updateLabelCache(rootElements);
324 viewer.setInput(rootElements);
325 viewer.setComparator(new ViewerComparator() {
326 @Override
327 public int compare(Viewer testViewer, Object e1, Object e2) {
328 if (((TreeNode)e1).getValue() instanceof SpecimenOrObservationBase){
329 return ((SpecimenOrObservationBase)((TreeNode)e1).getValue()).getTitleCache().compareTo(((SpecimenOrObservationBase)((TreeNode)e2).getValue()).getTitleCache());
330 }else{
331 return e1.toString().compareTo(e2.toString());
332 }
333 //return (((SpecimenOrObservationBase) e1).getTitleCache()).compareTo(((SpecimenOrObservationBase) e2).getTitleCache());
334 }
335 });
336
337 //TODO e4
338 // getEditorSite().getActionBars().getStatusLineManager().setMessage(String.format(Messages.DerivateView_CNT_DERIVATIVES_FOUND, rootElements.size()));
339
340 //set selection to derivatives if the filter criteria
341 //taxon assignment or derivative type are set
342 if(derivates!=null && !derivateSearchCompositeController.isDefaultSearch()){
343 List<TreeNode> nodesToSelect = new ArrayList<>();
344 for (SpecimenOrObservationBase specimenOrObservationBase : derivates) {
345 nodesToSelect.add(new TreeNode(specimenOrObservationBase));
346 }
347 setSelection(new StructuredSelection(nodesToSelect));
348 }
349 else{
350 setSelection(null);
351 }
352 }
353
354 private void setSelection(StructuredSelection selection){
355 viewer.removeSelectionChangedListener(selectionChangedListener);
356 viewer.setSelection(selection);
357 viewer.addSelectionChangedListener(selectionChangedListener);
358 }
359
360 public void updateLabelCache(){
361 labelProvider.updateLabelCache(rootElements);
362 }
363
364 @Persist
365 @Override
366 public void save(IProgressMonitor monitor) {
367 String taskName = Messages.DerivateView_SAVING_HIERARCHY;
368 monitor.beginTask(taskName, 3);
369 if (!conversation.isBound()) {
370 conversation.bind();
371 if (!cdmEntitySession.isActive()){
372 cdmEntitySession.bind();
373 }
374 }
375 monitor.worked(1);
376
377 // commit the conversation and start a new transaction immediately
378 conversation.commit(true);
379
380 for(AbstractPostOperation entry:operations){
381 IStatus status = Status.CANCEL_STATUS;
382 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
383 .getUIInfoAdapter(AbstractUtility.getShell());
384 String operationlabel = entry.getLabel();
385 try {
386 entry.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
387 status = entry.execute(new NullProgressMonitor(), uiInfoAdapter);
388 } catch (ExecutionException e) {
389
390 MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
391
392 }
393
394 String statusString = status.equals(Status.OK_STATUS) ? "completed"
395 : "cancelled";
396
397 IPostOperationEnabled postOperationEnabled = entry
398 .getPostOperationEnabled();
399 if (postOperationEnabled != null) {
400 postOperationEnabled.onComplete();
401 }
402
403
404 //AbstractUtility.executeOperation(entry,sync);
405 }
406
407 operations.clear();
408 CdmStore.getService(IOccurrenceService.class).merge(new ArrayList<>(rootElements), true);
409
410 monitor.worked(1);
411
412 this.setDirty(false);
413 monitor.worked(1);
414 monitor.done();
415 dirty.setDirty(false);
416 refreshTree();
417 }
418
419 /**
420 * @param isDirty the isDirty to set
421 */
422 public void setDirty(boolean isDirty) {
423 dirty.setDirty(isDirty);
424 }
425
426 public Set<AbstractPostOperation> getOperations() {
427 return operations;
428 }
429
430 public void addOperation(AbstractPostOperation operation) {
431 this.operations.add(operation);
432 }
433
434 @Focus
435 public void setFocus() {
436 //make sure to bind again if maybe in another view the conversation was unbound
437 if(conversation!=null && !conversation.isBound()){
438 conversation.bind();
439 }
440 if(cdmEntitySession != null) {
441 cdmEntitySession.bind();
442 }
443 if(viewer!=null && !viewer.getControl().isDisposed()) {
444 viewer.getControl().setFocus();
445 selService.setSelection(viewer.getSelection());
446 }
447 }
448
449 @Override
450 public void update(CdmDataChangeMap changeEvents) {
451 }
452
453 @Override
454 public ConversationHolder getConversationHolder() {
455 return conversation;
456 }
457
458 @Override
459 public void changed(Object element) {
460 setDirty(true);
461 //firePropertyChange(IEditorPart.PROP_DIRTY);
462 viewer.update(new TreeNode(element), null);
463 viewer.refresh();
464 }
465
466 @Override
467 public void forceDirty() {
468 changed(null);
469 }
470
471 @Override
472 public Map<Object, List<String>> getPropertyPathsMap() {
473 List<String> specimenPropertyPaths = Arrays.asList(new String[] {
474 "descriptions", //$NON-NLS-1$
475 "derivationEvents.derivates", //$NON-NLS-1$
476 "annotations", //$NON-NLS-1$
477 "markers", //$NON-NLS-1$
478 "credits", //$NON-NLS-1$
479 "extensions", //$NON-NLS-1$
480 "rights", //$NON-NLS-1$
481 "sources" //$NON-NLS-1$
482 });
483 Map<Object, List<String>> specimenPropertyPathMap =
484 new HashMap<>();
485 specimenPropertyPathMap.put(SpecimenOrObservationBase.class,specimenPropertyPaths);
486 return specimenPropertyPathMap;
487 }
488
489 /**
490 * Refreshes the derivate hierarchy tree and expands the tree
491 * to show and select the given object.
492 *
493 * @param expandTo the object to which the tree should be expanded
494 */
495 public void refreshTree(Object expandTo){
496 refreshTree();
497 TreeSelection selection = (TreeSelection) viewer.getSelection();
498 viewer.expandToLevel(selection.getFirstElement(), 1);
499 viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
500 }
501
502 /**
503 * Refreshes the derivate hierarchy tree
504 */
505 public void refreshTree(){
506 if(!viewer.getTree().isDisposed()){
507 viewer.refresh();
508 }
509 }
510
511 //FIXME:Remoting hack to make this work for remoting
512 //This should actually be resolved using remoting post operations
513 public void remove(Object obj) {
514 if (obj instanceof TreeNode){
515 obj = ((TreeNode)obj).getValue();
516 }
517 rootElements.remove(obj);
518 this.derivateToRootEntityMap.remove(obj);
519 viewer.setInput(rootElements);
520 }
521
522 /**
523 * @return a set of {@link SingleRead}s that have multiple parents
524 */
525 public Set<SingleRead> getMultiLinkSingleReads() {
526 return DerivateLabelProvider.getMultiLinkSingleReads();
527 }
528
529 public Object getSelectionInput() {
530 return selectedTaxon;
531 }
532
533 public DerivateLabelProvider getLabelProvider() {
534 return labelProvider;
535 }
536
537 @Override
538 public boolean postOperation(Object objectAffectedByOperation) {
539 refreshTree();
540 if(objectAffectedByOperation!=null){
541 changed(objectAffectedByOperation);
542 }
543 return true;
544 }
545
546 @Override
547 public boolean onComplete() {
548 return true;
549 }
550
551
552 @Override
553 public boolean canAttachMedia() {
554 return true;
555 }
556
557 public void addFieldUnit(FieldUnit fieldUnit) {
558 rootElements.add(fieldUnit);
559 derivateToRootEntityMap.put(fieldUnit, fieldUnit);
560 }
561
562 @Override
563 public ICdmEntitySession getCdmEntitySession() {
564 return cdmEntitySession;
565 }
566
567 @PreDestroy
568 public void dispose() {
569 if(conversation!=null){
570 conversation.close();
571 conversation = null;
572 }
573 if(cdmEntitySession != null) {
574 cdmEntitySession.dispose();
575 cdmEntitySession = null;
576 }
577 dirty.setDirty(false);
578 }
579
580
581 @Inject
582 @Optional
583 public void selectionChanged(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) IStructuredSelection selection,
584 @Named(IServiceConstants.ACTIVE_PART) MPart activePart, MPart thisPart){
585 if(activePart == thisPart || viewer==null){
586 return;
587 }
588 if(viewer.getTree().isDisposed()){
589 return;
590 }
591 if(listenToSelectionChange){
592 selectedTaxon = null;
593 if(activePart.getObject() instanceof TaxonNameEditorE4){
594 selectedTaxon = ((TaxonNameEditorE4) activePart.getObject()).getTaxon();
595 }
596 else if(selection != null){
597 Object selectedElement = selection.getFirstElement();
598 if(selectedElement instanceof TaxonNodeDto){
599 TaxonBase<?> taxonBase = CdmStore.getService(ITaxonService.class).load(((TaxonNodeDto)selectedElement).getTaxonUuid());
600 if(HibernateProxyHelper.isInstanceOf(taxonBase, Taxon.class)){
601 selectedTaxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
602 }
603 else if(selectedElement instanceof TaxonNode){
604 selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, TaxonNode.class).getTaxon();
605 }
606 else if(selectedElement instanceof Taxon){
607 selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, Taxon.class);
608 }
609 }
610 }
611 if(selectedTaxon!=null){
612 Collection<FieldUnit> fieldUnits = CdmStore.getService(IOccurrenceService.class).listRootUnitsByAssociatedTaxon(FieldUnit.class, selectedTaxon, null, null);
613 Collection<UUID> uuids = new HashSet<>();
614 for (SpecimenOrObservationBase<?> specimenOrObservationBase : fieldUnits) {
615 uuids.add(specimenOrObservationBase.getUuid());
616 }
617 checkWarnThreshold(uuids);
618 updateRootEntities(uuids);
619
620 thisPart.setLabel(SPECIMEN_EDITOR+": " + selectedTaxon.getName()); //$NON-NLS-1$
621 }
622 else{
623 updateRootEntities((Collection<UUID>)Collections.EMPTY_LIST);
624 }
625 }
626 }
627
628 private void checkWarnThreshold(Collection<UUID> uuids) {
629 if(uuids!=null && uuids.size()>WARN_THRESHOLD){
630 MessagingUtils.warningDialog(Messages.DerivateView_PERF_WARNING, this.getClass(), String.format(Messages.DerivateView_PERF_WARNING_MESSAGE, uuids.size()));
631 uuids.clear();
632 }
633 }
634
635 public TreeViewer getViewer() {
636 return viewer;
637 }
638
639 @Override
640 public List<SpecimenOrObservationBase<?>> getRootEntities() {
641 return new ArrayList<>(rootElements);
642 }
643
644 public void toggleListenToSelectionChange(MPart part) {
645 listenToSelectionChange = !listenToSelectionChange;
646 derivateSearchCompositeController.setEnabled(!listenToSelectionChange);
647 if(!listenToSelectionChange){
648 selectedTaxon = null;
649 part.setLabel(SPECIMEN_EDITOR);
650 }
651 else if(selectedTaxon==null){
652 part.setLabel(SPECIMEN_EDITOR+Messages.DerivateView_NO_TAXON_SELECTED);
653 }
654 }
655
656 public boolean isListenToSelectionChange(){
657 return listenToSelectionChange;
658 }
659
660 @Override
661 public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
662 }
663
664 @Override
665 public void contextStop(IMemento memento, IProgressMonitor monitor) {
666 //close view when workbench closes
667 try{
668 thisPart.getContext().get(EPartService.class).hidePart(thisPart);
669 }
670 catch(Exception e){
671 //nothing
672 }
673 }
674
675 @Override
676 public void contextStart(IMemento memento, IProgressMonitor monitor) {
677 }
678
679 @Override
680 public void contextRefresh(IProgressMonitor monitor) {
681 }
682
683 @Override
684 public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
685 }
686
687 @Override
688 public boolean isDirty() {
689 return dirty.isDirty();
690 }
691
692 @Override
693 public void collapse() {
694 viewer.collapseAll();
695 }
696
697 @Override
698 public void expand() {
699 viewer.expandAll();
700 }
701 }