614bd7aff6c2b230f5cba05f9488d1ac9dfca8ae
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / name / e4 / TaxonNameEditorE4.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
10 package eu.etaxonomy.taxeditor.editor.name.e4;
11
12 import java.util.ArrayList;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.UUID;
17
18 import javax.annotation.PostConstruct;
19 import javax.annotation.PreDestroy;
20 import javax.inject.Inject;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.eclipse.core.commands.operations.IUndoContext;
24 import org.eclipse.core.commands.operations.UndoContext;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.OperationCanceledException;
27 import org.eclipse.e4.core.contexts.IEclipseContext;
28 import org.eclipse.e4.core.di.annotations.Optional;
29 import org.eclipse.e4.core.services.events.IEventBroker;
30 import org.eclipse.e4.ui.di.Focus;
31 import org.eclipse.e4.ui.di.Persist;
32 import org.eclipse.e4.ui.di.UIEventTopic;
33 import org.eclipse.e4.ui.di.UISynchronize;
34 import org.eclipse.e4.ui.model.application.MApplication;
35 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
36 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
37 import org.eclipse.e4.ui.services.EMenuService;
38 import org.eclipse.e4.ui.workbench.modeling.EModelService;
39 import org.eclipse.e4.ui.workbench.modeling.EPartService;
40 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
41 import org.eclipse.jface.dialogs.MessageDialog;
42 import org.eclipse.jface.viewers.ISelection;
43 import org.eclipse.jface.viewers.ISelectionProvider;
44 import org.eclipse.jface.viewers.StructuredSelection;
45 import org.eclipse.swt.dnd.DND;
46 import org.eclipse.swt.dnd.DropTarget;
47 import org.eclipse.swt.dnd.Transfer;
48 import org.eclipse.swt.graphics.Color;
49 import org.eclipse.swt.widgets.Composite;
50 import org.eclipse.ui.ISelectionListener;
51 import org.eclipse.ui.IWorkbenchPart;
52 import org.eclipse.ui.IWorkbenchPartReference;
53 import org.eclipse.ui.forms.ManagedForm;
54 import org.eclipse.ui.forms.widgets.FormToolkit;
55 import org.eclipse.ui.forms.widgets.ScrolledForm;
56 import org.eclipse.ui.forms.widgets.TableWrapLayout;
57
58 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
59 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
60 import eu.etaxonomy.cdm.api.service.DeleteResult;
61 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
62 import eu.etaxonomy.cdm.model.common.CdmBase;
63 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
64 import eu.etaxonomy.cdm.model.name.TaxonName;
65 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
66 import eu.etaxonomy.cdm.model.taxon.Taxon;
67 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
68 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
69 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
70 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
71 import eu.etaxonomy.taxeditor.editor.CdmDataTransfer;
72 import eu.etaxonomy.taxeditor.editor.EditorUtil;
73 import eu.etaxonomy.taxeditor.editor.ISecuredEditor;
74 import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
75 import eu.etaxonomy.taxeditor.editor.e4.TaxonEditorInputE4;
76 import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
77 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
78 import eu.etaxonomy.taxeditor.editor.name.e4.container.AbstractGroupE4;
79 import eu.etaxonomy.taxeditor.editor.name.e4.container.AbstractGroupedContainerE4;
80 import eu.etaxonomy.taxeditor.editor.name.e4.container.AcceptedGroupE4;
81 import eu.etaxonomy.taxeditor.editor.name.e4.container.AcceptedNameContainerE4;
82 import eu.etaxonomy.taxeditor.editor.name.e4.container.ConceptContainerE4;
83 import eu.etaxonomy.taxeditor.editor.name.e4.container.ContainerFactoryE4;
84 import eu.etaxonomy.taxeditor.editor.name.e4.container.HomotypicalSynonymGroupE4;
85 import eu.etaxonomy.taxeditor.editor.name.e4.container.MisappliedGroupE4;
86 import eu.etaxonomy.taxeditor.editor.name.e4.dnd.NameEditorDropTargetListenerE4;
87 import eu.etaxonomy.taxeditor.event.EventUtility;
88 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
89 import eu.etaxonomy.taxeditor.model.AbstractUtility;
90 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
91 import eu.etaxonomy.taxeditor.model.IPartChangeListener;
92 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
93 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
94 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
95 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
96 import eu.etaxonomy.taxeditor.model.MessagingUtils;
97 import eu.etaxonomy.taxeditor.model.TaxeditorPartService;
98 import eu.etaxonomy.taxeditor.preference.Resources;
99 import eu.etaxonomy.taxeditor.security.RequiredPermissions;
100 import eu.etaxonomy.taxeditor.store.CdmStore;
101 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
102
103 /**
104 *
105 * @author pplitzner
106 * @date Aug 24, 2017
107 *
108 */
109 public class TaxonNameEditorE4 implements IConversationEnabled, IDirtyMarkable, IPartContentHasDetails,
110 IPartContentHasSupplementalData, IPartContentHasMedia, IPartContentHasFactualData, IPartChangeListener,
111 ISelectionListener, ISecuredEditor, IE4SavablePart, ITaxonEditor, IDropTargetableE4 {
112
113 private Taxon taxon;
114
115 private ManagedForm managedForm;
116 private ScrolledForm scrolledForm;
117 private Composite parent;
118 private ISelectionProvider simpleSelectionProvider;
119
120 private TaxonBase selection;
121
122 private ConversationHolder conversation;
123
124 private AcceptedGroupE4 acceptedGroup;
125 private List<HomotypicalSynonymGroupE4> heterotypicSynonymGroups = new ArrayList<>();
126 private MisappliedGroupE4 misappliedGroup;
127
128 private DropTarget target;
129
130 @Inject
131 UISynchronize sync;
132
133 private TaxonBase objectAffectedByLastOperation;
134
135 @Inject
136 private EMenuService menuService;
137
138 @Inject
139 private ESelectionService selService;
140
141 @Inject
142 private IEclipseContext context;
143
144 @Inject
145 private MDirtyable dirty;
146
147 @Inject
148 private MApplication application;
149
150 private MPart thisPart;
151
152 private TaxonEditorInputE4 input;
153
154 private UndoContext undoContext;
155
156 @Inject
157 private IEventBroker eventBroker;
158
159 @Inject
160 public TaxonNameEditorE4() {
161 undoContext = new UndoContext();
162 }
163
164 @PostConstruct
165 public void createPartControl(Composite parent, MPart thisPart) {
166 this.thisPart = thisPart;
167
168 createManagedForm(parent);
169
170 TaxeditorPartService.getInstance().addListener(TaxeditorPartService.PART_ACTIVATED, this);
171
172 }
173
174 protected void createManagedForm(Composite composite) {
175
176 managedForm = new ManagedForm(composite) {
177
178 @Override
179 public void dirtyStateChanged() {
180 dirty.setDirty(true);
181 }
182
183 @Override
184 public boolean setInput(Object input) {
185 if (input instanceof AbstractGroupedContainerE4) {
186 TaxonBase newSelection = ((AbstractGroupedContainerE4) input).getData();
187 if (selection != newSelection || TaxonNameEditorE4.this.isDirty()) {
188 selection = newSelection;
189 selService.setSelection(new StructuredSelection(selection));
190
191 }
192 } else if (input == null) {
193 selection = null;
194 selService.setSelection(new StructuredSelection());
195 }
196
197 return super.setInput(input);
198 }
199 };
200
201 scrolledForm = managedForm.getForm();
202 parent = scrolledForm.getBody();
203
204 parent.setData(taxon);
205
206 TableWrapLayout layout = new TableWrapLayout();
207 layout.leftMargin = 0;
208 layout.rightMargin = 0;
209 layout.topMargin = 0;
210 layout.bottomMargin = 0;
211
212 layout.verticalSpacing = 0;
213 layout.horizontalSpacing = 0;
214
215 parent.setLayout(layout);
216 parent.setBackground(AbstractUtility.getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
217 }
218
219 public void createOrUpdateNameComposites(boolean accepted, boolean heterotypicGroups, boolean misappliedNames) {
220
221 if (accepted) {
222 ContainerFactoryE4.createOrUpdateAcceptedTaxonsHomotypicGroup(this);
223 }
224 if (heterotypicGroups) {
225 ContainerFactoryE4.createOrUpdateHeterotypicSynonymyGroups(this);
226 }
227 if (misappliedNames) {
228 ContainerFactoryE4.createOrUpdateMisapplicationsGroup(this);
229 }
230 ContainerFactoryE4.setMenuToAllContainers(this);
231
232 // Redraw composite
233 parent.pack();
234 managedForm.refresh();
235 managedForm.reflow(true);
236
237 }
238
239 @Override
240 public Taxon getTaxon() {
241 return HibernateProxyHelper.deproxy(taxon);
242 }
243
244 public void setDirty() {
245 managedForm.dirtyStateChanged();
246 }
247
248 @Focus
249 public void setFocus() {
250 // make sure to bind again if maybe in another view the conversation was
251 // unbound
252 if (conversation != null && !conversation.isBound()) {
253 conversation.bind();
254 }
255
256 if (input != null) {
257 if (getSelectedContainer() == null) {
258 throw new IllegalStateException(Messages.TaxonNameEditor_THERE_SHOULD_ALWAYS_BE);
259 }
260 getSelectedContainer().setSelected();
261
262 if (!input.getCdmEntitySession().isActive()) {
263 input.bind();
264 }
265
266 // check permissions
267 boolean doEnable = permissionsSatisfied();
268 managedForm.getForm().setEnabled(doEnable);
269 }
270 if(selection!=null){
271 selService.setSelection(new StructuredSelection(selection));
272 }
273 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
274 }
275
276 @Override
277 public boolean permissionsSatisfied() {
278 TaxonNode taxonNode = input.getTaxonNode();
279 boolean doEnable = CdmStore.currentAuthentiationHasPermission(taxonNode.getTaxon(),
280 RequiredPermissions.TAXON_EDIT);
281 return doEnable;
282 }
283
284 @Override
285 public ConversationHolder getConversationHolder() {
286 return conversation;
287 }
288
289 /** {@inheritDoc} */
290 @Override
291 public void update(CdmDataChangeMap events) {
292 // redraw();
293 }
294
295 /**
296 * Redraws this editor return true on success
297 *
298 * @return a boolean.
299 */
300 public boolean redraw() {
301 return redraw(true, true, true, true);
302 }
303
304 /**
305 * {@inheritDoc}
306 *
307 * Redraws the editor controls
308 */
309 public boolean redraw(boolean focus, boolean accepted, boolean heterotypic, boolean misappliedNames) {
310
311 createOrUpdateNameComposites(accepted, heterotypic, misappliedNames);
312
313 if (focus) {
314 setFocus();
315 }
316
317 return true;
318 }
319
320 @Override
321 public boolean postOperation(Object objectAffectedByOperation) {
322 if (objectAffectedByOperation instanceof TaxonBase) {
323 objectAffectedByLastOperation = (TaxonBase) objectAffectedByOperation;
324 }
325
326 redraw(true, true, true, true);
327 changed(objectAffectedByOperation);
328 onComplete();
329 return true;
330 }
331
332 public ManagedForm getManagedForm() {
333 return managedForm;
334 }
335
336 /**
337 * <p>
338 * checkForEmptyNames
339 * </p>
340 *
341 * @return true if there are empty names
342 */
343 public boolean checkForEmptyNames() {
344 for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
345 if (container != null
346 && (container.getName() == null || StringUtils.isEmpty(container.getName().getTitleCache()))) {
347 return true;
348 }
349 }
350 return false;
351 }
352
353 public Set<AbstractGroupedContainerE4> getEmptyContainers() {
354 Set<AbstractGroupedContainerE4> containersWithEmptyNames = new HashSet<>();
355
356 for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
357 if (container.getName() == null || StringUtils.isEmpty(container.getName().getTitleCache())) {
358 containersWithEmptyNames.add(container);
359 }
360 }
361
362 return containersWithEmptyNames;
363 }
364
365 /** {@inheritDoc} */
366 @Override
367 @Persist
368 public void save(IProgressMonitor monitor) {
369
370 monitor.beginTask(Messages.TaxonNameEditor_SAVING_NAMES, getGroupedContainers().size());
371 if (!conversation.isBound()) {
372 conversation.bind();
373
374 }
375 conversation.commit(true);
376 monitor.worked(1);
377
378 // check for empty names
379 if (checkForEmptyNames()) {
380 MessageDialog.openWarning(AbstractUtility.getShell(), Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED,
381 Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE);
382 return;
383 }
384 for (AbstractGroupedContainerE4 container : getGroupedContainers()) {
385
386 monitor.subTask(Messages.TaxonNameEditor_SAVING_COMPOSITES + container.getTaxonBase().getTitleCache());
387 container.persistName();
388 // because of missing cascading the concepts need to be saved
389 // separately
390 if (container instanceof ConceptContainerE4) {
391 input.addToSaveNewConcept((Taxon) container.getData());
392 }
393 // In case the progress monitor was canceled throw an exception.
394 if (monitor.isCanceled()) {
395 throw new OperationCanceledException();
396 }
397
398 // Otherwise declare this step as done.
399 monitor.worked(1);
400
401 }
402 input.setSync(sync);
403 input.merge();
404 // commit the conversation and start a new transaction immediately
405 conversation.commit(true);
406
407 dirty.setDirty(false);
408 EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAVIGATOR, true);
409 EventUtility.postEvent(WorkbenchEventConstants.SAVE_TAXON, true);
410 // Stop the progress monitor.
411 monitor.done();
412 }
413
414 public void init(TaxonEditorInputE4 input) {
415 if (this.input != null) {
416 this.input.dispose();
417 // this.acceptedGroup = null;
418 // this.heterotypicSynonymGroups.clear();
419 // this.misappliedGroup = null;
420 }
421 if (!(input != null)) {
422 MessagingUtils.error(this.getClass(), new Exception(Messages.TaxonNameEditor_INVALID_INPUT));
423 return;
424 }
425
426 if (input.getAdapter(Taxon.class) != null) {
427 taxon = CdmBase.deproxy(input.getAdapter(Taxon.class), Taxon.class);
428 } else {
429 MessagingUtils.error(this.getClass(), new Exception(Messages.TaxonNameEditor_INVALID_INPUT_TAXON_NULL));
430 return;
431 }
432
433 this.input = input;
434 conversation = input.getConversationHolder();
435
436 createOrUpdateNameComposites(true, true, true);
437
438 createDragSupport();
439
440 setPartName();
441
442 // set initial selection
443 TaxonBase initiallySelectedTaxonBase = input.getInitiallySelectedTaxonBase();
444 if (initiallySelectedTaxonBase != null) {
445 selService.setSelection(new StructuredSelection(initiallySelectedTaxonBase));
446 getContainer(initiallySelectedTaxonBase).setSelected();
447 }
448 }
449
450 private void createDragSupport() {
451 // Listen for names being dragged outside of existing homotypic groups -
452 // user wants to create a new group
453 Transfer[] types = new Transfer[] { CdmDataTransfer.getInstance() };
454 int operations = DND.DROP_MOVE;
455 if (target == null) {
456 target = new DropTarget(parent, operations);
457 target.setTransfer(types);
458 target.addDropListener(new NameEditorDropTargetListenerE4(this));
459 }
460 }
461
462 public AcceptedNameContainerE4 getAcceptedNameContainer() {
463 return getAcceptedGroup().getAcceptedNameContainer();
464 }
465
466 public HomotypicalSynonymGroupE4 getHomotypicalGroupContainer(HomotypicalGroup homotypicalGroup) {
467 for (HomotypicalSynonymGroupE4 group : getHeterotypicSynonymGroups()) {
468 if (group.getGroup().equals(homotypicalGroup)) {
469 return group;
470 }
471 }
472
473 return null;
474 }
475
476 /**
477 * <p>
478 * getDirtyNames
479 * </p>
480 *
481 * @return a Set containing all composites that have been edited
482 */
483 public Set<AbstractGroupedContainerE4> getDirtyNames() {
484 Set<AbstractGroupedContainerE4> dirtyNames = new HashSet<>();
485
486 for (AbstractGroupedContainerE4 composite : getGroupedContainers()) {
487 if (composite.isDirty()) {
488 dirtyNames.add(composite);
489 }
490 }
491
492 return dirtyNames;
493 }
494
495 public List<AbstractGroupedContainerE4> getGroupedContainers() {
496 List<AbstractGroupedContainerE4> groupedComposites = new ArrayList<>();
497
498 for (AbstractGroupE4 group : getAllGroups()) {
499 if (group != null) {
500 groupedComposites.addAll(group.getGroupedContainers());
501 }
502 }
503
504 return groupedComposites;
505 }
506
507 public List<AbstractGroupE4> getAllGroups() {
508 List<AbstractGroupE4> allGroups = new ArrayList<>();
509
510 allGroups.add(getAcceptedGroup());
511
512 heterotypicSynonymGroups = getHeterotypicSynonymGroups();
513
514 if (heterotypicSynonymGroups != null) {
515 allGroups.addAll(heterotypicSynonymGroups);
516 }
517
518 if (misappliedGroup != null) {
519 allGroups.add(misappliedGroup);
520 }
521
522 return allGroups;
523 }
524
525 @Override
526 public IEclipseContext getContext() {
527 return context;
528 }
529
530 @Override
531 public boolean isDirty() {
532 return dirty.isDirty();
533 }
534
535 @PreDestroy
536 public void dispose() {
537 if (conversation != null) {
538 conversation.unregisterForDataStoreChanges(this);
539 conversation.close();
540 }
541 if (input != null) {
542 input.dispose();
543 }
544 dirty.setDirty(false);
545 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
546 }
547
548 /** {@inheritDoc} */
549 @Override
550 public void selectionChanged(IWorkbenchPart part, ISelection selection) {
551 System.err.println("Bla");
552 }
553
554 public AbstractGroupedContainerE4 getSelectedContainer() {
555 return (selection != null) ? getContainer(selection) : getAcceptedNameContainer();
556 }
557
558 @Override
559 public void dragEntered() {
560 // TODO change this
561 getControl().setBackground(AbstractUtility.getColor(Resources.COLOR_DRAG_ENTER));
562 }
563
564 @Override
565 public void dragLeft() {
566 getControl().setBackground(AbstractUtility.getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
567 }
568
569 public void setMisapplicationsGroup(MisappliedGroupE4 misappliedGroup) {
570 this.misappliedGroup = misappliedGroup;
571 }
572
573 public FormToolkit getToolkit() {
574 return managedForm.getToolkit();
575 }
576
577 public List<HomotypicalSynonymGroupE4> getHeterotypicSynonymGroups() {
578 return heterotypicSynonymGroups;
579 }
580
581 public void addHeterotypicSynonymGroup(HomotypicalSynonymGroupE4 group) {
582 heterotypicSynonymGroups.add(group);
583 }
584
585 public AcceptedGroupE4 getAcceptedGroup() {
586 return acceptedGroup;
587 }
588
589 public void setAcceptedGroup(AcceptedGroupE4 acceptedGroup) {
590 this.acceptedGroup = acceptedGroup;
591 }
592
593 public MisappliedGroupE4 getMisappliedGroup() {
594 return misappliedGroup;
595 }
596
597 public boolean isActive() {
598 return this.equals(AbstractUtility.getActivePart());
599 }
600
601 @Override
602 public boolean onComplete() {
603 getContainer(objectAffectedByLastOperation).setSelected();
604 return true;
605 }
606
607 /** {@inheritDoc} */
608 @Override
609 public void partChanged(Integer eventType, IWorkbenchPartReference partRef) {
610 if (!partRef.getPart(false).equals(this)) {
611 // getSelectedObject().colorSelected(AbstractGroupedContainer.SELECTED_NO_FOCUS);
612 }
613 }
614
615 public void removeGroup(AbstractGroupE4 group) {
616 if (group != null) {
617 group.dispose();
618
619 // if (heterotypicSynonymGroups != null) {
620 heterotypicSynonymGroups.remove(group);
621 // }
622 }
623 }
624
625 public AbstractGroupedContainerE4 getContainer(TaxonBase taxonBase) {
626 @SuppressWarnings("rawtypes")
627 List<AbstractGroupedContainerE4> groupedContainers = getGroupedContainers();
628 for (AbstractGroupedContainerE4 container : groupedContainers) {
629 if (container.getData().equals(taxonBase) && container.getNameViewer().getTextWidget() != null) {
630 return container;
631 }
632 }
633 return getAcceptedNameContainer();
634 }
635
636 public void setOnError() {
637 Color disabledColor = AbstractUtility.getColor(Resources.COLOR_EDITOR_ERROR);
638 setEnabled(false, disabledColor);
639 }
640
641 public void setDisabled() {
642 Color disabledColor = AbstractUtility.getColor(Resources.COLOR_TEXT_DISABLED_BACKGROUND);
643 setEnabled(false, disabledColor);
644 }
645
646 protected void setEnabled(boolean enabled, Color background) {
647
648 for (AbstractGroupedContainerE4 groupedContainer : getGroupedContainers()) {
649 groupedContainer.setEnabled(enabled);
650 }
651
652 // send an empty selection to the current provider - TODO only on error
653 // ???
654 if (!enabled) {
655 getManagedForm().setInput(null);
656
657 for (AbstractGroupedContainerE4 groupedContainer : getGroupedContainers()) {
658 groupedContainer.setBackground(background);
659 }
660 }
661 getControl().setBackground(background);
662 }
663
664 @Override
665 public void changed(Object element) {
666 // setDirty(true);
667 // if the attribute is null then do not set the dirty flag -> hotfix for
668 // the problem that for tasks done in service methods the changes are
669 // saved automatically
670 if (element != null) {
671 dirty.setDirty(true);
672 // refresh part title
673 // TODO: refresh taxon node in taxon navigator
674 setPartName();
675 }
676
677 if (element instanceof TaxonBase) {
678 AbstractGroupedContainerE4 container = getContainer((TaxonBase) element);
679 if (container != null) {
680 container.refresh();
681 }
682 }
683
684 if (element instanceof TaxonRelationship) {
685 AbstractGroupedContainerE4 container = getContainer(((TaxonRelationship) element).getFromTaxon());
686 if (container != null) {
687 container.refresh();
688 }
689 }
690 }
691
692 public void setPartName() {
693 // FIXME: temporary fix for #6437 to avoid outdated title caches
694 thisPart.setLabel(this.taxon.getName().generateFullTitle());
695 // thisPart.setLabel(this.taxon.getName().getFullTitleCache());
696 }
697
698 @Override
699 public void forceDirty() {
700 setDirty();
701 }
702
703 public IUndoContext getUndoContext() {
704 return undoContext;
705 }
706
707 @Override
708 public Composite getControl() {
709 return managedForm.getForm().getBody();
710 }
711
712 public EMenuService getMenuService() {
713 return menuService;
714 }
715
716 public ESelectionService getSelectionService() {
717 return selService;
718 }
719
720 /**
721 * {@inheritDoc}
722 */
723 @Override
724 public boolean canAttachMedia() {
725 return true;
726 }
727
728 public TaxonEditorInputE4 getEditorInput() {
729 return input;
730 }
731
732 /**
733 * {@inheritDoc}
734 */
735 @Override
736 public TaxonNameEditorE4 getEditor() {
737 return this;
738 }
739
740 @Inject
741 @Optional
742 private void updateView(@UIEventTopic(WorkbenchEventConstants.REFRESH_NAME_EDITOR) CdmBase cdmbase) {
743
744 if ((EventUtility.getTaxonEditor() != null && EventUtility.getTaxonEditor().equals(this))
745 || (this.taxon != null && (this.taxon.equals(cdmbase)
746 || (this.taxon.getName() != null && this.taxon.getName().equals(cdmbase))))) {
747 this.redraw(false, true, true, true);
748 this.setDirty();
749 if (cdmbase instanceof TaxonBase) {
750 this.selection = (TaxonBase) cdmbase;
751 }
752
753 }
754 }
755
756 @Inject
757 @Optional
758 private void updateView(@UIEventTopic(WorkbenchEventConstants.REFRESH_NAME_EDITOR) List<CdmBase> cdmBases) {
759
760 for (CdmBase cdmBase: cdmBases){
761 if (cdmBase instanceof Taxon || cdmBase instanceof TaxonName){
762 if ((EventUtility.getTaxonEditor() != null && EventUtility.getTaxonEditor().equals(this))
763 || (this.taxon != null && (this.taxon.equals(cdmBase)
764 || (this.taxon.getName() != null && this.taxon.getName().equals(cdmBase))))) {
765 EPartService partService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService.class);
766 EModelService modelService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EModelService.class);
767 EditorUtil.openTaxonBaseE4(this.getTaxon().getUuid(), modelService, partService, application);
768
769 }
770 }
771 }
772 }
773
774 @Inject
775 @Optional
776 private void updateView(@UIEventTopic(WorkbenchEventConstants.REFRESH_NAME_EDITOR) UUID cdmbaseUuid) {
777
778 if (this.taxon.getUuid().equals(cdmbaseUuid)) {
779 TaxonEditorInputE4 input = TaxonEditorInputE4.NewInstanceFromTaxonBase(cdmbaseUuid);
780 init(input);
781 }
782 }
783
784 @Inject
785 @Optional
786 private void updatefromDelete(@UIEventTopic(WorkbenchEventConstants.DELETE_DERIVATIVE) DeleteResult result) {
787 if (taxon.getName() == null) {
788 return;
789 }
790 Set<DerivedUnit> typeDesignationSpecimens = new HashSet<>();
791 this.taxon.getName().getSpecimenTypeDesignations()
792 .forEach(designation -> typeDesignationSpecimens.add(designation.getTypeSpecimen()));
793 // check if any deleted object was a type specimen
794 if (result.getUpdatedObjects().stream()
795 // filter only DerivedUnits
796 .filter(cdmBase -> cdmBase.isInstanceOf(DerivedUnit.class))
797 // deproxy from CdmBase to DerivedUnit
798 .map(unit -> HibernateProxyHelper.deproxy(unit, DerivedUnit.class))
799 // check for match in type designations
800 .anyMatch(unit -> typeDesignationSpecimens.contains(unit))) {
801 EditorUtil.updateEditor(this.input.getTaxonNode(), this);
802
803 }
804
805 }
806
807 /**
808 * {@inheritDoc}
809 */
810 @Override
811 public void update() {
812 EPartService partService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EPartService.class);
813 EModelService modelService = TaxeditorEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getService(EModelService.class);
814 EditorUtil.openTaxonBaseE4(this.getTaxon().getUuid(), modelService, partService, application);
815
816 }
817
818 }