Project

General

Profile

Download (21.7 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

    
10
package eu.etaxonomy.taxeditor.bulkeditor.e4;
11

    
12
import java.io.Serializable;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17

    
18
import javax.annotation.PostConstruct;
19
import javax.annotation.PreDestroy;
20
import javax.inject.Inject;
21

    
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.NullProgressMonitor;
24
import org.eclipse.e4.core.contexts.IEclipseContext;
25
import org.eclipse.e4.core.di.annotations.Optional;
26
import org.eclipse.e4.core.services.events.IEventBroker;
27
import org.eclipse.e4.ui.di.Focus;
28
import org.eclipse.e4.ui.di.Persist;
29
import org.eclipse.e4.ui.di.UIEventTopic;
30
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
31
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
32
import org.eclipse.e4.ui.services.EMenuService;
33
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
34
import org.eclipse.jface.dialogs.MessageDialog;
35
import org.eclipse.jface.layout.GridDataFactory;
36
import org.eclipse.jface.viewers.ISelectionChangedListener;
37
import org.eclipse.jface.viewers.IStructuredSelection;
38
import org.eclipse.jface.viewers.StructuredSelection;
39
import org.eclipse.nebula.widgets.nattable.NatTable;
40
import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommand;
41
import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommandHandler;
42
import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
43
import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;
44
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
45
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
46
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
47
import org.eclipse.nebula.widgets.nattable.config.IEditableRule;
48
import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
49
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
50
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
51
import org.eclipse.nebula.widgets.nattable.edit.action.MouseEditAction;
52
import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditConfiguration;
53
import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
54
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
55
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsSortModel;
56
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
57
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
58
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
59
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
60
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
61
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
62
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
63
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
64
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayer;
65
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
66
import org.eclipse.nebula.widgets.nattable.layer.stack.DefaultBodyLayerStack;
67
import org.eclipse.nebula.widgets.nattable.selection.RowSelectionModel;
68
import org.eclipse.nebula.widgets.nattable.selection.RowSelectionProvider;
69
import org.eclipse.nebula.widgets.nattable.sort.SortHeaderLayer;
70
import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
71
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
72
import org.eclipse.nebula.widgets.nattable.style.theme.ModernNatTableThemeConfiguration;
73
import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
74
import org.eclipse.nebula.widgets.nattable.ui.matcher.CellEditorMouseEventMatcher;
75
import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
76
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuAction;
77
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
78
import org.eclipse.swt.SWT;
79
import org.eclipse.swt.dnd.Clipboard;
80
import org.eclipse.swt.dnd.TextTransfer;
81
import org.eclipse.swt.dnd.Transfer;
82
import org.eclipse.swt.layout.GridData;
83
import org.eclipse.swt.layout.GridLayout;
84
import org.eclipse.swt.widgets.Composite;
85
import org.eclipse.swt.widgets.Display;
86
import org.eclipse.swt.widgets.Menu;
87

    
88
import ca.odell.glazedlists.SortedList;
89
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
90
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
91
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
92
import eu.etaxonomy.cdm.model.common.CdmBase;
93
import eu.etaxonomy.cdm.model.description.SpecimenDescription;
94
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
95
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
96
import eu.etaxonomy.cdm.model.taxon.Taxon;
97
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
98
import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
99
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
100
import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
101
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
102
import eu.etaxonomy.taxeditor.l10n.Messages;
103
import eu.etaxonomy.taxeditor.model.IDerivedUnitFacadePart;
104
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
105
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
106
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
107
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
108
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
109
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
110
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
111

    
112
/**
113
 *
114
 * @author pplitzner
115
 * @since Sep 8, 2017
116
 *
117
 */
118
public class BulkEditorE4 implements IPartContentHasDetails, IConversationEnabled, IPostOperationEnabled,
119
        IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData,
120
        IPartContentHasSupplementalData, IPartContentHasMedia, IE4SavablePart, ITaxonEditor {
121

    
122
    public static final String TYPE_PROPERTY = Messages.BulkEditorE4_TYPE;
123

    
124
    @Inject
125
	private MDirtyable dirty;
126

    
127
    private AbstractBulkEditorInput input;
128

    
129
    private Composite topComposite;
130

    
131
    private ConversationHolder conversation;
132

    
133
    @Inject
134
    private ESelectionService selService;
135

    
136
    @Inject
137
    private IEventBroker eventBroker;
138

    
139
    private ISelectionChangedListener selectionChangedListener;
140

    
141
    @Inject
142
    IEclipseContext context;
143

    
144
    @Inject
145
    private MPart thisPart;
146

    
147
    private BulkEditorQuery lastQuery = null;
148

    
149
    private Composite bottomComposite;
150

    
151
    @Inject
152
    private EMenuService menuService;
153

    
154
    private NatTable natTable;
155

    
156
    private DefaultBodyLayerStack bodyLayer;
157

    
158
    private ListDataProvider<CdmBase> bodyDataProvider;
159

    
160
    @Inject
161
    public BulkEditorE4() {
162
	}
163

    
164
	@SuppressWarnings("unused")
165
    public void init(AbstractBulkEditorInput<?> input){
166
	    this.input = input;
167
	    this.conversation = input.getConversation();
168

    
169
	    new BulkEditorSearchE4(this, topComposite, SWT.NONE);
170
	    //layout needed because the search bar is added after @PostConstuct method
171
	    topComposite.getParent().layout();
172

    
173
	    thisPart.setLabel(input.getEditorName());
174

    
175
        if(input.getEntityUuid()!=null){
176
            performSearch(new BulkEditorQuery(input.getEntityUuid().toString()));
177
        }
178

    
179
        createTable();
180

    
181
        configureTable();
182

    
183
        styleTable();
184

    
185
        GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
186

    
187
        //propagate selection
188
        selectionChangedListener = (event -> selService.setSelection(getSelection()));
189
        RowSelectionProvider<CdmBase> selectionProvider = new RowSelectionProvider<CdmBase>(bodyLayer.getSelectionLayer(), bodyDataProvider, true);
190
        selectionProvider.addSelectionChangedListener(selectionChangedListener);
191

    
192
        bottomComposite.layout();
193
	}
194

    
195
	private void createTable(){
196
	    ConfigRegistry configRegistry = new ConfigRegistry();
197
	    //property map
198
        Map<String, String> propertyToLabels = new HashMap<>();
199
        propertyToLabels.put(getEditorInput().getName(), getEditorInput().getName());
200
        propertyToLabels.put(TYPE_PROPERTY, TYPE_PROPERTY);
201
        String[] propertyNames = new String[] { input.getName(), TYPE_PROPERTY };
202
        //sorted list
203
        SortedList<CdmBase> sortedList = new SortedList<>(input.getModel(), input.getTitleComparator());
204
        //data provider
205
        BulkEditorPropertyAccessor columnPropertyAccessor = new BulkEditorPropertyAccessor(input);
206
        bodyDataProvider = new ListDataProvider<CdmBase>(sortedList,
207
                columnPropertyAccessor);
208
        DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(
209
                propertyNames, propertyToLabels);
210
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(
211
                bodyDataProvider);
212
        //body
213
        DataLayer dataLayer = new DataLayer(bodyDataProvider);
214
        dataLayer.registerCommandHandler(new VisualRefreshCommandHandler());
215
        GlazedListsEventLayer<CdmBase> eventLayer = new GlazedListsEventLayer<>(dataLayer, input.getModel());
216
        bodyLayer = new DefaultBodyLayerStack(eventLayer);
217
        //column
218
        DataLayer columnHeaderDataLayer = new DataLayer(colHeaderDataProvider);
219
        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(
220
                columnHeaderDataLayer,
221
                bodyLayer, bodyLayer.getSelectionLayer());
222
        // add the SortHeaderLayer to the column header layer stack
223
        // as we use GlazedLists, we use the GlazedListsSortModel which
224
        // delegates the sorting to the SortedList
225
        final SortHeaderLayer<SpecimenDescription> sortHeaderLayer = new SortHeaderLayer<>(
226
                columnHeaderLayer,
227
                new GlazedListsSortModel<>(
228
                        sortedList,
229
                        columnPropertyAccessor,
230
                        configRegistry,
231
                        columnHeaderDataLayer));
232
        //row
233
        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(new DataLayer(rowHeaderDataProvider, 50, 50),
234
//        DataLayer rowHeaderDataLayer = new DataLayer(rowHeaderDataProvider);
235
//        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer,
236
                bodyLayer, bodyLayer.getSelectionLayer());
237
//        rowHeaderDataLayer.setDefaultRowHeight(20);
238
//        rowHeaderDataLayer.setColumnWidthByPosition(0, 50);
239
//        rowHeaderDataLayer.setColumnWidthByPosition(1, 200);
240
//        rowHeaderDataLayer.setColumnWidthByPosition(2, 100);
241

    
242
        //corner
243
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(
244
                colHeaderDataProvider, rowHeaderDataProvider);
245
        CornerLayer cornerLayer = new CornerLayer(new DataLayer(
246
                cornerDataProvider), rowHeaderLayer, sortHeaderLayer);
247
        //grid
248
        GridLayer gridLayer = new GridLayer(bodyLayer, sortHeaderLayer,
249
                rowHeaderLayer, cornerLayer, false);//set autoconfigure to false to get rid of the single click editing
250
        dataLayer.setColumnPercentageSizing(true);
251
        natTable = new NatTable(bottomComposite, gridLayer, false);
252
        natTable.setConfigRegistry(configRegistry);
253

    
254
        //full row selection
255
        bodyLayer.getSelectionLayer().setSelectionModel(new RowSelectionModel<CdmBase>(bodyLayer.getSelectionLayer(), bodyDataProvider, new IRowIdAccessor<CdmBase>() {
256
            @Override
257
            public Serializable getRowId(CdmBase rowObject) {
258
                return input.getModel().indexOf(rowObject);
259
            }
260
        }));
261
	}
262

    
263
	private void configureTable(){
264

    
265
	    //this configuration enables cell to be editable in general
266
	    //necessary because we disabled this beforehand by setting autoconfigure=false
267
	    //in the GridLayer
268
	    ((AbstractLayer) natTable.getLayer()).addConfiguration(new DefaultEditConfiguration());
269

    
270
        natTable.addConfiguration(new AbstractUiBindingConfiguration() {
271
            @Override
272
            public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
273
                uiBindingRegistry.registerFirstDoubleClickBinding(new CellEditorMouseEventMatcher(GridRegion.BODY),
274
                        new MouseEditAction());
275
            }
276
        });
277

    
278
        //+++CONTEXT MENU+++
279
        menuService.registerContextMenu(natTable, "eu.etaxonomy.taxeditor.bulkeditor.popupmenu.bulkeditor"); //$NON-NLS-1$
280
        // get the menu registered by EMenuService
281
        final Menu e4Menu = natTable.getMenu();
282
        // remove the menu reference from NatTable instance
283
        natTable.setMenu(null);
284
        natTable.addConfiguration(
285
                new AbstractUiBindingConfiguration() {
286
            @Override
287
            public void configureUiBindings(
288
                    UiBindingRegistry uiBindingRegistry) {
289
                // add e4 menu to NatTable
290
                new PopupMenuBuilder(natTable, e4Menu)
291
                    .build();
292

    
293
                // register the UI binding for header, corner and body region
294
                uiBindingRegistry.registerMouseDownBinding(
295
                        new MouseEventMatcher(
296
                                SWT.NONE,
297
                                null,
298
                                MouseEventMatcher.RIGHT_BUTTON),
299
                        new PopupMenuAction(e4Menu));
300
            }
301
        });
302

    
303
        //make cells editable to allow selecting the text
304
        natTable.addConfiguration(new AbstractRegistryConfiguration() {
305
            @Override
306
            public void configureRegistry(IConfigRegistry configRegistry) {
307
              //make cell editable
308
                configRegistry.registerConfigAttribute(
309
                        EditConfigAttributes.CELL_EDITABLE_RULE,
310
                        IEditableRule.ALWAYS_EDITABLE,
311
                        DisplayMode.EDIT);
312
                //register editor
313
                TextCellEditor editor = new TextCellEditor();
314
                editor.setEditable(false);
315
                configRegistry.registerConfigAttribute(
316
                        EditConfigAttributes.CELL_EDITOR,
317
                        editor,
318
                        DisplayMode.NORMAL);
319
            }
320
        });
321

    
322
        //enable sorting
323
        natTable.addConfiguration(new SingleClickSortConfiguration());
324
        //add default configuration because autoconfigure is set to false in constructor
325
        natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
326
        natTable.configure();
327
	}
328

    
329
	private void styleTable(){
330
	    natTable.setTheme(new ModernNatTableThemeConfiguration());
331
	}
332

    
333
	/** {@inheritDoc} */
334
	@PostConstruct
335
	public void createPartControl(Composite parent) {
336
		parent.setLayout(new GridLayout());
337

    
338
		topComposite = new Composite(parent, SWT.NONE);
339
		topComposite.setLayout(new GridLayout());
340

    
341
		GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
342
		topComposite.setLayoutData(gridData);
343

    
344
		bottomComposite = new Composite(parent, SWT.NONE);
345
		bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
346
		bottomComposite.setLayout(new GridLayout());
347
	}
348

    
349
	@Override
350
	@Persist
351
	public void save(IProgressMonitor monitor) {
352
	    save(monitor, true);
353
	}
354

    
355
	@Focus
356
	public void setFocus() {
357
        //make sure to bind again if maybe in another view the conversation was unbound
358
        if(conversation!=null && !conversation.isBound()){
359
            conversation.bind();
360
        }
361
        if(input!=null && input.getCdmEntitySession()!= null) {
362
            input.getCdmEntitySession().bind();
363
        }
364

    
365
	    //make sure to bind again if maybe in another view the conversation was unbound
366
	    eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
367
	}
368

    
369
	@PreDestroy
370
	public void dispose() {
371
	    if(conversation!=null){
372
	        conversation.unregisterForDataStoreChanges(this);
373
	        conversation.close();
374
	    }
375
	    if(input!=null){
376
	        input.dispose();
377
	    }
378
	    dirty.setDirty(false);
379
	}
380

    
381
	public void save(IProgressMonitor monitor, boolean resetMerge) {
382
	    if (!input.getCdmEntitySession().isActive()){
383
            input.getCdmEntitySession().bind();
384
        }
385
	    input.saveModel(resetMerge);
386

    
387
	    IStructuredSelection selection = getSelection();
388

    
389
        dirty.setDirty(false);
390
        input.dispose();
391
        input.bind();
392
        conversation.commit(true);
393

    
394
        if (lastQuery != null){
395
            performSearch(lastQuery, selection);
396
        }
397
	}
398

    
399
	public void performSearch(BulkEditorQuery query) {
400
	    performSearch(query, null);
401
	}
402

    
403
	/** {@inheritDoc}
404
	 * @param selection */
405
    public void performSearch(BulkEditorQuery query, IStructuredSelection selection) {
406
        if (query != null) {
407
            // TODO check if dirty, prompt save
408
            if (isDirty()) {
409
                String[] labels = {Messages.BulkEditorE4_SAVE_AND_SEARCH, Messages.BulkEditorE4_DONT_SAVE,Messages.BulkEditorE4_CANCEL};
410
                MessageDialog dialog =new MessageDialog(topComposite.getShell(), Messages.BulkEditorE4_SAVE_CHANGES_TITLE, null, Messages.BulkEditorE4_SAVE_CHANGES_MESSAGE, MessageDialog.QUESTION,labels, 0);
411
                int result = dialog.open();
412
                if (result == 0) {
413
                    save(new NullProgressMonitor());
414
                } else if (result == 2){
415
                    return;
416
                }
417
            }
418
            dirty.setDirty(false);
419
            input.performSearch(query, selection);
420
            lastQuery = query;
421
        }
422
    }
423

    
424
    @Optional
425
    @Inject
426
    private void updateAfterSearch(@UIEventTopic(WorkbenchEventConstants.BULK_EDITOR_SEARCH_FINISHED)IStructuredSelection selection){
427

    
428

    
429
        if(selection!=null){
430
            setSelection(selection);
431
        }
432
//        //auto resize columns
433
//        InitializeAutoResizeColumnsCommand command = new InitializeAutoResizeColumnsCommand(
434
//                natTable, 2, natTable.getConfigRegistry(), new GCFactory(
435
//                        natTable));
436
//        natTable.doCommand(command);
437
//        command = new InitializeAutoResizeColumnsCommand(
438
//                natTable, 1, natTable.getConfigRegistry(), new GCFactory(
439
//                        natTable));
440
//        natTable.doCommand(command);
441
    }
442

    
443
    public void refresh(){
444
        natTable.doCommand(new VisualRefreshCommand());
445
    }
446

    
447
    public IStructuredSelection getSelection(){
448
        List<CdmBase> selection = new ArrayList<>();
449
        int[] fullySelectedRowPositions = bodyLayer.getSelectionLayer().getFullySelectedRowPositions();
450
        for (int i : fullySelectedRowPositions) {
451
            Object rowObject = bodyDataProvider.getRowObject(i);
452
            if(rowObject instanceof CdmBase){
453
                selection.add((CdmBase) rowObject);
454
            }
455
        }
456
        return new StructuredSelection(selection);
457
    }
458

    
459
    public void setSelection(IStructuredSelection selection){
460
        Object[] objects = selection.toArray();
461
        for (Object object : objects) {
462

    
463
            if(object instanceof CdmBase &&  input.getModel().contains(object)){
464
                bodyLayer.getSelectionLayer().selectRow(0, bodyDataProvider.indexOfRowObject((CdmBase) object), false, false);
465
            }
466
        }
467
    }
468

    
469
    public void setDirty(){
470
        dirty.setDirty(true);
471
    }
472

    
473
    public boolean isDirty() {
474
        return dirty.isDirty();
475
    }
476

    
477
    public AbstractBulkEditorInput getEditorInput() {
478
        return input;
479
    }
480

    
481
    public void copyDataToClipboard() {
482
        String textData = "";
483
        IStructuredSelection selection = getSelection();
484
        Object[] objects = selection.toArray();
485
        for (Object object : objects) {
486
            if(object instanceof CdmBase){
487
                textData += getEditorInput().getText((CdmBase)object);
488
            }
489
        }
490
        final TextTransfer textTransfer = TextTransfer.getInstance();
491
        final Clipboard clipboard = new Clipboard(Display.getDefault());
492
        try {
493
            clipboard.setContents(new Object[] { textData.toString() },
494
                    new Transfer[] { textTransfer });
495
        } finally {
496
            clipboard.dispose();
497
        }
498
    }
499

    
500
    @Override
501
    public void update(CdmDataChangeMap arg0) {
502
    }
503

    
504
    @Override
505
    public boolean canAttachMedia() {
506
        return true;
507
    }
508

    
509
    @Override
510
    public void changed(Object element) {
511
        if(element instanceof DerivedUnitFacade){
512
            DerivedUnit derivedUnit = ((DerivedUnitFacade) element).innerDerivedUnit();
513
            if(derivedUnit!=null){
514
                getEditorInput().addSaveCandidate(derivedUnit);
515
            }
516
            FieldUnit fieldUnit = ((DerivedUnitFacade) element).innerFieldUnit();
517
            if(fieldUnit!=null){
518
                getEditorInput().addSaveCandidate(fieldUnit);
519
            }
520
        }
521
        else if (element instanceof CdmBase) {
522
            getEditorInput().addSaveCandidate((CdmBase)element);
523
            input.replaceInModel((CdmBase) element);
524
        }
525
        dirty.setDirty(true);
526
        setSelection(new StructuredSelection(element));
527
    }
528

    
529
    @Override
530
    public void forceDirty() {
531
        dirty.setDirty(true);
532
    }
533

    
534
    @Override
535
    public boolean postOperation(CdmBase objectAffectedByOperation) {
536
        return false;
537
    }
538

    
539
    @Override
540
    public boolean onComplete() {
541
        return false;
542
    }
543

    
544
    @Override
545
    public ConversationHolder getConversationHolder() {
546
        return conversation;
547
    }
548

    
549
    public BulkEditorQuery getLastQuery() {
550
       return lastQuery;
551
    }
552

    
553
    public void setLastQuery(BulkEditorQuery lastQuery) {
554
       this.lastQuery = lastQuery;
555

    
556
    }
557

    
558
    @Override
559
    public Taxon getTaxon() {
560
        IStructuredSelection selection = getSelection();
561
        if(selection.size()==1) {
562
            Object object = selection.iterator().next();
563
            if(object instanceof Taxon){
564
                return (Taxon) object;
565
            }
566
        }
567
        return null;
568
    }
569

    
570
}
(1-1/5)