fix #6550 Discard page change event if no current page is present
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / MultiPageTaxonEditor.java
index 7725380804b367cb7985b5598d9c0d2eb5583d41..e427b39e12a1fa99bdc71fb2cfc90acc1eaa844d 100644 (file)
@@ -1,11 +1,11 @@
 /**
-* Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy 
-* http://www.e-taxonomy.eu
-* 
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
+ * Copyright (C) 2007 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
 
 package eu.etaxonomy.taxeditor.editor;
 
@@ -23,6 +23,9 @@ import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.forms.editor.FormEditor;
 
+import eu.etaxonomy.cdm.api.application.CdmApplicationState;
+import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
+import eu.etaxonomy.cdm.api.application.CdmChangeEvent.Action;
 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
 import eu.etaxonomy.cdm.model.common.CdmBase;
@@ -30,421 +33,554 @@ import eu.etaxonomy.cdm.model.name.TaxonNameBase;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.editor.internal.TaxeditorEditorPlugin;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
 import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
 import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
 import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
-import eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider;
+import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
+import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
+import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
 
 /**
  *
- * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs for
- *  "Descriptions", "Concepts", "Geography", etc.
+ * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs
+ * for "Descriptions", "Concepts", "Geography", etc.
  *
  * @author p.ciardelli
  * @author n.hoffmann
  * @created 15.05.2008
  * @version 1.0
  */
-public class MultiPageTaxonEditor extends FormEditor implements IConversationEnabled, IPostOperationEnabled, IDirtyMarkableSelectionProvider, IPartContentHasDetails { 
-
-       /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
-       public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon";
-
-       private boolean dirty;
-
-       private ConversationHolder conversation;
-       private IDataChangeBehavior dataChangeBehavior;
-       private IUndoContext undoContext;
-
-       private TaxonEditorInput input;
-       
-       /**
-        * <p>Constructor for MultiPageTaxonEditor.</p>
-        */
-       public MultiPageTaxonEditor() {
-               super();                
-               undoContext = new UndoContext();
-       }
-       
-       /** {@inheritDoc} */
-       @Override
-       public void dispose() {
-               conversation.unregisterForDataStoreChanges(this);
-               conversation.close();
-               super.dispose();                
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
-        */
-       /** {@inheritDoc} */
-       @Override
-       protected void addPages() {
-               input = (TaxonEditorInput) getEditorInput();
-               conversation = input.getConversationHolder();
-               conversation.registerForDataStoreChanges(this);
-               
-               try {
-                       addPage(Page.NAME.getIndex(), new TaxonNameEditor(this), getEditorInput());
-//                     setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
-                       
-                       // TODO lazy create
-//                     addPage(Page.DESCRIPTIVE.getIndex(), new TaxonDescriptionTreeEditor(this), getEditorInput());
-//                     setPageText(Page.DESCRIPTIVE.getIndex(), Page.DESCRIPTIVE.getTitle());
-                       
-//                     EditorUtil.showPropertySheet();
-                                       
-               } catch (PartInitException e) {
-                       EditorUtil.error(getClass(), e);
-               }
-       }
-       
-       
-       /** {@inheritDoc} */
-       @Override
-       public void doSave(IProgressMonitor monitor) {
-               monitor.beginTask("Saving Editor", 4);
-               try{
-                       if( ! conversation.isBound()){
-                               conversation.bind();
-                       }
-                       monitor.worked(1);
-                       
-                       for(IEditorPart editorPage : getPages()){
-                               if(editorPage instanceof TaxonNameEditor){
-                                       if(((TaxonNameEditor) editorPage).checkForEmptyNames()){
-                                               MessageDialog.openWarning(EditorUtil.getShell(), "No Name Specified", "An attempt was made to save a taxon or synonym with " +
-                                               "an empty name. Operation was cancelled.");
-                                               return;
-                                       }
-                               }
-       
-                               editorPage.doSave(monitor);
-                               monitor.worked(1);
-                       }
-                       
-                       // commit the conversation and start a new transaction immediately
-                       conversation.commit(true);
-                       monitor.worked(1);
-                       
-                       this.setDirty(false);
-                       monitor.worked(1);
-               }finally{
-                       monitor.done();
-               }
-       }
-
-
-       private void setDirty(boolean dirty) {
-               this.dirty = dirty;
-               firePropertyChange(PROP_DIRTY);
-       }
-       
-       /* (non-Javadoc)
-        * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
-        */
-       /**
-        * <p>isDirty</p>
-        *
-        * @return a boolean.
-        */
-       public boolean isDirty() {
-               return dirty;
-       }
-
-       /* (non-Javadoc)
-        * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
-        */
-       /** {@inheritDoc} */
-       @Override
-       public void editorDirtyStateChanged() {
-               dirty = true;
-               super.editorDirtyStateChanged();
-       }
-       
-       
-       /**
-        * {@inheritDoc}
-        *
-        * Checks whether nested editors are calling <code>firePropertyChange(PROP_DIRTY)</code>
-        * to signal an edit has taken place before passing property change along to
-        * <code>super.handlePropertyChange(int propertyId)</code>.
-        */
-       /* (non-Javadoc)
-        * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
-        */
-       protected void handlePropertyChange(int propertyId) {
-               if (propertyId == PROP_DIRTY) {
-                       setDirty(true);
-               }
-               super.handlePropertyChange(propertyId);
-       }
-       
-       /** {@inheritDoc} */
-       @Override
-       public void doSaveAs() {}
-
-       /** {@inheritDoc} */
-       @Override
-       public boolean isSaveAsAllowed() {
-               return false;
-       }
-
-       /** {@inheritDoc} */
-       @Override
-       public void init(IEditorSite site, IEditorInput input) throws PartInitException {
-               
-               if (!(input instanceof TaxonEditorInput))
-                       throw new PartInitException(
-                                       "Invalid Input: Must be TaxonEditorInput");
-               
-               this.input = (TaxonEditorInput) input;
-
-//             try {
-//                     // Listen for name changes, 
-//                     //  change tab for this taxon editor accordingly
-//                     getTaxon().addPropertyChangeListener("name",
-//                                     new PropertyChangeListener() {
-//                                             public void propertyChange(PropertyChangeEvent e) {
-//                                                     setPartName();
-//                                             }
-//                                     });
-//             } catch (NullPointerException e) {
-//                     EditorUtil.warn(getClass(), "Caught an NPE while initing an editor. This is most " +
-//                                     "likely due to the unsuccesful attempt to restore the former " +
-//                                     "state of the application. We ignore this because the workbench " +
-//                                     "will simply be reset.");
-//             }
-               setPartName();
-               
-               super.init(site, input);
-       }
-               
+public class MultiPageTaxonEditor extends FormEditor implements
+IPartContentHasFactualData, IConversationEnabled, IPostOperationEnabled,
+IDirtyMarkable, IPartContentHasDetails, ISecuredEditor, IPartContentHasMedia {
+
+    /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
+    public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon"; //$NON-NLS-1$
+
+    private boolean dirty;
+
+    private ConversationHolder conversation;
+    private IDataChangeBehavior dataChangeBehavior;
+    private IUndoContext undoContext;
+
+    private TaxonEditorInput input;
+
+    /**
+     * <p>
+     * Constructor for MultiPageTaxonEditor.
+     * </p>
+     */
+    public MultiPageTaxonEditor() {
+        super();
+        undoContext = new UndoContext();
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void dispose() {
+        input.dispose();
+        conversation.unregisterForDataStoreChanges(this);
+        conversation.close();
+        super.dispose();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
+     */
+    /** {@inheritDoc} */
+    @Override
+    protected void addPages() {
+        input = (TaxonEditorInput) getEditorInput();
+        conversation = input.getConversationHolder();
+        conversation.registerForDataStoreChanges(this);
+
+        try {
+            addPage(Page.NAME.getIndex(), new TaxonNameEditor(this),
+                    getEditorInput());
+            // setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
+
+            // TODO lazy create
+            // addPage(Page.DESCRIPTIVE.getIndex(), new
+            // TaxonDescriptionTreeEditor(this), getEditorInput());
+            // setPageText(Page.DESCRIPTIVE.getIndex(),
+            // Page.DESCRIPTIVE.getTitle());
+
+            // EditorUtil.showPropertySheet();
+
+        } catch (PartInitException e) {
+            MessagingUtils.error(getClass(), e);
+        }
+    }
+
     /**
-     * Calls <code>MultiPageEditorPart.setPartName(String partName)</code>
-     *  with text appropriate to the state of the taxon: any taxon that has
-     *  been saved will by necessity have a name to display; a new taxon
-     *  should display "New taxon" in the editor tab.
+     * {@inheritDoc}
+     */
+    @Override
+    protected void pageChange(int newPageIndex) {
+        if(getCurrentPage()==-1){
+            return;
+        }
+        super.pageChange(newPageIndex);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void doSave(IProgressMonitor monitor) {
+        monitor.beginTask(Messages.MultiPageTaxonEditor_SAVING_EDITOR, 4);
+        try {
+            if (!conversation.isBound()) {
+                conversation.bind();
+            }
+            monitor.worked(1);
+
+            for (IEditorPart editorPage : getPages()) {
+                if (editorPage instanceof TaxonNameEditor) {
+                    if (((TaxonNameEditor) editorPage).checkForEmptyNames()) {
+                        MessageDialog.openWarning(AbstractUtility.getShell(), Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED,
+                                Messages.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE);
+                        return;
+                    }
+                }
+
+                editorPage.doSave(monitor);
+                monitor.worked(1);
+            }
+
+            // commit the conversation and start a new transaction immediately
+
+            input.merge();
+
+            conversation.commit(true);
+            CdmApplicationState.getCurrentDataChangeService()
+            .fireChangeEvent(new CdmChangeEvent(Action.Update, input.getTaxonNode() , MultiPageTaxonEditor.class), true);
+            monitor.worked(1);
+
+            this.setDirty(false);
+            monitor.worked(1);
+        } catch (Exception e) {
+            setFocus();
+            MessagingUtils.operationDialog(this, e, TaxeditorEditorPlugin.PLUGIN_ID,Messages.MultiPageTaxonEditor_SAVING_TAXON, Messages.MultiPageTaxonEditor_SAVING_TAXON_MESSAGE);
+            disableEditor(true);
+        } finally {
+            monitor.done();
+        }
+    }
+
+    private void disableEditor(boolean isOnError) {
+        for (IMultiPageTaxonEditorPage editorPage : getPages()) {
+            if(isOnError){
+                editorPage.setOnError();
+            }else {
+                editorPage.setDisabled();
+            }
+        }
+
+        conversation.unregisterForDataStoreChanges(this);
+        conversation.close();
+        setDirty(false);
+    }
+
+    private void setDirty(boolean dirty) {
+        this.dirty = dirty;
+        firePropertyChange(PROP_DIRTY);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
+     */
+    /**
+     * <p>
+     * isDirty
+     * </p>
+     *
+     * @return a boolean.
+     */
+    @Override
+    public boolean isDirty() {
+        return dirty;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
+     */
+    /** {@inheritDoc} */
+    @Override
+    public void editorDirtyStateChanged() {
+        dirty = true;
+        super.editorDirtyStateChanged();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Checks whether nested editors are calling
+     * <code>firePropertyChange(PROP_DIRTY)</code> to signal an edit has taken
+     * place before passing property change along to
+     * <code>super.handlePropertyChange(int propertyId)</code>.
+     */
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
+     */
+    @Override
+    protected void handlePropertyChange(int propertyId) {
+        if (propertyId == PROP_DIRTY) {
+            setDirty(true);
+        }
+        super.handlePropertyChange(propertyId);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void doSaveAs() {
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isSaveAsAllowed() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void init(IEditorSite site, IEditorInput input)
+            throws PartInitException {
+
+        if (!(input instanceof TaxonEditorInput)) {
+            throw new PartInitException(
+                    Messages.MultiPageTaxonEditor_INVALID_INPUT);
+        }
+
+        this.input = (TaxonEditorInput) input;
+
+
+        // try {
+        // // Listen for name changes,
+        // // change tab for this taxon editor accordingly
+        // getTaxon().addPropertyChangeListener("name",
+        // new PropertyChangeListener() {
+        // public void propertyChange(PropertyChangeEvent e) {
+        // setPartName();
+        // }
+        // });
+        // } catch (NullPointerException e) {
+        // EditorUtil.warn(getClass(),
+        // "Caught an NPE while initing an editor. This is most " +
+        // "likely due to the unsuccesful attempt to restore the former " +
+        // "state of the application. We ignore this because the workbench " +
+        // "will simply be reset.");
+        // }
+        setPartName();
+
+        super.init(site, input);
+    }
+
+    /**
+     * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
+     * text appropriate to the state of the taxon: any taxon that has been saved
+     * will by necessity have a name to display; a new taxon should display
+     * "New taxon" in the editor tab.
      */
     protected void setPartName() {
-        
-       String partName = null;
-       TaxonNameBase<?, ?> name = getTaxon().getName();
-       
-       if (name != null) {
-               partName = name.getTitleCache();
-       }
-       
-       if (partName == null || partName.equals("")) {
-               partName = ("New taxon");
-       }
+
+        String partName = null;
+        TaxonNameBase<?, ?> name = getTaxon().getName();
+
+        if (name != null) {
+            partName = name.getTitleCache();
+        }
+
+        if (partName == null || partName.equals("")) { //$NON-NLS-1$
+            partName = (Messages.MultiPageTaxonEditor_NEW_TAXON);
+        }
 
         setPartName(partName);
     }
-    
+
     /**
      * {@inheritDoc}
      *
-     * Editor pages call this in their postOperation to notify the MultiPageTaxonEditor
-     * of unsaved changes
+     * Editor pages call this in their postOperation to notify the
+     * MultiPageTaxonEditor of unsaved changes
      */
+    @Override
     public void changed(Object element) {
-//     setDirty(true);
-               dirty = true;
-               super.editorDirtyStateChanged();
-               if(element instanceof TaxonBase){
-                       TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
-                       AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
-                       if(container != null){
-                               container.refresh();
-                       }
-               }
-    }
-    
+        // setDirty(true);
+        // 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
+        if (element != null){
+            dirty = true;
+            super.editorDirtyStateChanged();
+        }
+
+        if (element instanceof TaxonBase) {
+            TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
+            AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
+            if (container != null) {
+                container.refresh();
+            }
+        }
+        //refresh part title
+        //TODO: refresh taxon node in taxon navigator
+        setPartName();
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
+     */
+    @Override
+    public void forceDirty() {
+        changed(null);
+    }
+
     /**
      * The accepted taxon that is the input for this editor
      *
      * @return the accepted taxon
      */
-    public Taxon getTaxon(){
-       return input.getTaxon();
+    public Taxon getTaxon() {
+        return input.getTaxon();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
+     * ()
+     */
+    /**
+     * <p>
+     * getConversationHolder
+     * </p>
+     *
+     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
+     *         object.
+     */
+    @Override
+    public ConversationHolder getConversationHolder() {
+        return conversation;
+    }
+
+    /**
+     * <p>
+     * setConversationHolder
+     * </p>
+     *
+     * @param conversation
+     *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
+     *            object.
+     */
+    public void setConversationHolder(ConversationHolder conversation) {
+        this.conversation = conversation;
+    }
+
+    /**
+     * <p>
+     * Getter for the field <code>undoContext</code>.
+     * </p>
+     *
+     * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
+     *         object.
+     */
+    public IUndoContext getUndoContext() {
+        return undoContext;
+    }
+
+    /**
+     * <p>
+     * Setter for the field <code>undoContext</code>.
+     * </p>
+     *
+     * @param undoContext
+     *            a {@link org.eclipse.core.commands.operations.IUndoContext}
+     *            object.
+     */
+    public void setUndoContext(IUndoContext undoContext) {
+        this.undoContext = undoContext;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setFocus() {
+        // logger.warn("Setting focus to editor");
+        // bind the conversation
+        getConversationHolder().bind();
+        input.bind();
+        // pass focus to the active editor page
+        getActiveEditor().setFocus();
     }
 
     /*
      * (non-Javadoc)
-     * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
+     *
+     * @see
+     * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
+     * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
      */
-       /**
-        * <p>getConversationHolder</p>
-        *
-        * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
-        */
-       public ConversationHolder getConversationHolder() {
-               return conversation;
-       }
-       
-       /**
-        * <p>setConversationHolder</p>
-        *
-        * @param conversation a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
-        */
-       public void setConversationHolder(ConversationHolder conversation){
-               this.conversation = conversation;
-       }
-
-
-       /**
-        * <p>Getter for the field <code>undoContext</code>.</p>
-        *
-        * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
-        */
-       public IUndoContext getUndoContext() {
-               return undoContext;
-       }
-
-       /**
-        * <p>Setter for the field <code>undoContext</code>.</p>
-        *
-        * @param undoContext a {@link org.eclipse.core.commands.operations.IUndoContext} object.
-        */
-       public void setUndoContext(IUndoContext undoContext) {
-               this.undoContext = undoContext;
-       }
-       
-       /** {@inheritDoc} */
-       @Override
-       public void setFocus(){
-               //logger.warn("Setting focus to editor");
-               // bind the conversation
-               getConversationHolder().bind();
-               // pass focus to the active editor page
-               getActiveEditor().setFocus();
-       }
-
-       /*
-        * (non-Javadoc)
-        * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
-        */
-       /** {@inheritDoc} */
-       public void update(CdmDataChangeMap events) {
-               if(dataChangeBehavior == null){
-                       dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
-               }
-               
-               DataChangeBridge.handleDataChange(events, dataChangeBehavior);
-       }
-
-
-       /*
-        * (non-Javadoc)
-        * @see eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation()
-        */
-       /** {@inheritDoc} */
-       public boolean postOperation(CdmBase objectAffectedByOperation) {
-               setDirty(true);
-               
-               for(IEditorPart editor : this.getPages()){
-                       if (editor instanceof IPostOperationEnabled) {
-                               ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
-                       } else {
-                               EditorUtil.warn(getClass(), "postOperation not enabled for editor " + editor);
-                       }
-               }
-               EditorUtil.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
-               
-               return false;
-       }
-       
-       /**
-        * Returns an <code>IEditorPart</code> implementation by type
-        *
-        * @param page the page type
-        * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage} object.
-        */
-       public IMultiPageTaxonEditorPage getPage(Page page){
-               for(IEditorPart editor : this.getPages()){
-                       if(editor.getClass().equals(page.getClazz())){
-                               return (IMultiPageTaxonEditorPage) editor;
-                       }
-               }
-               return null;
-       }
-       
-       /**
-        * Return a list of <code>AbstractTaxonEditor</code>s registered with this
-        * <code>MultiPageTaxonEditor</code>.
-        *
-        * @return a {@link java.util.List} object.
-        */
-       public List<IMultiPageTaxonEditorPage> getPages(){
-               ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
-               for(int i = 0; i < this.getPageCount(); i++){
-                       
-                       editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
-               }
-               return editors;
-       }
-       
-       /**
-        * Refreshes a certain page of the MultipageTaxonEditor
-        *
-        * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
-        * @return a boolean.
-        */
-       public boolean redraw(Page page){
-               return redraw(page, true);
-       }
-       
-       /**
-        * Refreshes a certain page of the MultipageTaxonEditor and
-        * sets focus to that page
-        *
-        * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
-        * @param focus a boolean.
-        * @return a boolean.
-        */
-       public boolean redraw(Page page, boolean focus){
-               IMultiPageTaxonEditorPage editorPage = getPage(page);
-               return editorPage != null && editorPage.redraw(focus);
-       }
-
-       /**
-        * <p>onComplete</p>
-        *
-        * @return a boolean.
-        */
-       public boolean onComplete() {
-               return false;
-       }
-
-       /**
-        * Reloads the data for this 
-        */
-       public void reload() {
-               if(isDirty()){
-                       EditorUtil.warningDialog("Editor has unsaved data", getClass(), "This editor can not be " +
-                                       "refreshed because it contains unsaved data. Refreshing " +
-                                       "this editor would discard the changes. Please save this editor, " +
-                                       "close and reopen it manually in order to get the latest content");
-               }else{
-                       TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
-                       
-                       UUID uuid = input.getTaxonNode().getUuid();
-                       
-                       conversation.clear();
-                       
-                       try {
-                               TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
-                               setInput(newInput);
-                               for(IMultiPageTaxonEditorPage editorPart : getPages()){
-                                       editorPart.redraw();
-                               }
-                       } catch (Exception e) {
-                               EditorUtil.errorDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e);
-                       }
-               }
-       }
+    /** {@inheritDoc} */
+    @Override
+    public void update(CdmDataChangeMap events) {
+        if (dataChangeBehavior == null) {
+            dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
+        }
+
+        DataChangeBridge.handleDataChange(events, dataChangeBehavior);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
+     * ()
+     */
+    /** {@inheritDoc} */
+    @Override
+    public boolean postOperation(CdmBase objectAffectedByOperation) {
+               setDirty(true);
+
+        for (IEditorPart editor : this.getPages()) {
+            if (editor instanceof IPostOperationEnabled) {
+                ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
+            } else {
+                MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_NOT_ENABLED + editor);
+            }
+        }
+        MessagingUtils.warn(getClass(), Messages.MultiPageTaxonEditor_POST_OP_CALLED);
+
+        return false;
+    }
+
+    /**
+     * Returns an <code>IEditorPart</code> implementation by type
+     *
+     * @param page
+     *            the page type
+     * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
+     *         object.
+     */
+    public IMultiPageTaxonEditorPage getPage(Page page) {
+        for (IEditorPart editor : this.getPages()) {
+            if (editor.getClass().equals(page.getClazz())) {
+                return (IMultiPageTaxonEditorPage) editor;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return a list of <code>AbstractTaxonEditor</code>s registered with this
+     * <code>MultiPageTaxonEditor</code>.
+     *
+     * @return a {@link java.util.List} object.
+     */
+    public List<IMultiPageTaxonEditorPage> getPages() {
+        ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
+        for (int i = 0; i < this.getPageCount(); i++) {
+
+            editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
+        }
+        return editors;
+    }
+
+    /**
+     * Refreshes a certain page of the MultipageTaxonEditor
+     *
+     * @param page
+     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
+     * @return a boolean.
+     */
+    public boolean redraw(Page page) {
+        return redraw(page, true);
+    }
+
+    /**
+     * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
+     * that page
+     *
+     * @param page
+     *            a {@link eu.etaxonomy.taxeditor.editor.Page} object.
+     * @param focus
+     *            a boolean.
+     * @return a boolean.
+     */
+    public boolean redraw(Page page, boolean focus) {
+        IMultiPageTaxonEditorPage editorPage = getPage(page);
+        return editorPage != null && editorPage.redraw(focus);
+    }
+
+    /**
+     * <p>
+     * onComplete
+     * </p>
+     *
+     * @return a boolean.
+     */
+    @Override
+    public boolean onComplete() {
+        return false;
+    }
+
+    /**
+     * Reloads the data for this
+     */
+    public void reload() {
+        if (isDirty()) {
+            MessagingUtils.warningDialog(Messages.MultiPageTaxonEditor_UNSAVED_DATA, getClass(), Messages.MultiPageTaxonEditor_UNSAVED_DATA_MESSAGE);
+        } else {
+            TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
+
+            UUID uuid = input.getTaxonNode().getUuid();
+
+            conversation.clear();
+
+            try {
+                TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
+                setInput(newInput);
+                for (IMultiPageTaxonEditorPage editorPart : getPages()) {
+                    editorPart.redraw();
+                }
+            } catch (Exception e) {
+                MessagingUtils.messageDialog(Messages.MultiPageTaxonEditor_REFRESH_ERROR, getClass(), Messages.MultiPageTaxonEditor_REFRESH_ERROR_MESSAGE, e);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput()); //$NON-NLS-1$
+    }
+
+    @Override
+    public boolean permissionsSatisfied() {
+        IEditorPart activeEditor = getActiveEditor();
+        if(activeEditor != null && ISecuredEditor.class.isAssignableFrom(activeEditor.getClass())){
+            return ((ISecuredEditor)activeEditor).permissionsSatisfied();
+        }
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.model.IPartContentHasMedia#canAttachMedia()
+     */
+    @Override
+    public boolean canAttachMedia() {
+        return true;
+    }
+
 }