Project

General

Profile

Download (13.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.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.DataChangeBridge;
36
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
37
import eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider;
38
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
39
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
40

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

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

    
58
	private boolean dirty;
59

    
60
	private ConversationHolder conversation;
61
	private IDataChangeBehavior dataChangeBehavior;
62
	private IUndoContext undoContext;
63

    
64
	private TaxonEditorInput input;
65

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

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

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

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

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

    
107
			// EditorUtil.showPropertySheet();
108

    
109
		} catch (PartInitException e) {
110
			EditorUtil.error(getClass(), e);
111
		}
112
	}
113

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

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

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

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

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

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

    
174
	private void setDirty(boolean dirty) {
175
		this.dirty = dirty;
176
		firePropertyChange(PROP_DIRTY);
177
	}
178

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

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

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

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

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

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

    
243
		if (!(input instanceof TaxonEditorInput))
244
			throw new PartInitException(
245
					"Invalid Input: Must be TaxonEditorInput");
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
	public void changed(Object element) {
299
		// setDirty(true);
300
		dirty = true;
301
		super.editorDirtyStateChanged();
302
		if (element instanceof TaxonBase) {
303
			TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
304
			AbstractGroupedContainer container = page
305
					.getContainer((TaxonBase) element);
306
			if (container != null) {
307
				container.refresh();
308
			}
309
		}
310
	}
311

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

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

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

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

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

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

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

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

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

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

    
429
		return false;
430
	}
431

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

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

    
459
			editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
460
		}
461
		return editors;
462
	}
463

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

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

    
490
	/**
491
	 * <p>
492
	 * onComplete
493
	 * </p>
494
	 * 
495
	 * @return a boolean.
496
	 */
497
	public boolean onComplete() {
498
		return false;
499
	}
500

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

    
517
			UUID uuid = input.getTaxonNode().getUuid();
518

    
519
			conversation.clear();
520

    
521
			try {
522
				TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
523
				setInput(newInput);
524
				for (IMultiPageTaxonEditorPage editorPart : getPages()) {
525
					editorPart.redraw();
526
				}
527
			} catch (Exception e) {
528
				EditorUtil.errorDialog("Error refreshing editor", getClass(),
529
						"Could not refresh this editor", e);
530
			}
531
		}
532
	}
533
	
534
	@Override
535
	public String toString() {
536
		return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput());
537
	}
538

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