Project

General

Profile

Download (17.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.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.IPartContentHasSupplementalData;
49
import eu.etaxonomy.taxeditor.model.MessagingUtils;
50
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
51

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

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

    
69
    private boolean dirty;
70

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

    
75
    private TaxonEditorInput input;
76

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

    
86
    }
87

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

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

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

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

    
120
            // EditorUtil.showPropertySheet();
121

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

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

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

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

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

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

    
163
            input.merge();
164

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

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

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

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

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

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

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

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

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

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

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

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

    
271
        this.input = (TaxonEditorInput) input;
272

    
273

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

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

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

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

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

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

    
314
        setPartName(partName);
315
    }
316

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

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

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

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

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

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

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

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

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

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

    
452
        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
453
    }
454

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

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

    
476
        return false;
477
    }
478

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

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

    
506
            editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
507
        }
508
        return editors;
509
    }
510

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

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

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

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

    
558
            UUID uuid = input.getTaxonNode().getUuid();
559

    
560
            conversation.clear();
561

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

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

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

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

    
596
}
(7-7/17)