Project

General

Profile

Download (17.6 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.TaxonName;
33
import eu.etaxonomy.cdm.model.taxon.Taxon;
34
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
35
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
36
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
37
import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
38
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
39
import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
40
import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
41
import eu.etaxonomy.taxeditor.model.AbstractUtility;
42
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
43
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
44
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
45
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
46
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
47
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
48
import eu.etaxonomy.taxeditor.model.MessagingUtils;
49
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
50

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

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

    
68
    private boolean dirty;
69

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

    
74
    private TaxonEditorInput input;
75

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

    
85
    }
86

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

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

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

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

    
119
            // EditorUtil.showPropertySheet();
120

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

    
126
    /**
127
     * {@inheritDoc}
128
     */
129
    @Override
130
    protected void pageChange(int newPageIndex) {
131
        if(getCurrentPage()==-1){
132
            return;
133
        }
134
        super.pageChange(newPageIndex);
135
    }
136

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

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

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

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

    
162
            input.merge();
163

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

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

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

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

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

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

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

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

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

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

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

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

    
270
        this.input = (TaxonEditorInput) input;
271

    
272

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

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

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

    
302
        String partName = null;
303
        TaxonName name = getTaxon().getName();
304

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

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

    
313
        setPartName(partName);
314
    }
315

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

    
331
        if (element instanceof TaxonBase) {
332
            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
333
            AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
334
            if (container != null) {
335
                container.refresh();
336
            }
337
        }
338
        if (element instanceof TaxonRelationship) {
339
            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
340
            AbstractGroupedContainer container = page.getContainer(((TaxonRelationship) element).getFromTaxon());
341
            if (container != null) {
342
                container.refresh();
343
            }
344
        }
345
        //refresh part title
346
        //TODO: refresh taxon node in taxon navigator
347
        setPartName();
348
    }
349

    
350
    /* (non-Javadoc)
351
     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
352
     */
353
    @Override
354
    public void forceDirty() {
355
        changed(null);
356
    }
357

    
358
    /**
359
     * The accepted taxon that is the input for this editor
360
     *
361
     * @return the accepted taxon
362
     */
363
    public Taxon getTaxon() {
364
        return input.getTaxon();
365
    }
366

    
367
    /*
368
     * (non-Javadoc)
369
     *
370
     * @see
371
     * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
372
     * ()
373
     */
374
    /**
375
     * <p>
376
     * getConversationHolder
377
     * </p>
378
     *
379
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
380
     *         object.
381
     */
382
    @Override
383
    public ConversationHolder getConversationHolder() {
384
        return conversation;
385
    }
386

    
387
    /**
388
     * <p>
389
     * setConversationHolder
390
     * </p>
391
     *
392
     * @param conversation
393
     *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
394
     *            object.
395
     */
396
    public void setConversationHolder(ConversationHolder conversation) {
397
        this.conversation = conversation;
398
    }
399

    
400
    /**
401
     * <p>
402
     * Getter for the field <code>undoContext</code>.
403
     * </p>
404
     *
405
     * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
406
     *         object.
407
     */
408
    public IUndoContext getUndoContext() {
409
        return undoContext;
410
    }
411

    
412
    /**
413
     * <p>
414
     * Setter for the field <code>undoContext</code>.
415
     * </p>
416
     *
417
     * @param undoContext
418
     *            a {@link org.eclipse.core.commands.operations.IUndoContext}
419
     *            object.
420
     */
421
    public void setUndoContext(IUndoContext undoContext) {
422
        this.undoContext = undoContext;
423
    }
424

    
425
    /** {@inheritDoc} */
426
    @Override
427
    public void setFocus() {
428
        // logger.warn("Setting focus to editor");
429
        // bind the conversation
430
        getConversationHolder().bind();
431
        input.bind();
432
        // pass focus to the active editor page
433
        getActiveEditor().setFocus();
434
    }
435

    
436
    /*
437
     * (non-Javadoc)
438
     *
439
     * @see
440
     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
441
     * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
442
     */
443
    /** {@inheritDoc} */
444
    @Override
445
    public void update(CdmDataChangeMap events) {
446
        if (dataChangeBehavior == null) {
447
            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
448
        }
449

    
450
        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
451
    }
452

    
453
    /*
454
     * (non-Javadoc)
455
     *
456
     * @see
457
     * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
458
     * ()
459
     */
460
    /** {@inheritDoc} */
461
    @Override
462
    public boolean postOperation(CdmBase objectAffectedByOperation) {
463
    		setDirty(true);
464

    
465
        for (IEditorPart editor : this.getPages()) {
466
            if (editor instanceof IPostOperationEnabled) {
467
                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
468
            } else {
469
                MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_NOT_ENABLED + editor);
470
            }
471
        }
472
        MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_CALLED);
473

    
474
        return false;
475
    }
476

    
477
    /**
478
     * Returns an <code>IEditorPart</code> implementation by type
479
     *
480
     * @param page
481
     *            the page type
482
     * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
483
     *         object.
484
     */
485
    public IMultiPageTaxonEditorPage getPage(Page page) {
486
        for (IEditorPart editor : this.getPages()) {
487
            if (editor.getClass().equals(page.getClazz())) {
488
                return (IMultiPageTaxonEditorPage) editor;
489
            }
490
        }
491
        return null;
492
    }
493

    
494
    /**
495
     * Return a list of <code>AbstractTaxonEditor</code>s registered with this
496
     * <code>MultiPageTaxonEditor</code>.
497
     *
498
     * @return a {@link java.util.List} object.
499
     */
500
    public List<IMultiPageTaxonEditorPage> getPages() {
501
        ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
502
        for (int i = 0; i < this.getPageCount(); i++) {
503

    
504
            editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
505
        }
506
        return editors;
507
    }
508

    
509
    /**
510
     * Refreshes a certain page of the MultipageTaxonEditor
511
     *
512
     * @param page
513
     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
514
     * @return a boolean.
515
     */
516
    public boolean redraw(Page page) {
517
        return redraw(page, true);
518
    }
519

    
520
    /**
521
     * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
522
     * that page
523
     *
524
     * @param page
525
     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
526
     * @param focus
527
     *            a boolean.
528
     * @return a boolean.
529
     */
530
    public boolean redraw(Page page, boolean focus) {
531
        IMultiPageTaxonEditorPage editorPage = getPage(page);
532
        return editorPage != null && editorPage.redraw(focus);
533
    }
534

    
535
    /**
536
     * <p>
537
     * onComplete
538
     * </p>
539
     *
540
     * @return a boolean.
541
     */
542
    @Override
543
    public boolean onComplete() {
544
        return false;
545
    }
546

    
547
    /**
548
     * Reloads the data for this
549
     */
550
    public void reload() {
551
        if (isDirty()) {
552
            MessagingUtils.warningDialog(Messages.MultiPageTaxonEditor_UNSAVED_DATA, getClass(), Messages.MultiPageTaxonEditor_UNSAVED_DATA_MESSAGE);
553
        } else {
554
            TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
555

    
556
            UUID uuid = input.getTaxonNode().getUuid();
557

    
558
            conversation.clear();
559

    
560
            try {
561
                TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
562
                setInput(newInput);
563
                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
564
                    editorPart.redraw();
565
                }
566
            } catch (Exception e) {
567
                MessagingUtils.messageDialog(Messages.MultiPageTaxonEditor_REFRESH_ERROR, getClass(), Messages.MultiPageTaxonEditor_REFRESH_ERROR_MESSAGE, e);
568
            }
569
        }
570
    }
571

    
572
    @Override
573
    public String toString() {
574
        return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput()); //$NON-NLS-1$
575
    }
576

    
577
    @Override
578
    public boolean permissionsSatisfied() {
579
        IEditorPart activeEditor = getActiveEditor();
580
        if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
581
            return ((ISecuredEditor)activeEditor).permissionsSatisfied();
582
        }
583
        return true;
584
    }
585

    
586
    /* (non-Javadoc)
587
     * @see eu.etaxonomy.taxeditor.model.IPartContentHasMedia#canAttachMedia()
588
     */
589
    @Override
590
    public boolean canAttachMedia() {
591
        return true;
592
    }
593

    
594
}
(7-7/17)