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