Project

General

Profile

Download (14.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.conversation.ConversationHolder;
27
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
28
import eu.etaxonomy.cdm.model.common.CdmBase;
29
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
30
import eu.etaxonomy.cdm.model.taxon.Taxon;
31
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
32
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
33
import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
34
import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
35
import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
36
import eu.etaxonomy.taxeditor.model.AbstractUtility;
37
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
38
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
39
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
40
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
41
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
42
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
43
import eu.etaxonomy.taxeditor.model.MessagingUtils;
44
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
45

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

    
60
	/** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
61
	public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon";
62

    
63
	private boolean dirty;
64

    
65
	private ConversationHolder conversation;
66
	private IDataChangeBehavior dataChangeBehavior;
67
	private IUndoContext undoContext;
68

    
69
	private TaxonEditorInput input;
70

    
71
	/**
72
	 * <p>
73
	 * Constructor for MultiPageTaxonEditor.
74
	 * </p>
75
	 */
76
	public MultiPageTaxonEditor() {
77
		super();
78
		undoContext = new UndoContext();
79
	}
80

    
81
	/** {@inheritDoc} */
82
	@Override
83
	public void dispose() {
84
		conversation.unregisterForDataStoreChanges(this);
85
		conversation.close();
86
		super.dispose();
87
	}
88

    
89
	/*
90
	 * (non-Javadoc)
91
	 *
92
	 * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
93
	 */
94
	/** {@inheritDoc} */
95
	@Override
96
	protected void addPages() {
97
		input = (TaxonEditorInput) getEditorInput();
98
		conversation = input.getConversationHolder();
99
		conversation.registerForDataStoreChanges(this);
100

    
101
		try {
102
			addPage(Page.NAME.getIndex(), new TaxonNameEditor(this),
103
					getEditorInput());
104
			// setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
105

    
106
			// TODO lazy create
107
			// addPage(Page.DESCRIPTIVE.getIndex(), new
108
			// TaxonDescriptionTreeEditor(this), getEditorInput());
109
			// setPageText(Page.DESCRIPTIVE.getIndex(),
110
			// Page.DESCRIPTIVE.getTitle());
111

    
112
			// EditorUtil.showPropertySheet();
113

    
114
		} catch (PartInitException e) {
115
			MessagingUtils.error(getClass(), e);
116
		}
117
	}
118

    
119
	/** {@inheritDoc} */
120
	@Override
121
	public void doSave(IProgressMonitor monitor) {
122
		monitor.beginTask("Saving Editor", 4);
123
		try {
124
			if (!conversation.isBound()) {
125
				conversation.bind();
126
			}
127
			monitor.worked(1);
128

    
129
            for (IEditorPart editorPage : getPages()) {
130
                if (editorPage instanceof TaxonNameEditor) {
131
                    if (((TaxonNameEditor) editorPage).checkForEmptyNames()) {
132
                        MessageDialog.openWarning(AbstractUtility.getShell(), "No Name Specified",
133
                                "An attempt was made to save a taxon or synonym with "
134
                                        + "an empty name. Operation was cancelled.");
135
                        return;
136
                    }
137
                }
138

    
139
                editorPage.doSave(monitor);
140
                monitor.worked(1);
141
            }
142

    
143
			// commit the conversation and start a new transaction immediately
144
			conversation.commit(true);
145
			monitor.worked(1);
146

    
147
            this.setDirty(false);
148
            monitor.worked(1);
149
        } catch (Exception e) {
150
            setFocus();
151
            MessagingUtils.operationDialog(this, e, TaxeditorEditorPlugin.PLUGIN_ID,"saving a taxon", " Please close and reopen the taxon again.");
152
            disableEditor(true);
153
        } finally {
154
            monitor.done();
155
        }
156
	}
157

    
158
	private void disableEditor(boolean isOnError) {
159
		for (IMultiPageTaxonEditorPage editorPage : getPages()) {
160
			if(isOnError){
161
				editorPage.setOnError();
162
			}else {
163
				editorPage.setDisabled();
164
			}
165
		}
166
		conversation.unregisterForDataStoreChanges(this);
167
		conversation.close();
168
		setDirty(false);
169
	}
170

    
171
	private void setDirty(boolean dirty) {
172
		this.dirty = dirty;
173
		firePropertyChange(PROP_DIRTY);
174
	}
175

    
176
	/*
177
	 * (non-Javadoc)
178
	 *
179
	 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
180
	 */
181
	/**
182
	 * <p>
183
	 * isDirty
184
	 * </p>
185
	 *
186
	 * @return a boolean.
187
	 */
188
	@Override
189
    public boolean isDirty() {
190
		return dirty;
191
	}
192

    
193
	/*
194
	 * (non-Javadoc)
195
	 *
196
	 * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
197
	 */
198
	/** {@inheritDoc} */
199
	@Override
200
	public void editorDirtyStateChanged() {
201
		dirty = true;
202
		super.editorDirtyStateChanged();
203
	}
204

    
205
	/**
206
	 * {@inheritDoc}
207
	 *
208
	 * Checks whether nested editors are calling
209
	 * <code>firePropertyChange(PROP_DIRTY)</code> to signal an edit has taken
210
	 * place before passing property change along to
211
	 * <code>super.handlePropertyChange(int propertyId)</code>.
212
	 */
213
	/*
214
	 * (non-Javadoc)
215
	 *
216
	 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
217
	 */
218
	@Override
219
    protected void handlePropertyChange(int propertyId) {
220
		if (propertyId == PROP_DIRTY) {
221
			setDirty(true);
222
		}
223
		super.handlePropertyChange(propertyId);
224
	}
225

    
226
	/** {@inheritDoc} */
227
	@Override
228
	public void doSaveAs() {
229
	}
230

    
231
	/** {@inheritDoc} */
232
	@Override
233
	public boolean isSaveAsAllowed() {
234
		return false;
235
	}
236

    
237
	/** {@inheritDoc} */
238
	@Override
239
	public void init(IEditorSite site, IEditorInput input)
240
			throws PartInitException {
241

    
242
		if (!(input instanceof TaxonEditorInput)) {
243
            throw new PartInitException(
244
					"Invalid Input: Must be TaxonEditorInput");
245
        }
246

    
247
		this.input = (TaxonEditorInput) input;
248

    
249
		// try {
250
		// // Listen for name changes,
251
		// // change tab for this taxon editor accordingly
252
		// getTaxon().addPropertyChangeListener("name",
253
		// new PropertyChangeListener() {
254
		// public void propertyChange(PropertyChangeEvent e) {
255
		// setPartName();
256
		// }
257
		// });
258
		// } catch (NullPointerException e) {
259
		// EditorUtil.warn(getClass(),
260
		// "Caught an NPE while initing an editor. This is most " +
261
		// "likely due to the unsuccesful attempt to restore the former " +
262
		// "state of the application. We ignore this because the workbench " +
263
		// "will simply be reset.");
264
		// }
265
		setPartName();
266

    
267
		super.init(site, input);
268
	}
269

    
270
	/**
271
	 * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
272
	 * text appropriate to the state of the taxon: any taxon that has been saved
273
	 * will by necessity have a name to display; a new taxon should display
274
	 * "New taxon" in the editor tab.
275
	 */
276
	protected void setPartName() {
277

    
278
		String partName = null;
279
		TaxonNameBase<?, ?> name = getTaxon().getName();
280

    
281
		if (name != null) {
282
			partName = name.getTitleCache();
283
		}
284

    
285
		if (partName == null || partName.equals("")) {
286
			partName = ("New taxon");
287
		}
288

    
289
		setPartName(partName);
290
	}
291

    
292
    /**
293
     * {@inheritDoc}
294
     *
295
     * Editor pages call this in their postOperation to notify the
296
     * MultiPageTaxonEditor of unsaved changes
297
     */
298
    @Override
299
    public void changed(Object element) {
300
        // setDirty(true);
301
        dirty = true;
302
        super.editorDirtyStateChanged();
303
        if (element instanceof TaxonBase) {
304
            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
305
            AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
306
            if (container != null) {
307
                container.refresh();
308
            }
309
        }
310
    }
311

    
312
    /* (non-Javadoc)
313
     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
314
     */
315
    @Override
316
    public void forceDirty() {
317
        changed(null);
318
    }
319

    
320
	/**
321
	 * The accepted taxon that is the input for this editor
322
	 *
323
	 * @return the accepted taxon
324
	 */
325
	public Taxon getTaxon() {
326
		return input.getTaxon();
327
	}
328

    
329
	/*
330
	 * (non-Javadoc)
331
	 *
332
	 * @see
333
	 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
334
	 * ()
335
	 */
336
	/**
337
	 * <p>
338
	 * getConversationHolder
339
	 * </p>
340
	 *
341
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
342
	 *         object.
343
	 */
344
	@Override
345
    public ConversationHolder getConversationHolder() {
346
		return conversation;
347
	}
348

    
349
	/**
350
	 * <p>
351
	 * setConversationHolder
352
	 * </p>
353
	 *
354
	 * @param conversation
355
	 *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
356
	 *            object.
357
	 */
358
	public void setConversationHolder(ConversationHolder conversation) {
359
		this.conversation = conversation;
360
	}
361

    
362
	/**
363
	 * <p>
364
	 * Getter for the field <code>undoContext</code>.
365
	 * </p>
366
	 *
367
	 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
368
	 *         object.
369
	 */
370
	public IUndoContext getUndoContext() {
371
		return undoContext;
372
	}
373

    
374
	/**
375
	 * <p>
376
	 * Setter for the field <code>undoContext</code>.
377
	 * </p>
378
	 *
379
	 * @param undoContext
380
	 *            a {@link org.eclipse.core.commands.operations.IUndoContext}
381
	 *            object.
382
	 */
383
	public void setUndoContext(IUndoContext undoContext) {
384
		this.undoContext = undoContext;
385
	}
386

    
387
	/** {@inheritDoc} */
388
	@Override
389
	public void setFocus() {
390
		// logger.warn("Setting focus to editor");
391
		// bind the conversation
392
		getConversationHolder().bind();
393
		// pass focus to the active editor page
394
		getActiveEditor().setFocus();
395
	}
396

    
397
    /*
398
     * (non-Javadoc)
399
     *
400
     * @see
401
     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
402
     * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
403
     */
404
    /** {@inheritDoc} */
405
    @Override
406
    public void update(CdmDataChangeMap events) {
407
        if (dataChangeBehavior == null) {
408
            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
409
        }
410

    
411
        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
412
    }
413

    
414
    /*
415
     * (non-Javadoc)
416
     *
417
     * @see
418
     * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
419
     * ()
420
     */
421
    /** {@inheritDoc} */
422
    @Override
423
    public boolean postOperation(CdmBase objectAffectedByOperation) {
424
        setDirty(true);
425

    
426
        for (IEditorPart editor : this.getPages()) {
427
            if (editor instanceof IPostOperationEnabled) {
428
                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
429
            } else {
430
                MessagingUtils.warn(getClass(), "postOperation not enabled for editor " + editor);
431
            }
432
        }
433
        MessagingUtils.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
434

    
435
        return false;
436
    }
437

    
438
	/**
439
	 * Returns an <code>IEditorPart</code> implementation by type
440
	 *
441
	 * @param page
442
	 *            the page type
443
	 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
444
	 *         object.
445
	 */
446
	public IMultiPageTaxonEditorPage getPage(Page page) {
447
		for (IEditorPart editor : this.getPages()) {
448
			if (editor.getClass().equals(page.getClazz())) {
449
				return (IMultiPageTaxonEditorPage) editor;
450
			}
451
		}
452
		return null;
453
	}
454

    
455
	/**
456
	 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
457
	 * <code>MultiPageTaxonEditor</code>.
458
	 *
459
	 * @return a {@link java.util.List} object.
460
	 */
461
	public List<IMultiPageTaxonEditorPage> getPages() {
462
		ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
463
		for (int i = 0; i < this.getPageCount(); i++) {
464

    
465
			editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
466
		}
467
		return editors;
468
	}
469

    
470
	/**
471
	 * Refreshes a certain page of the MultipageTaxonEditor
472
	 *
473
	 * @param page
474
	 *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
475
	 * @return a boolean.
476
	 */
477
	public boolean redraw(Page page) {
478
		return redraw(page, true);
479
	}
480

    
481
	/**
482
	 * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
483
	 * that page
484
	 *
485
	 * @param page
486
	 *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
487
	 * @param focus
488
	 *            a boolean.
489
	 * @return a boolean.
490
	 */
491
	public boolean redraw(Page page, boolean focus) {
492
		IMultiPageTaxonEditorPage editorPage = getPage(page);
493
		return editorPage != null && editorPage.redraw(focus);
494
	}
495

    
496
	/**
497
	 * <p>
498
	 * onComplete
499
	 * </p>
500
	 *
501
	 * @return a boolean.
502
	 */
503
	@Override
504
    public boolean onComplete() {
505
		return false;
506
	}
507

    
508
    /**
509
     * Reloads the data for this
510
     */
511
    public void reload() {
512
        if (isDirty()) {
513
            MessagingUtils.warningDialog("Editor has unsaved data", getClass(), "This editor can not be "
514
                    + "refreshed because it contains unsaved data. Refreshing "
515
                    + "this editor would discard the changes. Please save this editor, "
516
                    + "close and reopen it manually in order to get the latest content");
517
        } else {
518
            TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
519

    
520
            UUID uuid = input.getTaxonNode().getUuid();
521

    
522
            conversation.clear();
523

    
524
            try {
525
                TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
526
                setInput(newInput);
527
                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
528
                    editorPart.redraw();
529
                }
530
            } catch (Exception e) {
531
                MessagingUtils.messageDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e);
532
            }
533
        }
534
    }
535

    
536
	@Override
537
	public String toString() {
538
		return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput());
539
	}
540

    
541
	@Override
542
	public boolean permissionsSatisfied() {
543
		IEditorPart activeEditor = getActiveEditor();
544
		if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
545
			return ((ISecuredEditor)activeEditor).permissionsSatisfied();
546
		}
547
		return true;
548
	}
549
}
(8-8/18)