Project

General

Profile

Download (14.8 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
    	if (objectAffectedByOperation != null){
425
    		setDirty(true);
426
    	}
427
        for (IEditorPart editor : this.getPages()) {
428
            if (editor instanceof IPostOperationEnabled) {
429
                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
430
            } else {
431
                MessagingUtils.warn(getClass(), "postOperation not enabled for editor " + editor);
432
            }
433
        }
434
        MessagingUtils.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
435

    
436
        return false;
437
    }
438

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

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

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

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

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

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

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

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

    
523
            conversation.clear();
524

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

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

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