Project

General

Profile

Download (14.4 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.name.TaxonNameEditor;
34
import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
35
import eu.etaxonomy.taxeditor.model.AbstractUtility;
36
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
37
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
38
import eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider;
39
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
40
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
41
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
42

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

    
57
	/** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
58
	public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon";
59

    
60
	private boolean dirty;
61

    
62
	private ConversationHolder conversation;
63
	private IDataChangeBehavior dataChangeBehavior;
64
	private IUndoContext undoContext;
65

    
66
	private TaxonEditorInput input;
67

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

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

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

    
98
		try {
99
			addPage(Page.NAME.getIndex(), new TaxonNameEditor(this),
100
					getEditorInput());
101
			// setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
102

    
103
			// TODO lazy create
104
			// addPage(Page.DESCRIPTIVE.getIndex(), new
105
			// TaxonDescriptionTreeEditor(this), getEditorInput());
106
			// setPageText(Page.DESCRIPTIVE.getIndex(),
107
			// Page.DESCRIPTIVE.getTitle());
108

    
109
			// EditorUtil.showPropertySheet();
110

    
111
		} catch (PartInitException e) {
112
			AbstractUtility.error(getClass(), e);
113
		}
114
	}
115

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

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

    
136
                editorPage.doSave(monitor);
137
                monitor.worked(1);
138
            }
139

    
140
			// commit the conversation and start a new transaction immediately
141
			conversation.commit(true);
142
			monitor.worked(1);
143

    
144
            this.setDirty(false);
145
            monitor.worked(1);
146
        } catch (Exception e) {
147
            setFocus();
148
            AbstractUtility.errorDialog("An error occurred while saving", getClass(),
149
                    "An error occurred while saving the editor. Please close and reopen the taxon again.", e);
150
            disableEditor(true);
151
        } finally {
152
            monitor.done();
153
        }
154
	}
155

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

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

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

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

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

    
224
	/** {@inheritDoc} */
225
	@Override
226
	public void doSaveAs() {
227
	}
228

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

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

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

    
245
		this.input = (TaxonEditorInput) input;
246

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

    
265
		super.init(site, input);
266
	}
267

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

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

    
279
		if (name != null) {
280
			partName = name.getTitleCache();
281
		}
282

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

    
287
		setPartName(partName);
288
	}
289

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

    
310
	/**
311
	 * The accepted taxon that is the input for this editor
312
	 *
313
	 * @return the accepted taxon
314
	 */
315
	public Taxon getTaxon() {
316
		return input.getTaxon();
317
	}
318

    
319
	/*
320
	 * (non-Javadoc)
321
	 *
322
	 * @see
323
	 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
324
	 * ()
325
	 */
326
	/**
327
	 * <p>
328
	 * getConversationHolder
329
	 * </p>
330
	 *
331
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
332
	 *         object.
333
	 */
334
	@Override
335
    public ConversationHolder getConversationHolder() {
336
		return conversation;
337
	}
338

    
339
	/**
340
	 * <p>
341
	 * setConversationHolder
342
	 * </p>
343
	 *
344
	 * @param conversation
345
	 *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
346
	 *            object.
347
	 */
348
	public void setConversationHolder(ConversationHolder conversation) {
349
		this.conversation = conversation;
350
	}
351

    
352
	/**
353
	 * <p>
354
	 * Getter for the field <code>undoContext</code>.
355
	 * </p>
356
	 *
357
	 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
358
	 *         object.
359
	 */
360
	public IUndoContext getUndoContext() {
361
		return undoContext;
362
	}
363

    
364
	/**
365
	 * <p>
366
	 * Setter for the field <code>undoContext</code>.
367
	 * </p>
368
	 *
369
	 * @param undoContext
370
	 *            a {@link org.eclipse.core.commands.operations.IUndoContext}
371
	 *            object.
372
	 */
373
	public void setUndoContext(IUndoContext undoContext) {
374
		this.undoContext = undoContext;
375
	}
376

    
377
	/** {@inheritDoc} */
378
	@Override
379
	public void setFocus() {
380
		// logger.warn("Setting focus to editor");
381
		// bind the conversation
382
		getConversationHolder().bind();
383
		// pass focus to the active editor page
384
		getActiveEditor().setFocus();
385
	}
386

    
387
    /*
388
     * (non-Javadoc)
389
     *
390
     * @see
391
     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
392
     * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
393
     */
394
    /** {@inheritDoc} */
395
    @Override
396
    public void update(CdmDataChangeMap events) {
397
        if (dataChangeBehavior == null) {
398
            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
399
        }
400

    
401
        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
402
    }
403

    
404
    /*
405
     * (non-Javadoc)
406
     *
407
     * @see
408
     * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
409
     * ()
410
     */
411
    /** {@inheritDoc} */
412
    @Override
413
    public boolean postOperation(CdmBase objectAffectedByOperation) {
414
        setDirty(true);
415

    
416
        for (IEditorPart editor : this.getPages()) {
417
            if (editor instanceof IPostOperationEnabled) {
418
                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
419
            } else {
420
                AbstractUtility.warn(getClass(), "postOperation not enabled for editor " + editor);
421
            }
422
        }
423
        AbstractUtility.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
424

    
425
        return false;
426
    }
427

    
428
	/**
429
	 * Returns an <code>IEditorPart</code> implementation by type
430
	 *
431
	 * @param page
432
	 *            the page type
433
	 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
434
	 *         object.
435
	 */
436
	public IMultiPageTaxonEditorPage getPage(Page page) {
437
		for (IEditorPart editor : this.getPages()) {
438
			if (editor.getClass().equals(page.getClazz())) {
439
				return (IMultiPageTaxonEditorPage) editor;
440
			}
441
		}
442
		return null;
443
	}
444

    
445
	/**
446
	 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
447
	 * <code>MultiPageTaxonEditor</code>.
448
	 *
449
	 * @return a {@link java.util.List} object.
450
	 */
451
	public List<IMultiPageTaxonEditorPage> getPages() {
452
		ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
453
		for (int i = 0; i < this.getPageCount(); i++) {
454

    
455
			editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
456
		}
457
		return editors;
458
	}
459

    
460
	/**
461
	 * Refreshes a certain page of the MultipageTaxonEditor
462
	 *
463
	 * @param page
464
	 *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
465
	 * @return a boolean.
466
	 */
467
	public boolean redraw(Page page) {
468
		return redraw(page, true);
469
	}
470

    
471
	/**
472
	 * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
473
	 * that page
474
	 *
475
	 * @param page
476
	 *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
477
	 * @param focus
478
	 *            a boolean.
479
	 * @return a boolean.
480
	 */
481
	public boolean redraw(Page page, boolean focus) {
482
		IMultiPageTaxonEditorPage editorPage = getPage(page);
483
		return editorPage != null && editorPage.redraw(focus);
484
	}
485

    
486
	/**
487
	 * <p>
488
	 * onComplete
489
	 * </p>
490
	 *
491
	 * @return a boolean.
492
	 */
493
	@Override
494
    public boolean onComplete() {
495
		return false;
496
	}
497

    
498
    /**
499
     * Reloads the data for this
500
     */
501
    public void reload() {
502
        if (isDirty()) {
503
            AbstractUtility.warningDialog("Editor has unsaved data", getClass(), "This editor can not be "
504
                    + "refreshed because it contains unsaved data. Refreshing "
505
                    + "this editor would discard the changes. Please save this editor, "
506
                    + "close and reopen it manually in order to get the latest content");
507
        } else {
508
            TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
509

    
510
            UUID uuid = input.getTaxonNode().getUuid();
511

    
512
            conversation.clear();
513

    
514
            try {
515
                TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
516
                setInput(newInput);
517
                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
518
                    editorPart.redraw();
519
                }
520
            } catch (Exception e) {
521
                AbstractUtility.errorDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e);
522
            }
523
        }
524
    }
525

    
526
	@Override
527
	public String toString() {
528
		return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput());
529
	}
530

    
531
	@Override
532
	public boolean permissionsSatisfied() {
533
		IEditorPart activeEditor = getActiveEditor();
534
		if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
535
			return ((ISecuredEditor)activeEditor).permissionsSatisfied();
536
		}
537
		return true;
538
	}
539
}
(7-7/17)