Project

General

Profile

Download (17.2 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
    /**
126
     * {@inheritDoc}
127
     */
128
    @Override
129
    protected void pageChange(int newPageIndex) {
130
        if(getCurrentPage()==-1){
131
            return;
132
        }
133
        super.pageChange(newPageIndex);
134
    }
135

    
136
    /** {@inheritDoc} */
137
    @Override
138
    public void doSave(IProgressMonitor monitor) {
139
        monitor.beginTask(Messages.MultiPageTaxonEditor_SAVING_EDITOR, 4);
140
        try {
141
            if (!conversation.isBound()) {
142
                conversation.bind();
143
            }
144
            monitor.worked(1);
145

    
146
            for (IEditorPart editorPage : getPages()) {
147
                if (editorPage instanceof TaxonNameEditor) {
148
                    if (((TaxonNameEditor) editorPage).checkForEmptyNames()) {
149
                        MessageDialog.openWarning(AbstractUtility.getShell(), Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED,
150
                                Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE);
151
                        return;
152
                    }
153
                }
154

    
155
                editorPage.doSave(monitor);
156
                monitor.worked(1);
157
            }
158

    
159
            // commit the conversation and start a new transaction immediately
160

    
161
            input.merge();
162

    
163
            conversation.commit(true);
164
            CdmApplicationState.getCurrentDataChangeService()
165
            .fireChangeEvent(new CdmChangeEvent(Action.Update, input.getTaxonNode() , MultiPageTaxonEditor.class), true);
166
            monitor.worked(1);
167

    
168
            this.setDirty(false);
169
            monitor.worked(1);
170
        } catch (Exception e) {
171
            setFocus();
172
            MessagingUtils.operationDialog(this, e, TaxeditorEditorPlugin.PLUGIN_ID,Messages.MultiPageTaxonEditor_SAVING_TAXON, Messages.MultiPageTaxonEditor_SAVING_TAXON_MESSAGE);
173
            disableEditor(true);
174
        } finally {
175
            monitor.done();
176
        }
177
    }
178

    
179
    private void disableEditor(boolean isOnError) {
180
        for (IMultiPageTaxonEditorPage editorPage : getPages()) {
181
            if(isOnError){
182
                editorPage.setOnError();
183
            }else {
184
                editorPage.setDisabled();
185
            }
186
        }
187

    
188
        conversation.unregisterForDataStoreChanges(this);
189
        conversation.close();
190
        setDirty(false);
191
    }
192

    
193
    private void setDirty(boolean dirty) {
194
        this.dirty = dirty;
195
        firePropertyChange(PROP_DIRTY);
196
    }
197

    
198
    /*
199
     * (non-Javadoc)
200
     *
201
     * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
202
     */
203
    /**
204
     * <p>
205
     * isDirty
206
     * </p>
207
     *
208
     * @return a boolean.
209
     */
210
    @Override
211
    public boolean isDirty() {
212
        return dirty;
213
    }
214

    
215
    /*
216
     * (non-Javadoc)
217
     *
218
     * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
219
     */
220
    /** {@inheritDoc} */
221
    @Override
222
    public void editorDirtyStateChanged() {
223
        dirty = true;
224
        super.editorDirtyStateChanged();
225
    }
226

    
227
    /**
228
     * {@inheritDoc}
229
     *
230
     * Checks whether nested editors are calling
231
     * <code>firePropertyChange(PROP_DIRTY)</code> to signal an edit has taken
232
     * place before passing property change along to
233
     * <code>super.handlePropertyChange(int propertyId)</code>.
234
     */
235
    /*
236
     * (non-Javadoc)
237
     *
238
     * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
239
     */
240
    @Override
241
    protected void handlePropertyChange(int propertyId) {
242
        if (propertyId == PROP_DIRTY) {
243
            setDirty(true);
244
        }
245
        super.handlePropertyChange(propertyId);
246
    }
247

    
248
    /** {@inheritDoc} */
249
    @Override
250
    public void doSaveAs() {
251
    }
252

    
253
    /** {@inheritDoc} */
254
    @Override
255
    public boolean isSaveAsAllowed() {
256
        return false;
257
    }
258

    
259
    /** {@inheritDoc} */
260
    @Override
261
    public void init(IEditorSite site, IEditorInput input)
262
            throws PartInitException {
263

    
264
        if (!(input instanceof TaxonEditorInput)) {
265
            throw new PartInitException(
266
                    Messages.MultiPageTaxonEditor_INVALID_INPUT);
267
        }
268

    
269
        this.input = (TaxonEditorInput) input;
270

    
271

    
272
        // try {
273
        // // Listen for name changes,
274
        // // change tab for this taxon editor accordingly
275
        // getTaxon().addPropertyChangeListener("name",
276
        // new PropertyChangeListener() {
277
        // public void propertyChange(PropertyChangeEvent e) {
278
        // setPartName();
279
        // }
280
        // });
281
        // } catch (NullPointerException e) {
282
        // EditorUtil.warn(getClass(),
283
        // "Caught an NPE while initing an editor. This is most " +
284
        // "likely due to the unsuccesful attempt to restore the former " +
285
        // "state of the application. We ignore this because the workbench " +
286
        // "will simply be reset.");
287
        // }
288
        setPartName();
289

    
290
        super.init(site, input);
291
    }
292

    
293
    /**
294
     * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
295
     * text appropriate to the state of the taxon: any taxon that has been saved
296
     * will by necessity have a name to display; a new taxon should display
297
     * "New taxon" in the editor tab.
298
     */
299
    protected void setPartName() {
300

    
301
        String partName = null;
302
        TaxonNameBase<?, ?> name = getTaxon().getName();
303

    
304
        if (name != null) {
305
            partName = name.getTitleCache();
306
        }
307

    
308
        if (partName == null || partName.equals("")) { //$NON-NLS-1$
309
            partName = (Messages.MultiPageTaxonEditor_NEW_TAXON);
310
        }
311

    
312
        setPartName(partName);
313
    }
314

    
315
    /**
316
     * {@inheritDoc}
317
     *
318
     * Editor pages call this in their postOperation to notify the
319
     * MultiPageTaxonEditor of unsaved changes
320
     */
321
    @Override
322
    public void changed(Object element) {
323
        // setDirty(true);
324
        // 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
325
        if (element != null){
326
            dirty = true;
327
            super.editorDirtyStateChanged();
328
        }
329

    
330
        if (element instanceof TaxonBase) {
331
            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
332
            AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
333
            if (container != null) {
334
                container.refresh();
335
            }
336
        }
337
        //refresh part title
338
        //TODO: refresh taxon node in taxon navigator
339
        setPartName();
340
    }
341

    
342
    /* (non-Javadoc)
343
     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
344
     */
345
    @Override
346
    public void forceDirty() {
347
        changed(null);
348
    }
349

    
350
    /**
351
     * The accepted taxon that is the input for this editor
352
     *
353
     * @return the accepted taxon
354
     */
355
    public Taxon getTaxon() {
356
        return input.getTaxon();
357
    }
358

    
359
    /*
360
     * (non-Javadoc)
361
     *
362
     * @see
363
     * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
364
     * ()
365
     */
366
    /**
367
     * <p>
368
     * getConversationHolder
369
     * </p>
370
     *
371
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
372
     *         object.
373
     */
374
    @Override
375
    public ConversationHolder getConversationHolder() {
376
        return conversation;
377
    }
378

    
379
    /**
380
     * <p>
381
     * setConversationHolder
382
     * </p>
383
     *
384
     * @param conversation
385
     *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
386
     *            object.
387
     */
388
    public void setConversationHolder(ConversationHolder conversation) {
389
        this.conversation = conversation;
390
    }
391

    
392
    /**
393
     * <p>
394
     * Getter for the field <code>undoContext</code>.
395
     * </p>
396
     *
397
     * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
398
     *         object.
399
     */
400
    public IUndoContext getUndoContext() {
401
        return undoContext;
402
    }
403

    
404
    /**
405
     * <p>
406
     * Setter for the field <code>undoContext</code>.
407
     * </p>
408
     *
409
     * @param undoContext
410
     *            a {@link org.eclipse.core.commands.operations.IUndoContext}
411
     *            object.
412
     */
413
    public void setUndoContext(IUndoContext undoContext) {
414
        this.undoContext = undoContext;
415
    }
416

    
417
    /** {@inheritDoc} */
418
    @Override
419
    public void setFocus() {
420
        // logger.warn("Setting focus to editor");
421
        // bind the conversation
422
        getConversationHolder().bind();
423
        input.bind();
424
        // pass focus to the active editor page
425
        getActiveEditor().setFocus();
426
    }
427

    
428
    /*
429
     * (non-Javadoc)
430
     *
431
     * @see
432
     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
433
     * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
434
     */
435
    /** {@inheritDoc} */
436
    @Override
437
    public void update(CdmDataChangeMap events) {
438
        if (dataChangeBehavior == null) {
439
            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
440
        }
441

    
442
        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
443
    }
444

    
445
    /*
446
     * (non-Javadoc)
447
     *
448
     * @see
449
     * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
450
     * ()
451
     */
452
    /** {@inheritDoc} */
453
    @Override
454
    public boolean postOperation(CdmBase objectAffectedByOperation) {
455
    		setDirty(true);
456

    
457
        for (IEditorPart editor : this.getPages()) {
458
            if (editor instanceof IPostOperationEnabled) {
459
                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
460
            } else {
461
                MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_NOT_ENABLED + editor);
462
            }
463
        }
464
        MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_CALLED);
465

    
466
        return false;
467
    }
468

    
469
    /**
470
     * Returns an <code>IEditorPart</code> implementation by type
471
     *
472
     * @param page
473
     *            the page type
474
     * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
475
     *         object.
476
     */
477
    public IMultiPageTaxonEditorPage getPage(Page page) {
478
        for (IEditorPart editor : this.getPages()) {
479
            if (editor.getClass().equals(page.getClazz())) {
480
                return (IMultiPageTaxonEditorPage) editor;
481
            }
482
        }
483
        return null;
484
    }
485

    
486
    /**
487
     * Return a list of <code>AbstractTaxonEditor</code>s registered with this
488
     * <code>MultiPageTaxonEditor</code>.
489
     *
490
     * @return a {@link java.util.List} object.
491
     */
492
    public List<IMultiPageTaxonEditorPage> getPages() {
493
        ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
494
        for (int i = 0; i < this.getPageCount(); i++) {
495

    
496
            editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
497
        }
498
        return editors;
499
    }
500

    
501
    /**
502
     * Refreshes a certain page of the MultipageTaxonEditor
503
     *
504
     * @param page
505
     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
506
     * @return a boolean.
507
     */
508
    public boolean redraw(Page page) {
509
        return redraw(page, true);
510
    }
511

    
512
    /**
513
     * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
514
     * that page
515
     *
516
     * @param page
517
     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
518
     * @param focus
519
     *            a boolean.
520
     * @return a boolean.
521
     */
522
    public boolean redraw(Page page, boolean focus) {
523
        IMultiPageTaxonEditorPage editorPage = getPage(page);
524
        return editorPage != null && editorPage.redraw(focus);
525
    }
526

    
527
    /**
528
     * <p>
529
     * onComplete
530
     * </p>
531
     *
532
     * @return a boolean.
533
     */
534
    @Override
535
    public boolean onComplete() {
536
        return false;
537
    }
538

    
539
    /**
540
     * Reloads the data for this
541
     */
542
    public void reload() {
543
        if (isDirty()) {
544
            MessagingUtils.warningDialog(Messages.MultiPageTaxonEditor_UNSAVED_DATA, getClass(), Messages.MultiPageTaxonEditor_UNSAVED_DATA_MESSAGE);
545
        } else {
546
            TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
547

    
548
            UUID uuid = input.getTaxonNode().getUuid();
549

    
550
            conversation.clear();
551

    
552
            try {
553
                TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
554
                setInput(newInput);
555
                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
556
                    editorPart.redraw();
557
                }
558
            } catch (Exception e) {
559
                MessagingUtils.messageDialog(Messages.MultiPageTaxonEditor_REFRESH_ERROR, getClass(), Messages.MultiPageTaxonEditor_REFRESH_ERROR_MESSAGE, e);
560
            }
561
        }
562
    }
563

    
564
    @Override
565
    public String toString() {
566
        return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput()); //$NON-NLS-1$
567
    }
568

    
569
    @Override
570
    public boolean permissionsSatisfied() {
571
        IEditorPart activeEditor = getActiveEditor();
572
        if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
573
            return ((ISecuredEditor)activeEditor).permissionsSatisfied();
574
        }
575
        return true;
576
    }
577

    
578
    /* (non-Javadoc)
579
     * @see eu.etaxonomy.taxeditor.model.IPartContentHasMedia#canAttachMedia()
580
     */
581
    @Override
582
    public boolean canAttachMedia() {
583
        return true;
584
    }
585

    
586
}
(7-7/17)