Project

General

Profile

Download (17 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.editor;
11

    
12
import java.util.ArrayList;
13
import java.util.List;
14
import java.util.UUID;
15

    
16
import org.eclipse.core.commands.operations.IUndoContext;
17
import org.eclipse.core.commands.operations.UndoContext;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.jface.dialogs.MessageDialog;
20
import org.eclipse.ui.IEditorInput;
21
import org.eclipse.ui.IEditorPart;
22
import org.eclipse.ui.IEditorSite;
23
import org.eclipse.ui.PartInitException;
24
import org.eclipse.ui.forms.editor.FormEditor;
25

    
26
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
27
import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
28
import eu.etaxonomy.cdm.api.application.CdmChangeEvent.Action;
29
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
30
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
31
import eu.etaxonomy.cdm.model.common.CdmBase;
32
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
33
import eu.etaxonomy.cdm.model.taxon.Taxon;
34
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
35
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
36
import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
37
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
38
import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
39
import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
40
import eu.etaxonomy.taxeditor.model.AbstractUtility;
41
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
42
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
43
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
44
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
45
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
46
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
47
import eu.etaxonomy.taxeditor.model.MessagingUtils;
48
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
49

    
50
/**
51
 *
52
 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs
53
 * for "Descriptions", "Concepts", "Geography", etc.
54
 *
55
 * @author p.ciardelli
56
 * @author n.hoffmann
57
 * @created 15.05.2008
58
 * @version 1.0
59
 */
60
public class MultiPageTaxonEditor extends FormEditor implements
61
IPartContentHasFactualData, IConversationEnabled, IPostOperationEnabled,
62
IDirtyMarkable, IPartContentHasDetails, ISecuredEditor, IPartContentHasMedia {
63

    
64
    /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
65
    public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon"; //$NON-NLS-1$
66

    
67
    private boolean dirty;
68

    
69
    private ConversationHolder conversation;
70
    private IDataChangeBehavior dataChangeBehavior;
71
    private IUndoContext undoContext;
72

    
73
    private TaxonEditorInput input;
74

    
75
    /**
76
     * <p>
77
     * Constructor for MultiPageTaxonEditor.
78
     * </p>
79
     */
80
    public MultiPageTaxonEditor() {
81
        super();
82
        undoContext = new UndoContext();
83

    
84
    }
85

    
86
    /** {@inheritDoc} */
87
    @Override
88
    public void dispose() {
89
        input.dispose();
90
        conversation.unregisterForDataStoreChanges(this);
91
        conversation.close();
92
        super.dispose();
93
    }
94

    
95
    /*
96
     * (non-Javadoc)
97
     *
98
     * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
99
     */
100
    /** {@inheritDoc} */
101
    @Override
102
    protected void addPages() {
103
        input = (TaxonEditorInput) getEditorInput();
104
        conversation = input.getConversationHolder();
105
        conversation.registerForDataStoreChanges(this);
106

    
107
        try {
108
            addPage(Page.NAME.getIndex(), new TaxonNameEditor(this),
109
                    getEditorInput());
110
            // setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
111

    
112
            // TODO lazy create
113
            // addPage(Page.DESCRIPTIVE.getIndex(), new
114
            // TaxonDescriptionTreeEditor(this), getEditorInput());
115
            // setPageText(Page.DESCRIPTIVE.getIndex(),
116
            // Page.DESCRIPTIVE.getTitle());
117

    
118
            // EditorUtil.showPropertySheet();
119

    
120
        } catch (PartInitException e) {
121
            MessagingUtils.error(getClass(), e);
122
        }
123
    }
124

    
125
    /** {@inheritDoc} */
126
    @Override
127
    public void doSave(IProgressMonitor monitor) {
128
        monitor.beginTask(Messages.MultiPageTaxonEditor_SAVING_EDITOR, 4);
129
        try {
130
            if (!conversation.isBound()) {
131
                conversation.bind();
132
            }
133
            monitor.worked(1);
134

    
135
            for (IEditorPart editorPage : getPages()) {
136
                if (editorPage instanceof TaxonNameEditor) {
137
                    if (((TaxonNameEditor) editorPage).checkForEmptyNames()) {
138
                        MessageDialog.openWarning(AbstractUtility.getShell(), Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED,
139
                                Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE);
140
                        return;
141
                    }
142
                }
143

    
144
                editorPage.doSave(monitor);
145
                monitor.worked(1);
146
            }
147

    
148
            // commit the conversation and start a new transaction immediately
149

    
150
            input.merge();
151

    
152
            conversation.commit(true);
153
            CdmApplicationState.getCurrentDataChangeService()
154
            .fireChangeEvent(new CdmChangeEvent(Action.Update, input.getTaxonNode() , MultiPageTaxonEditor.class), true);
155
            monitor.worked(1);
156

    
157
            this.setDirty(false);
158
            monitor.worked(1);
159
        } catch (Exception e) {
160
            setFocus();
161
            MessagingUtils.operationDialog(this, e, TaxeditorEditorPlugin.PLUGIN_ID,Messages.MultiPageTaxonEditor_SAVING_TAXON, Messages.MultiPageTaxonEditor_SAVING_TAXON_MESSAGE);
162
            disableEditor(true);
163
        } finally {
164
            monitor.done();
165
        }
166
    }
167

    
168
    private void disableEditor(boolean isOnError) {
169
        for (IMultiPageTaxonEditorPage editorPage : getPages()) {
170
            if(isOnError){
171
                editorPage.setOnError();
172
            }else {
173
                editorPage.setDisabled();
174
            }
175
        }
176

    
177
        conversation.unregisterForDataStoreChanges(this);
178
        conversation.close();
179
        setDirty(false);
180
    }
181

    
182
    private void setDirty(boolean dirty) {
183
        this.dirty = dirty;
184
        firePropertyChange(PROP_DIRTY);
185
    }
186

    
187
    /*
188
     * (non-Javadoc)
189
     *
190
     * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
191
     */
192
    /**
193
     * <p>
194
     * isDirty
195
     * </p>
196
     *
197
     * @return a boolean.
198
     */
199
    @Override
200
    public boolean isDirty() {
201
        return dirty;
202
    }
203

    
204
    /*
205
     * (non-Javadoc)
206
     *
207
     * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
208
     */
209
    /** {@inheritDoc} */
210
    @Override
211
    public void editorDirtyStateChanged() {
212
        dirty = true;
213
        super.editorDirtyStateChanged();
214
    }
215

    
216
    /**
217
     * {@inheritDoc}
218
     *
219
     * Checks whether nested editors are calling
220
     * <code>firePropertyChange(PROP_DIRTY)</code> to signal an edit has taken
221
     * place before passing property change along to
222
     * <code>super.handlePropertyChange(int propertyId)</code>.
223
     */
224
    /*
225
     * (non-Javadoc)
226
     *
227
     * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
228
     */
229
    @Override
230
    protected void handlePropertyChange(int propertyId) {
231
        if (propertyId == PROP_DIRTY) {
232
            setDirty(true);
233
        }
234
        super.handlePropertyChange(propertyId);
235
    }
236

    
237
    /** {@inheritDoc} */
238
    @Override
239
    public void doSaveAs() {
240
    }
241

    
242
    /** {@inheritDoc} */
243
    @Override
244
    public boolean isSaveAsAllowed() {
245
        return false;
246
    }
247

    
248
    /** {@inheritDoc} */
249
    @Override
250
    public void init(IEditorSite site, IEditorInput input)
251
            throws PartInitException {
252

    
253
        if (!(input instanceof TaxonEditorInput)) {
254
            throw new PartInitException(
255
                    Messages.MultiPageTaxonEditor_INVALID_INPUT);
256
        }
257

    
258
        this.input = (TaxonEditorInput) input;
259

    
260

    
261
        // try {
262
        // // Listen for name changes,
263
        // // change tab for this taxon editor accordingly
264
        // getTaxon().addPropertyChangeListener("name",
265
        // new PropertyChangeListener() {
266
        // public void propertyChange(PropertyChangeEvent e) {
267
        // setPartName();
268
        // }
269
        // });
270
        // } catch (NullPointerException e) {
271
        // EditorUtil.warn(getClass(),
272
        // "Caught an NPE while initing an editor. This is most " +
273
        // "likely due to the unsuccesful attempt to restore the former " +
274
        // "state of the application. We ignore this because the workbench " +
275
        // "will simply be reset.");
276
        // }
277
        setPartName();
278

    
279
        super.init(site, input);
280
    }
281

    
282
    /**
283
     * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
284
     * text appropriate to the state of the taxon: any taxon that has been saved
285
     * will by necessity have a name to display; a new taxon should display
286
     * "New taxon" in the editor tab.
287
     */
288
    protected void setPartName() {
289

    
290
        String partName = null;
291
        TaxonNameBase<?, ?> name = getTaxon().getName();
292

    
293
        if (name != null) {
294
            partName = name.getTitleCache();
295
        }
296

    
297
        if (partName == null || partName.equals("")) { //$NON-NLS-1$
298
            partName = (Messages.MultiPageTaxonEditor_NEW_TAXON);
299
        }
300

    
301
        setPartName(partName);
302
    }
303

    
304
    /**
305
     * {@inheritDoc}
306
     *
307
     * Editor pages call this in their postOperation to notify the
308
     * MultiPageTaxonEditor of unsaved changes
309
     */
310
    @Override
311
    public void changed(Object element) {
312
        // setDirty(true);
313
        // if the attribute is null then do not set the dirty flag -> hotfix for the problem that for tasks done in service methods the changes are saved automatically
314
        if (element != null){
315
            dirty = true;
316
            super.editorDirtyStateChanged();
317
        }
318

    
319
        if (element instanceof TaxonBase) {
320
            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
321
            AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
322
            if (container != null) {
323
                container.refresh();
324
            }
325
        }
326
        //refresh part title
327
        //TODO: refresh taxon node in taxon navigator
328
        setPartName();
329
    }
330

    
331
    /* (non-Javadoc)
332
     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
333
     */
334
    @Override
335
    public void forceDirty() {
336
        changed(null);
337
    }
338

    
339
    /**
340
     * The accepted taxon that is the input for this editor
341
     *
342
     * @return the accepted taxon
343
     */
344
    public Taxon getTaxon() {
345
        return input.getTaxon();
346
    }
347

    
348
    /*
349
     * (non-Javadoc)
350
     *
351
     * @see
352
     * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
353
     * ()
354
     */
355
    /**
356
     * <p>
357
     * getConversationHolder
358
     * </p>
359
     *
360
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
361
     *         object.
362
     */
363
    @Override
364
    public ConversationHolder getConversationHolder() {
365
        return conversation;
366
    }
367

    
368
    /**
369
     * <p>
370
     * setConversationHolder
371
     * </p>
372
     *
373
     * @param conversation
374
     *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
375
     *            object.
376
     */
377
    public void setConversationHolder(ConversationHolder conversation) {
378
        this.conversation = conversation;
379
    }
380

    
381
    /**
382
     * <p>
383
     * Getter for the field <code>undoContext</code>.
384
     * </p>
385
     *
386
     * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
387
     *         object.
388
     */
389
    public IUndoContext getUndoContext() {
390
        return undoContext;
391
    }
392

    
393
    /**
394
     * <p>
395
     * Setter for the field <code>undoContext</code>.
396
     * </p>
397
     *
398
     * @param undoContext
399
     *            a {@link org.eclipse.core.commands.operations.IUndoContext}
400
     *            object.
401
     */
402
    public void setUndoContext(IUndoContext undoContext) {
403
        this.undoContext = undoContext;
404
    }
405

    
406
    /** {@inheritDoc} */
407
    @Override
408
    public void setFocus() {
409
        // logger.warn("Setting focus to editor");
410
        // bind the conversation
411
        getConversationHolder().bind();
412
        input.bind();
413
        // pass focus to the active editor page
414
        getActiveEditor().setFocus();
415
    }
416

    
417
    /*
418
     * (non-Javadoc)
419
     *
420
     * @see
421
     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
422
     * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
423
     */
424
    /** {@inheritDoc} */
425
    @Override
426
    public void update(CdmDataChangeMap events) {
427
        if (dataChangeBehavior == null) {
428
            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
429
        }
430

    
431
        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
432
    }
433

    
434
    /*
435
     * (non-Javadoc)
436
     *
437
     * @see
438
     * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
439
     * ()
440
     */
441
    /** {@inheritDoc} */
442
    @Override
443
    public boolean postOperation(CdmBase objectAffectedByOperation) {
444
    		setDirty(true);
445

    
446
        for (IEditorPart editor : this.getPages()) {
447
            if (editor instanceof IPostOperationEnabled) {
448
                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
449
            } else {
450
                MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_NOT_ENABLED + editor);
451
            }
452
        }
453
        MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_CALLED);
454

    
455
        return false;
456
    }
457

    
458
    /**
459
     * Returns an <code>IEditorPart</code> implementation by type
460
     *
461
     * @param page
462
     *            the page type
463
     * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
464
     *         object.
465
     */
466
    public IMultiPageTaxonEditorPage getPage(Page page) {
467
        for (IEditorPart editor : this.getPages()) {
468
            if (editor.getClass().equals(page.getClazz())) {
469
                return (IMultiPageTaxonEditorPage) editor;
470
            }
471
        }
472
        return null;
473
    }
474

    
475
    /**
476
     * Return a list of <code>AbstractTaxonEditor</code>s registered with this
477
     * <code>MultiPageTaxonEditor</code>.
478
     *
479
     * @return a {@link java.util.List} object.
480
     */
481
    public List<IMultiPageTaxonEditorPage> getPages() {
482
        ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
483
        for (int i = 0; i < this.getPageCount(); i++) {
484

    
485
            editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
486
        }
487
        return editors;
488
    }
489

    
490
    /**
491
     * Refreshes a certain page of the MultipageTaxonEditor
492
     *
493
     * @param page
494
     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
495
     * @return a boolean.
496
     */
497
    public boolean redraw(Page page) {
498
        return redraw(page, true);
499
    }
500

    
501
    /**
502
     * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
503
     * that page
504
     *
505
     * @param page
506
     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
507
     * @param focus
508
     *            a boolean.
509
     * @return a boolean.
510
     */
511
    public boolean redraw(Page page, boolean focus) {
512
        IMultiPageTaxonEditorPage editorPage = getPage(page);
513
        return editorPage != null && editorPage.redraw(focus);
514
    }
515

    
516
    /**
517
     * <p>
518
     * onComplete
519
     * </p>
520
     *
521
     * @return a boolean.
522
     */
523
    @Override
524
    public boolean onComplete() {
525
        return false;
526
    }
527

    
528
    /**
529
     * Reloads the data for this
530
     */
531
    public void reload() {
532
        if (isDirty()) {
533
            MessagingUtils.warningDialog(Messages.MultiPageTaxonEditor_UNSAVED_DATA, getClass(), Messages.MultiPageTaxonEditor_UNSAVED_DATA_MESSAGE);
534
        } else {
535
            TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
536

    
537
            UUID uuid = input.getTaxonNode().getUuid();
538

    
539
            conversation.clear();
540

    
541
            try {
542
                TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
543
                setInput(newInput);
544
                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
545
                    editorPart.redraw();
546
                }
547
            } catch (Exception e) {
548
                MessagingUtils.messageDialog(Messages.MultiPageTaxonEditor_REFRESH_ERROR, getClass(), Messages.MultiPageTaxonEditor_REFRESH_ERROR_MESSAGE, e);
549
            }
550
        }
551
    }
552

    
553
    @Override
554
    public String toString() {
555
        return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput()); //$NON-NLS-1$
556
    }
557

    
558
    @Override
559
    public boolean permissionsSatisfied() {
560
        IEditorPart activeEditor = getActiveEditor();
561
        if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
562
            return ((ISecuredEditor)activeEditor).permissionsSatisfied();
563
        }
564
        return true;
565
    }
566

    
567
    /* (non-Javadoc)
568
     * @see eu.etaxonomy.taxeditor.model.IPartContentHasMedia#canAttachMedia()
569
     */
570
    @Override
571
    public boolean canAttachMedia() {
572
        return true;
573
    }
574

    
575
}
(7-7/17)