es.cv.gvcase.mdt.common.part.MOSKittMultiPageEditor.java Source code

Java tutorial

Introduction

Here is the source code for es.cv.gvcase.mdt.common.part.MOSKittMultiPageEditor.java

Source

/*******************************************************************************
 * Copyright (c) 2009 Conselleria de Infraestructuras y Transporte, Generalitat 
 * de la Comunitat Valenciana . All rights reserved. This program
 * and the accompanying materials are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: Francisco Javier Cano Muoz (Prodevelop)  Initial implementation
 *              Marc Gil Sendra (Prodevelop) - Add image to the page
 *
 ******************************************************************************/
package es.cv.gvcase.mdt.common.part;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.ui.URIEditorInput;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.transaction.ResourceSetChangeEvent;
import org.eclipse.emf.transaction.ResourceSetListener;
import org.eclipse.emf.transaction.ResourceSetListenerImpl;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gmf.runtime.common.ui.action.actions.global.GlobalRedoAction;
import org.eclipse.gmf.runtime.common.ui.action.actions.global.GlobalUndoAction;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditDomain;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.LabelRetargetAction;
import org.eclipse.ui.internal.EditorActionBars;
import org.eclipse.ui.internal.EditorSite;
import org.eclipse.ui.operations.RedoActionHandler;
import org.eclipse.ui.operations.UndoActionHandler;
import org.eclipse.ui.views.contentoutline.ContentOutline;

import es.cv.gvcase.emf.common.part.EditingDomainRegistry;
import es.cv.gvcase.emf.common.util.PathsUtil;
import es.cv.gvcase.mdt.common.Activator;
import es.cv.gvcase.mdt.common.ids.MOSKittEditorIDs;
import es.cv.gvcase.mdt.common.internal.Messages;
import es.cv.gvcase.mdt.common.migrations.DiagramMigrationRegistry;
import es.cv.gvcase.mdt.common.migrations.MigratorService;
import es.cv.gvcase.mdt.common.migrations.MigratorVersionComparator;
import es.cv.gvcase.mdt.common.preferences.MOSKittPreferenceConstants;
import es.cv.gvcase.mdt.common.provider.IMOSKittEditorFactory;
import es.cv.gvcase.mdt.common.provider.MOSKittEditorFactoryRegistry;
import es.cv.gvcase.mdt.common.runnable.HookRunner;
import es.cv.gvcase.mdt.common.storage.store.IStorageApplicable;
import es.cv.gvcase.mdt.common.util.DiagramEditPartsUtil;
import es.cv.gvcase.mdt.common.util.MDTUtil;
import es.cv.gvcase.mdt.common.util.MultiDiagramUtil;

/**
 * A MultiPage editor for MOSKitt editors. <br>
 * It can hold diagram editors based on GMF. By default it will open all
 * diagrams in the given {@link IEditorInput}, each in a different page.
 * Creating or removing {@link Diagram}s from the {@link ResourceSet} makes
 * pages in the editor to be added or removed.
 * 
 * @author <a href="mailto:fjcano@prodevelop.es">Francisco Javier Cano Muoz</a>
 * 
 */
public class MOSKittMultiPageEditor extends MultiPageEditorPart implements IPartListener2, IDiagramWorkbenchPart,
        ISaveablePart2, es.cv.gvcase.emf.common.part.IEditingDomainRegistrable {

    /**
     * Added an identifier for the MOSKittMultiPageEditor
     */
    public static final String MOSKittMultiPageEditorID = "es.cv.gvcase.mdt.common.EditorSite.SharedIdentifier"; //$NON-NLS-1$

    // // context for this MultiPageEditor. It controls transactional editing
    // domains and documents providers.
    IMOSKittMultiPageEditorContext multiPageEditorContext = null;

    // EditPart that is being created in addPageForElement()
    IEditorPart creatingEditorPart = null;

    private boolean migrated = false;

    /**
     * Retrieves the main resource that contains the diagrams this editor is
     * editing.
     * 
     * @return
     */
    public Resource getMainDiagramResource() {
        IEditorInput input = getEditorInput();
        TransactionalEditingDomain domain = getMultiPageEditorContext().getEditingDomain();
        if (input != null && domain != null) {
            String uriString = es.cv.gvcase.emf.common.util.PathsUtil.fromEditorInputToURIString(input);
            URI inputURI = URI.createURI(uriString);
            return domain.getResourceSet().getResource(inputURI, false);
        }
        return null;
    }

    protected IMOSKittMultiPageEditorContext getMultiPageEditorContext() {
        return multiPageEditorContext;
    }

    protected void setMultiPageEditorContext(IMOSKittMultiPageEditorContext multiPageEditorContext) {
        this.multiPageEditorContext = multiPageEditorContext;
    }

    // // Map of editor input to editor index
    Map<EObject, Integer> mapEditorInput2EditorIndex = new HashMap<EObject, Integer>();

    public Map<EObject, Integer> getMapEditorInput2EditorIndex() {
        if (mapEditorInput2EditorIndex == null) {
            mapEditorInput2EditorIndex = new HashMap<EObject, Integer>();
        }
        return mapEditorInput2EditorIndex;
    }

    /**
     * Creates a page for each different {@link Diagram} that is in the given
     * {@link IEditorInput}.
     */
    @Override
    protected void createPages() {
        // add a listener to the TabFolder so that the window title is updated
        addTabFolderListeners();
        // 1 - get input
        // 2 - get root elements to be opened from input
        // 3 - search IMOSKittEditorFactories
        // 4 - for each root element that has an IMOSKittEditorFactory
        // 4.1 - create an IEditorPart
        // 4.2 - add a page for that IEditorPart
        addPagesForInput(getEditorInput());
        // review that the mapping from editor input to index is correct
        // this has to be done because the EObjects that are originally read are
        // not in the same ResourceSet as the ones that the editors are really
        // editing
        reviewEObjectsInEditors();
        // listen to changes (adding/removing diagrams) in the ResourceSet so
        // that the pages in this multi tab editor are updated correctly.
        addDiagramsListener();
    }

    protected void addTabFolderListeners() {
        if (getTabFolder() != null) {
            getTabFolder().addSelectionListener(createTabSelectionListener());
        }
    }

    protected SelectionListener tabSelectedListener = null;

    protected SelectionListener createTabSelectionListener() {
        if (tabSelectedListener == null) {
            tabSelectedListener = new SelectionListener() {

                public void widgetSelected(SelectionEvent e) {
                    // update the title of the editor
                    if (e.item != null && e.item.getData() instanceof CachedResourcesDiagramEditor) {
                        CachedResourcesDiagramEditor diagrameditor = (CachedResourcesDiagramEditor) e.item
                                .getData();
                        updateEditorTitle(diagrameditor);
                        //
                        setUndoContextForUndoAction();
                        setUndoContextForRedoAction();
                    }
                }

                public void widgetDefaultSelected(SelectionEvent e) {
                }
            };
        }
        return tabSelectedListener;
    }

    protected void updateEditorTitle(IEditorPart editorPart) {
        if (editorPart instanceof CachedResourcesDiagramEditor) {
            // update this part's text
            CachedResourcesDiagramEditor diagramEditor = (CachedResourcesDiagramEditor) editorPart;
            Diagram diagram = diagramEditor.getDiagram();
            String type = diagram.getType();
            if (MOSKittEditorIDs.getExtensionsMapModelToLabel().containsKey(type)) {
                String label = MOSKittEditorIDs.getExtensionsMapModelToLabel().get(type);
                setPartName(buildPartLabel(label));
            }
            // update this part's image
            // set image of the title. The image is the one that the label
            // provider provides for the given eObject (in this case the
            // element of the diagram)
            Image titleImage = getLabelProvider().getImage(diagram.getElement());
            setTitleImage(titleImage);
        }
    }

    protected String buildPartLabel(String editorLabel) {
        if (editorLabel != null) {
            return editorLabel + Messages.MOSKittMultiPageEditor_1;
        }
        return Messages.MOSKittMultiPageEditor_2;
    }

    /**
     * Adds a listener that listens to the creation or destruction of
     * {@link Diagram}s in the {@link ResourceSet} and adds or removes pages in
     * the editor accordingly.
     * 
     */
    protected void addDiagramsListener() {
        if (getMultiPageEditorContext() != null) {
            TransactionalEditingDomain domain = getMultiPageEditorContext().getEditingDomain();
            if (domain != null) {
                domain.addResourceSetListener(createListenerForDiagrams());
            }
        }
    }

    /**
     * Adds the initial pages for the given {@link IEditorInput}. <br>
     * Tries to retrieve a list of the last open diagrams and restore only
     * those.
     * 
     * @param editorInput
     */
    protected void addPagesForInput(IEditorInput editorInput) {
        if (editorInput != null) {
            try {
                List<EObject> rootEObjects = MultiDiagramUtil.getOpenDiagrams(editorInput);
                if (rootEObjects == null || rootEObjects.size() <= 0) {
                    List<EObject> rootElements = MDTUtil.getRootElementsFromFile(editorInput);
                    if (rootElements != null && rootElements.size() >= 1) {
                        removeAllExceptFirstDiagram(rootElements);
                        rootEObjects = rootElements;
                    }
                }
                if (rootEObjects == null || rootEObjects.size() <= 0) {
                    addEmptyPage();
                }
                addPagesForElements(rootEObjects);
            } catch (PartInitException ex) {
                Activator.getDefault().logError(Messages.MOSKittMultiPageEditor_3, ex);
                addErrorPage(ex.getMessage());
            }
        }
    }

    /**
     * Remove all {@link EObject}s except the first {@link Diagram}.
     * 
     * @param eObjects
     */
    protected void removeAllExceptFirstDiagram(List<EObject> eObjects) {
        List<EObject> toRemove = new ArrayList<EObject>();
        Diagram diagram = null;
        for (EObject eObject : eObjects) {
            if (diagram != null) {
                toRemove.add(eObject);
            } else if (eObject != null) {
                diagram = (Diagram) Platform.getAdapterManager().getAdapter(eObject, Diagram.class);
                if (diagram == null) {
                    toRemove.add(eObject);
                }
            }
        }
        eObjects.removeAll(toRemove);
    }

    /**
     * A default empty page for when there is no other page for a
     * {@link Diagram} or other {@link EObject} to show.
     */
    protected void addEmptyPage() {
        Label label = new Label(getTabFolder(), SWT.BORDER);
        label.setText(Messages.MOSKittMultiPageEditor_4);
        addPage(label);
    }

    /**
     * A default empty page for when there is no other page for a
     * {@link Diagram} or other {@link EObject} to show.
     */
    protected void addErrorPage(String errorMessage) {
        Label label = new Label(getTabFolder(), SWT.BORDER);
        label.setText(MessageFormat.format(Messages.MOSKittMultiPageEditor_5,
                (errorMessage == null ? errorMessage : ""))); //$NON-NLS-1$
        addPage(label);
    }

    /**
     * Adds a page for each of the given {@link EObject}s.
     * 
     * @param rootEObjects
     */
    protected void addPagesForElements(List<EObject> rootEObjects) throws PartInitException {
        for (EObject eObject : rootEObjects) {
            addPageForElement(eObject);
        }
    }

    /**
     * Adds a page for the given {@link EObject}. <br>
     * To add a page for this EObject an {@link IMOSKittEditorFactory} must
     * exist that can handle this type of EObject.
     * 
     * @param eObject
     * @return
     */
    protected int addPageForElement(EObject eObject) throws PartInitException {
        // try to get an editor that can handle this EObejct.
        IEditorPart editorPart = MOSKittEditorFactoryRegistry.getInstance().getEditorFor(eObject);
        // store the recently created editor part
        creatingEditorPart = editorPart;

        if (editorPart != null) {
            // if an editor for this kind of EObject exists, create a page for
            // it, with its IEditorInput pointing to this EObject via an
            // URIEditorInput.
            IEditorInput input = createEditorInputFor(eObject);
            try {
                // add the page
                int index = addPage(editorPart, input);
                if (index >= 0) {
                    // set this editor part title
                    updateEditorTitle(editorPart);
                    // set text of the tab
                    setPageText(index, MDTUtil.getObjectNameOrEmptyString(eObject));

                    // set image of the tab. The image is the one that the label
                    // provider provides for the given eObject (in this case the
                    // element of the diagram)
                    if (eObject instanceof Diagram && ((Diagram) eObject).getElement() != null) {
                        setPageImage(index, getLabelProvider().getImage(((Diagram) eObject).getElement()));
                    }

                    // add this editor's index to the mapping between editor
                    // inputs and editor indexes.
                    getMapEditorInput2EditorIndex().put(eObject, index);
                    //
                    updateUndoContextForActions();
                }
                return index;
            } catch (PartInitException ex) {
                // something went wrong, log it.
                Activator.getDefault().logError(MessageFormat.format(Messages.MOSKittMultiPageEditor_7, eObject),
                        ex);
                // the editing domain may need removal
                cleanUpEditingDomain();
                throw ex;
            } catch (NullPointerException ex) {
                // something went wrong, log it.
                Activator.getDefault().logError(MessageFormat.format(Messages.MOSKittMultiPageEditor_8, eObject),
                        ex);
                // the editing domain may need removal
                cleanUpEditingDomain();
                throw new PartInitException(MessageFormat.format(Messages.MOSKittMultiPageEditor_9, eObject));
            }
        }
        // we can't handle this kind of EObject.
        return -1;
    }

    /**
     * Asks the editing domain registry for an editing domain clean up in case
     * it is needed:
     */
    protected void cleanUpEditingDomain() {
        // remove the editing domain in case it has been created
        if (getEditors().size() <= 0) {
            EditingDomainRegistry.getInstance().cleanRegistry(getSite().getPage());
        }
    }

    @Override
    public int addPage(IEditorPart editor, IEditorInput input) throws PartInitException {
        int addedIndex = -1;
        try {
            // add the page
            addedIndex = super.addPage(editor, input);
            // notify the actionbar contributor of the new active page
        } catch (PartInitException ex) {
            // set an invalid index
            addedIndex = -1;
            // remove the editing domain in case it has been created
            cleanUpEditingDomain();
        }
        // return the added index
        return addedIndex;
    }

    /**
     * Returns a set of all the labelProviders registered in the system. Only
     * one of them if used to return the text and image for the given object
     */
    protected ILabelProvider getLabelProvider() {
        return MDTUtil.getLabelProvider();
    }

    /**
     * Create a {@link CTabItem} with a special {@link CTabItem#dispose()} that
     * 1) prevents the tab from closing if its the last open tab and 2) when the
     * tab is disposed a reordering of the mapping of editor input to editor
     * index is performed.
     */
    @Override
    protected CTabItem createItem(int index, Control control) {
        CTabItem item = new CTabItem(getTabFolder(), SWT.CLOSE, index) {
            @Override
            public void dispose() {
                if (getPageCount() == 1) {
                    // if there is only one page it can not be closed.
                    return;
                }
                // get index
                int index = getParent().indexOf(this);
                if (index == 0) {
                    // never allow the first tab to be closed
                    return;
                }
                // if the control is an EditorPart, deactivate all edit parts in
                // that editor
                if (getData() instanceof IDiagramWorkbenchPart) {
                    EditPart rootEditPart = ((IDiagramWorkbenchPart) getData()).getDiagramEditPart();
                    if (rootEditPart != null) {
                        rootEditPart.deactivate();
                    }
                }
                // do normal dispose()
                super.dispose();
                // reorder, if all went well.
                if (index >= 0) {
                    reorderMapEditorInput2EditorIndex(index);
                }
            }
        };
        item.setControl(control);
        return item;
    }

    /**
     * When removing a page we must check if it was from one editor and update
     * the mapping of editor input to editor index.
     */
    @Override
    public void removePage(int pageIndex) {
        super.removePage(pageIndex);
        // Update mapping of editor input to page index when a page is removed.
        // after removing a page we will store the currently open diagrams.
        MultiDiagramUtil.storeOpenDiagrams(getDiagramInputs());
    }

    /**
     * Forces a reordering of the mapping of editor input to editor index.
     * Usually because a page was closed. <br>
     * 
     * @param removedIndex
     */
    protected void reorderMapEditorInput2EditorIndex(int removedIndex) {
        // Update mapping of editor input to page index when a page is removed.
        // All indexes higher than the one removed must be taken 1.
        EObject toRemove = null;
        for (Entry<EObject, Integer> entry : getMapEditorInput2EditorIndex().entrySet()) {
            if (entry.getValue() != null && entry.getValue() == removedIndex) {
                toRemove = entry.getKey();
            }
            if (entry.getValue() != null && entry.getValue() > removedIndex) {
                entry.setValue(entry.getValue() - 1);
            }
        }
        if (toRemove != null) {
            getMapEditorInput2EditorIndex().remove(toRemove);
        }
    }

    /**
     * Reviews the diagrams being edited with those in the editor input to
     * editor index mapping and updates the entries in the mapping with the
     * correct keys. This must be done as some EObjects are initially loaded in
     * different ResourceSets than the ones in which they are finally edited by
     * their editors and being in different ResourceSets makes them return false
     * when compared with #equals().
     * 
     */
    protected void reviewEObjectsInEditors() {
        Diagram diagram = null;
        List<EObject> toRemove = new ArrayList<EObject>();
        Map<EObject, Integer> toAdd = new HashMap<EObject, Integer>();
        // review every open editor.
        for (IEditorPart editorPart : getEditors()) {
            // get the Diagram being edited in that editor.
            diagram = (Diagram) editorPart.getAdapter(Diagram.class);
            if (diagram != null) {
                // we will compare via URI fragments.
                String oneFragment = diagram.eResource().getURIFragment(diagram);
                for (EObject eObject : getMapEditorInput2EditorIndex().keySet()) {
                    String otherFragment = eObject.eResource().getURIFragment(eObject);
                    if (otherFragment != null && otherFragment.equals(oneFragment)) {
                        // objects to be removed
                        toRemove.add(eObject);
                        // entries to add
                        toAdd.put(diagram, getMapEditorInput2EditorIndex().get(eObject));
                    }
                }
            }
        }
        // remove some entries
        for (EObject eObject : toRemove) {
            getMapEditorInput2EditorIndex().remove(eObject);
        }
        // add some entries.
        getMapEditorInput2EditorIndex().putAll(toAdd);
    }

    /**
     * Create an {@link IEditorInput} that points to the given {@link EObject}.
     * 
     * @param eObject
     * @return
     */
    protected IEditorInput createEditorInputFor(EObject eObject) {
        if (eObject == null || eObject.eResource() == null) {
            return null;
        }
        String uriPath = URI.decode(eObject.eResource().getURI().toString());
        uriPath = PathsUtil.fromAbsoluteFileSystemToAbsoluteWorkspace(uriPath, false);
        URI tempURI = URI.createURI(uriPath);
        URI uri = tempURI.appendFragment(eObject.eResource().getURIFragment(eObject));
        // the IEditorInput is an URIEditorInput that points to the given
        // EObject via URI fragments. If it has been migrated, it is a
        // CachedResourcesEditorInput
        IEditorInput input = null;
        input = new CachedResourcesEditorInput(uri);
        ((CachedResourcesEditorInput) input).setMigrated(migrated);
        return input;
    }

    /**
     * Adds the underlying model {@link EObject}s of the {@link Diagram}s in the
     * list.
     * 
     * @param rootEObjects
     */
    protected void addDiagramModelFiles(List<EObject> rootEObjects) {
        if (rootEObjects == null) {
            return;
        }
        Diagram diagram = null;
        EObject root = null;
        List<EObject> toAdd = new ArrayList<EObject>();
        for (EObject eObject : rootEObjects) {
            diagram = (Diagram) Platform.getAdapterManager().getAdapter(eObject, Diagram.class);
            if (diagram != null) {
                root = diagram.getElement();
                if (!toAdd.contains(root)) {
                    toAdd.add(root);
                }
            }
        }
        for (EObject eObject : toAdd) {
            if (!rootEObjects.contains(eObject)) {
                rootEObjects.add(eObject);
            }
        }
    }

    /**
     * Saving is delegated to each dirty nested {@link IEditorPart}.
     */
    @Override
    public void doSave(IProgressMonitor monitor) {
        IEditorPart editor = null;
        int saveNeeded = ISaveablePart2.DEFAULT;
        for (int i = 0; i < getPageCount(); i++) {
            editor = getEditor(i);
            // an editor must be dirty to be saved
            if (editor != null && editor.isDirty()) {
                // check the save option given by the user in the
                // propmtToSaveOnClose()
                if (mapEditorIndex2SaveOnClose.containsKey(i)) {
                    saveNeeded = mapEditorIndex2SaveOnClose.get(i);
                } else {
                    saveNeeded = ISaveablePart2.YES;
                }
                if (saveNeeded == ISaveablePart2.YES || saveNeeded == ISaveablePart2.DEFAULT) {
                    // if the save option is YEs or DEFAULT, the editor's
                    // contents need to be saved
                    editor.doSave(monitor);
                }
            }
        }
        // we store the open diagrams in each save operation.
        MultiDiagramUtil.storeOpenDiagrams(getDiagramInputs());
    }

    /**
     * Save as is delegated to the currently active {@link IEditorPart}.
     */
    @Override
    public void doSaveAs() {
        IEditorPart editor = getActiveEditor();
        if (editor != null) {
            editor.doSaveAs();
        }
    }

    /**
     * Is save as allowed is delegated to the currently active editor.
     */
    @Override
    public boolean isSaveAsAllowed() {
        IEditorPart editor = getActiveEditor();
        if (editor != null) {
            return editor.isSaveAsAllowed();
        }
        return false;
    }

    // add - remove Diagrams and EObjects pages

    /**
     * Opens a page for the given {@link EObject}, with the proper
     * {@link IEditorPart} (if one exists). If the given EObject is already
     * being edited, the page with the editor editing it will be given focus.
     */
    public boolean openPageForEObject(EObject eObject) {
        try {
            if (eObject != null) {
                int existingEditor = searchPageEditingEObject(eObject);
                if (existingEditor >= 0) {
                    // if there is a page that has an editor that is editing the
                    // element to open, set focus in that page.
                    setActivePage(existingEditor);
                    return true;
                } else {
                    try {
                        // otherwise, create an editor and a page for it.
                        int index = addPageForElement(eObject);
                        if (index >= 0) {
                            setActivePage(index);
                            return true;
                        }
                    } catch (PartInitException ex) {
                        Activator.getDefault()
                                .logError(MessageFormat.format(Messages.MOSKittMultiPageEditor_10, eObject), ex);
                        addErrorPage(ex.getMessage());
                    }
                }
            }
            return false;
        } finally {
            // always revise that the maping between editor input and editor
            // index is correct.
            reviewEObjectsInEditors();
            // the pages that are open have changed, store them
            MultiDiagramUtil.storeOpenDiagrams(getDiagramInputs());
        }
    }

    /**
     * Closes the page that has an {@link IEditorPart} that is editing the given
     * {@link EObject}.
     * 
     * @param eObject
     * @return
     */
    public boolean closePageForEObject(EObject eObject) {
        try {
            int pageCount = getPageCount();
            if (pageCount <= 1) {
                return false;
            }
            // close the page
            return closeExistingPageForEObject(eObject);
        } finally {
            // always make sure that the mapping between editor input and editor
            // index is correct.
            reviewEObjectsInEditors();
            // the pages that are open have changed, store them.
            MultiDiagramUtil.storeOpenDiagrams(getDiagramInputs());
        }
    }

    protected boolean closeExistingPageForEObject(EObject eObject) {
        if (eObject != null) {
            // search for the page that is editing the EObject
            int index = searchPageEditingEObject(eObject);
            if (index >= 0) {
                // remove it if it exists
                removePage(index);
                return true;
            }
        }
        return false;
    }

    /**
     * Get the index of the page that contains an editor that is editing the
     * given {@link EObject}.
     * 
     * @param eObject
     * @return
     */
    protected int searchPageEditingEObject(EObject eObject) {
        if (eObject == null) {
            // no EObject, no page
            return -1;
        }
        if (getMapEditorInput2EditorIndex().containsKey(eObject)) {
            // the mapping has the info, return it.
            return getMapEditorInput2EditorIndex().get(eObject);
        }
        // no page is editing that EObject.
        return -1;
    }

    // // IAdaptable

    /**
     * Adapts to {@link Diagram}. <br>
     * Adapts to {@link EditingDomain}. <br>
     * Adapts to {@link TransactionalEditingDomain}. <br>
     * Other adaptations are handled by superclasses.
     */
    @Override
    public Object getAdapter(Class adapter) {
        if (Diagram.class.equals(adapter)) {
            // if a Diagfram is wanted, return the one from the active editor,
            // if any.
            IEditorPart editorPart = getActiveEditor();
            if (editorPart != null) {
                return editorPart.getAdapter(Diagram.class);
            }
        }
        if (EditingDomain.class.equals(adapter) || TransactionalEditingDomain.class.equals(adapter)) {
            // if an editing domain is wanted, return the one shared by this
            // multi page editor, if any.
            return getMultiPageEditorContext().getEditingDomain();
        }
        if (IEditingDomainProvider.class.equals(adapter)) {
            // return a proper provider that can return the editing domain used
            // by all the nested editors.
            if (getActiveEditor() instanceof IEditingDomainProvider) {
                return getActiveEditor();
            } else {
                return null;
            }
        }
        if (IStorageApplicable.class.equals(adapter)) {
            if (getActiveEditor() == null) {
                return null;
            }
            return getActiveEditor().getAdapter(adapter);
        }
        // other adaptations are delegated to the superclass.
        return super.getAdapter(adapter);
    }

    // // init

    /**
     * The initialization must create the {@link MOSKittMultiPageEditorContext}
     * context and add this edtor as an {@link IPartListener2}.
     */
    @Override
    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
        if (site.getActionBars() instanceof EditorActionBars) {
            ((EditorActionBars) site.getActionBars())
                    .setEditorContributor(MOSKittMultiPageEditorActionBarContributor.getDefault());
        }
        super.init(site, input);
        // create this editor's context.
        setMultiPageEditorContext(new MOSKittMultiPageEditorContext(this));
        // add this editor as a listener to listen to its own closing ;)
        addThisEditorAsPartListener(site.getPage());
    }

    /**
     * Adds this editor as an {@link IPartListener2} to listen to its own
     * closing.
     * 
     * @param page
     */
    protected void addThisEditorAsPartListener(IWorkbenchPage page) {
        page.addPartListener(this);
    }

    // // create site

    /**
     * Create a {@link MOSKittMultiPageEditorSite} that has info about the
     * {@link MOSKittMultiPageEditorContext}.
     */
    @Override
    protected IEditorSite createSite(IEditorPart editorPart) {
        // This editor's site must include information about the
        // IMOSKittMultiPageEditorContext.
        return new MOSKittMultiPageEditorSite(this, editorPart, getMultiPageEditorContext(),
                getEditorSite().getActionBarContributor());
    }

    // // utilities

    /**
     * Returns the active editor. If no editor is active yet but there is one
     * being initialized, that one is returned. Otherwise, return null.
     */
    @Override
    public IEditorPart getActiveEditor() {
        IEditorPart activeEditor = super.getActiveEditor();
        return activeEditor != null ? activeEditor : creatingEditorPart;
    }

    /**
     * Returns a list with all the {@link IEditorPart}s open as pages.
     */
    public List<IEditorPart> getEditors() {
        List<IEditorPart> editors = new ArrayList<IEditorPart>();
        IEditorPart editor = null;
        for (int i = 0; i < getPageCount(); i++) {
            editor = getEditor(i);
            if (editor != null) {
                editors.add(editor);
            }
        }
        return editors;
    }

    /**
     * Get a list of diagrams that are inputs for any of the open editors.
     * 
     * @return
     */
    protected List<Diagram> getDiagramInputs() {
        if (getMapEditorInput2EditorIndex() == null || getMapEditorInput2EditorIndex().size() <= 0) {
            return Collections.emptyList();
        }
        List<Diagram> diagrams = new ArrayList<Diagram>();
        Diagram diagram = null;
        for (EObject eObject : getMapEditorInput2EditorIndex().keySet()) {
            diagram = (Diagram) Platform.getAdapterManager().getAdapter(eObject, Diagram.class);
            if (diagram != null) {
                diagrams.add(diagram);
            }
        }
        return diagrams;
    }

    protected IDiagramWorkbenchPart getDiagramWorkbenchPartEditor() {
        IEditorPart activeEditor = getActiveEditor();
        if (activeEditor != null) {
            IDiagramWorkbenchPart diagramWorkbenchPart = (IDiagramWorkbenchPart) Platform.getAdapterManager()
                    .getAdapter(activeEditor, IDiagramWorkbenchPart.class);
            if (diagramWorkbenchPart != null) {
                return diagramWorkbenchPart;
            }
        }
        return null;
    }

    /**
     * Creates a listener that listens to changes in the {@link ResourceSet}
     * regarding {@link Diagram} changed (additions, removal, name change).
     * 
     * @return
     */
    protected ResourceSetListener createListenerForDiagrams() {
        // resource set listener to add and remove pages when diagrams are
        // created - deleted - name changed
        return new ResourceSetListenerImpl() {

            @Override
            public void resourceSetChanged(ResourceSetChangeEvent event) {
                if (event.getNotifications() != null) {
                    List<Diagram> diagramsAdded = new ArrayList<Diagram>(1);
                    List<Diagram> diagramsRemoved = new ArrayList<Diagram>(1);

                    for (Notification notification : event.getNotifications()) {
                        // check diagrams added
                        if (notification.getEventType() == Notification.ADD) {
                            if (notification.getNotifier() instanceof Resource) {
                                if (notification.getNewValue() instanceof Diagram)
                                    // add diagram to toAdd list
                                    diagramsAdded.add((Diagram) notification.getNewValue());
                            }
                        }
                        if (notification.getEventType() == Notification.ADD_MANY) {
                            if (notification.getNotifier() instanceof Resource) {
                                if (notification.getNewValue() instanceof Collection) {
                                    for (Object object : (Collection) notification.getNewValue()) {
                                        if (object instanceof Diagram) {
                                            diagramsAdded.add((Diagram) object);
                                        }
                                    }
                                }
                            }
                        }
                        // check diagrams removed
                        if (notification.getEventType() == Notification.REMOVE) {
                            if (notification.getNotifier() instanceof Resource) {
                                if (notification.getOldValue() instanceof Diagram) {
                                    // add diagram to toRemove list
                                    diagramsRemoved.add((Diagram) notification.getOldValue());
                                }
                            }
                        }
                        if (notification.getEventType() == Notification.REMOVE_MANY) {
                            if (notification.getNotifier() instanceof Resource) {
                                if (notification.getOldValue() instanceof Collection) {
                                    for (Object object : (Collection) notification.getOldValue()) {
                                        if (object instanceof Diagram) {
                                            diagramsRemoved.add((Diagram) object);
                                        }
                                    }
                                }
                            }
                        }
                        // check for diagram name's changes
                        if (notification.getEventType() == Notification.SET
                                || notification.getEventType() == Notification.UNSET) {
                            if (notification.getNotifier() instanceof Diagram && NotationPackage.eINSTANCE
                                    .getDiagram_Name().equals(notification.getFeature())) {
                                Diagram diagram = (Diagram) notification.getNotifier();
                                if (diagram != null) {
                                    String newName = diagram.getName() != null ? diagram.getName()
                                            : diagram.getType();
                                    for (EObject eObject : getMapEditorInput2EditorIndex().keySet()) {
                                        if (eObject != null && eObject.equals(diagram)) {
                                            Integer pageIndex = getMapEditorInput2EditorIndex().get(eObject);
                                            if (pageIndex != null) {
                                                setPageText(pageIndex, newName);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    for (Diagram diagram : diagramsAdded) {
                        // handle added diagrams
                        handleDiagramAdded(diagram);
                    }

                    for (Diagram diagram : diagramsRemoved) {
                        // handle removed diagrams
                        handleDiagramRemoved(diagram);
                    }
                }
                super.resourceSetChanged(event);
            }
        };
    }

    protected void handleDiagramAdded(Diagram diagram) {
        // open a page for each added diagram.
        // if the diagram does not belong to the original Resource, do not add
        // it.
        if (diagram != null) {
            if (diagram.eResource() != null) {
                if (!diagram.eResource().equals(getMainDiagramResource())) {
                    return;
                }
            }
        }
        boolean openNewDiagram = getOpenNewDiagramPreferenceValue();
        if (openNewDiagram) {
            openPageForEObject(diagram);
        }
    }

    private boolean getOpenNewDiagramPreferenceValue() {
        boolean value = Activator.getDefault().getPreferenceStore()
                .getBoolean(MOSKittPreferenceConstants.P_NEW_DIAGRAMS);

        return value;
    }

    protected void handleDiagramRemoved(Diagram diagram) {
        // close each deleted diagram's page
        closeExistingPageForEObject(diagram);
    }

    // // IPartListener2

    public void partActivated(IWorkbenchPartReference partRef) {
        // nothing
    }

    public void partBroughtToTop(IWorkbenchPartReference partRef) {
        // nothing
    }

    public void partClosed(IWorkbenchPartReference partRef) {
        if (partRef != null) {
            IWorkbenchPart workbenchPart = partRef.getPart(false);
            if (workbenchPart != null && this.equals(workbenchPart)) {
                // if its us who is closing, store the open diagrams
                MultiDiagramUtil.storeOpenDiagrams(getDiagramInputs());
            }
        }
    }

    public void partDeactivated(IWorkbenchPartReference partRef) {
        // nothing
    }

    public void partHidden(IWorkbenchPartReference partRef) {
        // nothing
    }

    public void partInputChanged(IWorkbenchPartReference partRef) {
        // nothing
    }

    public void partOpened(IWorkbenchPartReference partRef) {
        // nothing
    }

    public void partVisible(IWorkbenchPartReference partRef) {
        // nothing
    }

    // // IDiagramWorkbenchPart

    /**
     * {@link IDiagramWorkbenchPart} operations are delegated to the active
     * editor.
     */
    public Diagram getDiagram() {
        IDiagramWorkbenchPart diagramWorkbenchPart = getDiagramWorkbenchPartEditor();
        if (diagramWorkbenchPart != null) {
            return diagramWorkbenchPart.getDiagram();
        }
        return null;
    }

    /**
     * {@link IDiagramWorkbenchPart} operations are delegated to the active
     * editor.
     */
    public IDiagramEditDomain getDiagramEditDomain() {
        IDiagramWorkbenchPart diagramWorkbenchPart = getDiagramWorkbenchPartEditor();
        if (diagramWorkbenchPart != null) {
            return diagramWorkbenchPart.getDiagramEditDomain();
        }
        return null;
    }

    /**
     * {@link IDiagramWorkbenchPart} operations are delegated to the active
     * editor.
     */
    public DiagramEditPart getDiagramEditPart() {
        IDiagramWorkbenchPart diagramWorkbenchPart = getDiagramWorkbenchPartEditor();
        if (diagramWorkbenchPart != null) {
            return diagramWorkbenchPart.getDiagramEditPart();
        }
        return null;
    }

    /**
     * {@link IDiagramWorkbenchPart} operations are delegated to the active
     * editor.
     */
    public IDiagramGraphicalViewer getDiagramGraphicalViewer() {
        IDiagramWorkbenchPart diagramWorkbenchPart = getDiagramWorkbenchPartEditor();
        if (diagramWorkbenchPart != null) {
            return diagramWorkbenchPart.getDiagramGraphicalViewer();
        }
        return null;
    }

    // // content outline update & refresh

    /** "Content Outline" view identifier */
    private static final String DiagramOutlineViewID = "org.eclipse.ui.views.ContentOutline"; //$NON-NLS-1$

    /**
     * When a page changes we want to notify the content outline so that the new
     * diagram is rendered in the diagram.
     */
    @Override
    protected void pageChange(int newPageIndex) {
        IEditorPart iep = getEditor(newPageIndex);

        // refresh the disposed icons from the views
        if (iep instanceof IDiagramWorkbenchPart) {
            IDiagramWorkbenchPart diagramWP = (IDiagramWorkbenchPart) iep;
            DiagramEditPart dep = diagramWP.getDiagramEditPart();
            refreshChilds(dep);
        }
        // do default operations
        super.pageChange(newPageIndex);
        // notify outline view of the page change
        notifyContentOutlinePartActivated();
        // refresh the new active diagram
        refreshDiagram(newPageIndex);
    }

    private void refreshChilds(DiagramEditPart dep) {
        for (Object o : dep.getChildren()) {
            if (!(o instanceof IGraphicalEditPart))
                continue;

            IGraphicalEditPart igep = (IGraphicalEditPart) o;

            IFigure figure = igep.getFigure();
            if (figure != null) {
                refreshFigureLabel(figure, igep.resolveSemanticElement());
            }

            refreshChilds(igep);
        }
    }

    private void refreshChilds(IGraphicalEditPart igep) {
        for (Object o : igep.getChildren()) {
            if (!(o instanceof IGraphicalEditPart))
                continue;

            IGraphicalEditPart igep2 = (IGraphicalEditPart) o;

            IFigure figure = igep2.getFigure();
            if (figure != null) {
                refreshFigureLabel(figure, igep2.resolveSemanticElement());
            }

            refreshChilds(igep2);
        }
    }

    private void refreshFigureLabel(IFigure figure, EObject eObject) {
        if (eObject == null)
            return;

        if (figure instanceof org.eclipse.draw2d.Label) {
            org.eclipse.draw2d.Label label = (org.eclipse.draw2d.Label) figure;
            if (label.getIcon().isDisposed()) {
                label.setIcon(MDTUtil.getLabelProvider().getImage(eObject));
            }
        } else if (figure instanceof WrappingLabel) {
            WrappingLabel label = (WrappingLabel) figure;
            if (label.getIcon() != null && label.getIcon().isDisposed()) {
                label.setIcon(MDTUtil.getLabelProvider().getImage(eObject));
            }
        }
    }

    protected void refreshDiagram(int pageIndex) {
        IEditorPart editorPart = getEditor(pageIndex);
        if (editorPart instanceof IDiagramWorkbenchPart) {
            DiagramEditPart editPart = ((IDiagramWorkbenchPart) editorPart).getDiagramEditPart();
            if (editPart != null) {
                DiagramEditPartsUtil.updateDiagram(editPart);
            }
        }
    }

    /**
     * Will look for the "Content Outline" view and notify it that a new editor
     * has been activated.
     */
    protected void notifyContentOutlinePartActivated() {
        // get the active editor inside this multi page editor
        IEditorPart activeEditor = getActiveEditor();
        if (activeEditor == null) {
            // no active editor means nothing to do
            return;
        }
        IViewReference[] viewReferences = null;
        try {
            // get the view references in the workbench to search for the
            // "Content Outline" view.
            IWorkbenchWindow ww = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
            if (ww != null && ww.getActivePage() != null) {
                viewReferences = ww.getActivePage().getViewReferences();
            }
        } catch (NullPointerException ex) {
            // workbench not yet ready;
        }
        if (viewReferences == null) {
            // no views means nothing to do.
            return;
        }
        // search through all the view references
        for (IViewReference reference : viewReferences) {
            if (reference.getId() != null && reference.getId().equals(DiagramOutlineViewID)) {
                // the "Content Outline" is among the open view parts
                IWorkbenchPart part = reference.getPart(false);
                if (part != null) {
                    // check that it is ready
                    ContentOutline contentOutline = (ContentOutline) Platform.getAdapterManager().getAdapter(part,
                            ContentOutline.class);
                    if (contentOutline != null) {
                        // finally notify the "Content Outline" of the editor
                        // change.
                        contentOutline.partActivated(activeEditor);
                    }
                }
            }
        }
    }

    /**
     * Mapping that stores the last save option selected by the user for each
     * nested editor.
     */
    private Map<Integer, Integer> mapEditorIndex2SaveOnClose = new HashMap<Integer, Integer>();

    /**
     * {@link ISaveablePart2} implementation. <br>
     * Will ask nested editors that implement ISaveablePart2 to perform their
     * prompt.
     * 
     */
    public int promptToSaveOnClose() {
        // clear the previous map
        mapEditorIndex2SaveOnClose.clear();
        int saveOption = ISaveablePart2.DEFAULT;
        boolean saveNeeded = false;
        ISaveablePart saveablePart1 = null;
        ISaveablePart2 saveablePart2 = null;
        String partsNamesToSave = ""; //$NON-NLS-1$
        for (int i = 0; i < getPageCount(); i++) {
            IEditorPart editor = getEditor(i);
            if (editor == null) {
                continue;
            }
            saveablePart1 = (ISaveablePart) Platform.getAdapterManager().getAdapter(editor, ISaveablePart.class);
            saveablePart2 = (ISaveablePart2) Platform.getAdapterManager().getAdapter(editor, ISaveablePart2.class);
            if (saveablePart2 != null) {
                saveOption = saveablePart2.promptToSaveOnClose();
            } else if (saveablePart1 != null) {
                saveOption = saveablePart1.isSaveOnCloseNeeded() ? ISaveablePart2.YES : ISaveablePart2.NO;
            } else {
                saveOption = ISaveablePart2.DEFAULT;
            }
            mapEditorIndex2SaveOnClose.put(i, saveOption);
            if (saveOption == ISaveablePart2.YES) {
                saveNeeded = true;
                partsNamesToSave += ((partsNamesToSave.length() == 0 ? "" //$NON-NLS-1$
                        : ", ") + getPageText(i)); //$NON-NLS-1$
            }
        }

        if (saveNeeded) {
            String message = Messages.MOSKittMultiPageEditor_15;
            String[] buttons = new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL,
                    IDialogConstants.CANCEL_LABEL };
            MessageDialog dialog = new MessageDialog(
                    PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                    Messages.MOSKittMultiPageEditor_16, null, message, MessageDialog.QUESTION, buttons, 0) {
                protected int getShellStyle() {
                    return SWT.CLOSE | SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL | getDefaultOrientation();
                }
            };
            int choice = ISaveablePart2.NO;
            choice = dialog.open();
            // map value of choice back to ISaveablePart2 values
            switch (choice) {
            case 0: // Yes
                choice = ISaveablePart2.YES;
                break;
            case 1: // No
                choice = ISaveablePart2.NO;
                break;
            case 2: // Cancel
                choice = ISaveablePart2.CANCEL;
                break;
            default: // ??
                choice = ISaveablePart2.DEFAULT;
                break;
            }
            return choice;
        } else {
            return ISaveablePart2.NO;
        }
    }

    public String getEditingDomainID() {
        if (getActiveEditor() instanceof es.cv.gvcase.emf.common.part.IEditingDomainRegistrable) {
            return ((es.cv.gvcase.emf.common.part.IEditingDomainRegistrable) getActiveEditor())
                    .getEditingDomainID();
        }
        return null;
    }

    public String getEditingDomainResourceURI() {
        if (getActiveEditor() instanceof es.cv.gvcase.emf.common.part.IEditingDomainRegistrable) {
            return ((es.cv.gvcase.emf.common.part.IEditingDomainRegistrable) getActiveEditor())
                    .getEditingDomainResourceURI();
        }
        return null;
    }

    public static final String MOSKittEditorSetInputHookID = "es.cv.gvcase.mdt.common.part.MOSKittMultiPageEditor.setInput.HookID"; //$NON-NLS-1$

    @Override
    protected void setInput(IEditorInput input) {
        // remove the possible editor properties set to the file of the given
        // input; that property interferes with the copy/paste handler
        MDTUtil.removeEditorForDiagramProperty(input);
        // a MOSKitt editor is started or changed input
        Object[] info = new Object[] { this, input };
        HookRunner.getInstance().runRunnablesWithInfoForHook(MOSKittEditorSetInputHookID, info);
        // mgil: migrate diagrams
        TransactionalEditingDomain editingDomain = EditingDomainRegistry.getInstance().hasDomain("", input); //$NON-NLS-1$

        Diagram diagram = MDTUtil.getDiagramFromEditorInput(input, editingDomain);
        if (diagram != null) {
            checkDiagramToOpen(editingDomain, diagram);
        }
        // mgil: end migrate diagrams

        super.setInput(input);
    }

    /**
     * Opens the given editor input after this editor has been created.
     * 
     * @param editorInput
     */
    public void openInput(IEditorInput editorInput) {
        if (editorInput != null) {
            // make sure this editor is active and on the front
            getSite().getWorkbenchWindow().getActivePage().activate(this);
            if (editorInput instanceof URIEditorInput) {
                URIEditorInput uriEditorInput = (URIEditorInput) editorInput;
                URI inputURI = uriEditorInput.getURI();
                ResourceSet resourceSet = getDiagram().eResource().getResourceSet();
                inputURI = PathsUtil.toWorkspaceURI(inputURI);
                Resource inputResource = resourceSet.getResource(inputURI.trimFragment(), true);
                if (uriEditorInput.getURI().hasFragment()) {
                    // get the Diagram to open from the given editor input
                    EObject eObject = inputResource.getEObject(uriEditorInput.getURI().fragment());
                    String eObjectFragment = eObject.eResource().getURIFragment(eObject);
                    if (eObject instanceof Diagram) {
                        boolean alreadyShown = false;
                        int i = 0;
                        // search for an already open tab that is showing that
                        // diagram
                        for (CTabItem tabItem : getTabFolder().getItems()) {
                            Object data = tabItem.getData();
                            if (data instanceof IDiagramWorkbenchPart) {
                                Diagram editorDiagram = ((IDiagramWorkbenchPart) data).getDiagram();
                                String editorDiagramFragment = editorDiagram.eResource()
                                        .getURIFragment(editorDiagram);
                                if (eObjectFragment.equals(editorDiagramFragment)) {
                                    // a tab has been found that is already
                                    // showing the diagram, open that tab
                                    setActivePage(i);
                                    alreadyShown = true;
                                    break;
                                }
                            }
                            i++;
                        }
                        if (!alreadyShown) {
                            // if no tab that show the iven input exist, open a
                            // new one
                            try {
                                addPageForElement(eObject);
                            } catch (PartInitException ex) {
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Check if there exists some migrator for the diagram, and execute them
     * 
     * @author mgil
     * @param input
     */
    protected void checkDiagramToOpen(TransactionalEditingDomain editingDomain, Diagram diagram) {
        // read the migrators
        DiagramMigrationRegistry migrationRegistry = DiagramMigrationRegistry.getInstance();
        if (migrationRegistry == null) {
            return;
        }

        // compute all the migrators
        List<MigratorService> migrators = migrationRegistry.parseMigrators();
        List<MigratorService> validMigrators = new ArrayList<MigratorService>();
        for (MigratorService migrator : migrators) {
            if (migrator.provides(diagram)) {
                validMigrators.add(migrator);
            }
        }

        // if no valid migrators for this diagram, do nothing
        if (validMigrators.size() == 0) {
            return;
        }

        // sort the migrators by version (alphabetically ascendant way)
        Collections.sort(validMigrators, new MigratorVersionComparator());

        // if valid migrators founded, execute them. First, ask user if wants to
        // execute the migration...
        String title = Messages.MOSKittMultiPageEditor_19;
        String message = Messages.MOSKittMultiPageEditor_20;
        for (MigratorService migrator : validMigrators) {
            String name = migrator.getLabel();
            message += "\t- " + name + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
        }
        message += Messages.MOSKittMultiPageEditor_23;
        boolean answer = MessageDialog.openQuestion(new Shell(), title, message);

        if (!answer) {
            return;
        }

        // ... and finally execute them. Check if we have an editing domain, to
        // execute the migration with a read/write transactions, or without it
        if (editingDomain != null) {
            for (MigratorService migrator : validMigrators) {
                if (!migrator.executeMigrationWithTransaction(editingDomain)) {
                    break;
                } else {
                    migrated = true;
                }
            }
        } else {
            for (MigratorService migrator : validMigrators) {
                if (!migrator.executeMigrationWithoutTransaction()) {
                    break;
                } else {
                    migrated = true;
                }
            }
        }
    }

    protected void updateUndoContextForActions() {
        try {
            setUndoContextForUndoAction();
            setUndoContextForRedoAction();
        } catch (NullPointerException ex) {
            return;
        }
    }

    protected void setUndoContextForUndoAction() {
        // update undo/redo menu
        IWorkbenchPart workbenchpart = this;
        if (workbenchpart != null && workbenchpart.getSite() instanceof EditorSite) {
            IContributionItem[] items = ((org.eclipse.ui.internal.EditorMenuManager) ((org.eclipse.ui.internal.EditorSite) workbenchpart
                    .getSite()).getActionBars().getMenuManager()).getParent().getItems();
            for (IContributionItem item : items) {
                if (item instanceof MenuManager) {
                    MenuManager menuManager = ((MenuManager) item);
                    if (menuManager.getId().equals("edit")) { //$NON-NLS-1$
                        for (IContributionItem menuItem : menuManager.getItems()) {
                            if (menuItem instanceof ActionContributionItem) {
                                ActionContributionItem actionItem = (ActionContributionItem) menuItem;
                                if (actionItem.getId().equals("undo")) { //$NON-NLS-1$
                                    if (actionItem.getAction() instanceof LabelRetargetAction) {
                                        LabelRetargetAction labelAction = (LabelRetargetAction) actionItem
                                                .getAction();
                                        if (labelAction.getActionHandler() instanceof GlobalUndoAction) {
                                            GlobalUndoAction globalUndoAction = (GlobalUndoAction) labelAction
                                                    .getActionHandler();
                                            IUndoContext undoContext = (IUndoContext) getAdapter(
                                                    IUndoContext.class);
                                            globalUndoAction.setUndoContext(undoContext);
                                            IUndoableOperation operation = PlatformUI.getWorkbench()
                                                    .getOperationSupport().getOperationHistory()
                                                    .getUndoOperation(undoContext);
                                            if (operation != null) {
                                                String label = operation.getLabel();
                                                labelAction.setText(Messages.MOSKittMultiPageEditor_26 + label);
                                            }
                                        }
                                        if (labelAction.getActionHandler() instanceof UndoActionHandler) {
                                            UndoActionHandler undoAction = (UndoActionHandler) labelAction
                                                    .getActionHandler();
                                            IUndoContext undoContext = (IUndoContext) getAdapter(
                                                    IUndoContext.class);
                                            undoAction.setContext(undoContext);
                                            IUndoableOperation operation = PlatformUI.getWorkbench()
                                                    .getOperationSupport().getOperationHistory()
                                                    .getUndoOperation(undoContext);
                                            if (operation != null) {
                                                String label = operation.getLabel();
                                                labelAction.setText(Messages.MOSKittMultiPageEditor_27 + label);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    protected void setUndoContextForRedoAction() {
        // update undo/redo menu
        IWorkbenchPart workbenchpart = this;
        if (workbenchpart != null && workbenchpart.getSite() instanceof EditorSite) {
            IContributionItem[] items = ((org.eclipse.ui.internal.EditorMenuManager) ((org.eclipse.ui.internal.EditorSite) workbenchpart
                    .getSite()).getActionBars().getMenuManager()).getParent().getItems();
            for (IContributionItem item : items) {
                if (item instanceof MenuManager) {
                    MenuManager menuManager = ((MenuManager) item);
                    if (menuManager.getId().equals("edit")) { //$NON-NLS-1$
                        for (IContributionItem menuItem : menuManager.getItems()) {
                            if (menuItem instanceof ActionContributionItem) {
                                ActionContributionItem actionItem = (ActionContributionItem) menuItem;
                                if (actionItem.getId().equals("redo")) { //$NON-NLS-1$
                                    if (actionItem.getAction() instanceof LabelRetargetAction) {
                                        LabelRetargetAction labelAction = (LabelRetargetAction) actionItem
                                                .getAction();
                                        if (labelAction.getActionHandler() instanceof GlobalRedoAction) {
                                            GlobalRedoAction globalRedoAction = (GlobalRedoAction) labelAction
                                                    .getActionHandler();
                                            IUndoContext undoContext = (IUndoContext) getAdapter(
                                                    IUndoContext.class);
                                            globalRedoAction.setUndoContext(undoContext);
                                            IUndoableOperation operation = PlatformUI.getWorkbench()
                                                    .getOperationSupport().getOperationHistory()
                                                    .getUndoOperation(undoContext);
                                            if (operation != null) {
                                                String label = operation.getLabel();
                                                labelAction.setText(Messages.MOSKittMultiPageEditor_30 + label);
                                            }
                                        }
                                        if (labelAction.getActionHandler() instanceof RedoActionHandler) {
                                            RedoActionHandler redoAction = (RedoActionHandler) labelAction
                                                    .getActionHandler();
                                            IUndoContext undoContext = (IUndoContext) getAdapter(
                                                    IUndoContext.class);
                                            redoAction.setContext(undoContext);
                                            IUndoableOperation operation = PlatformUI.getWorkbench()
                                                    .getOperationSupport().getOperationHistory()
                                                    .getUndoOperation(undoContext);
                                            if (operation != null) {
                                                String label = operation.getLabel();
                                                labelAction.setText(Messages.MOSKittMultiPageEditor_31 + label);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public void setFocus() {
        super.setFocus();
        //
        updateUndoContextForActions();
    }

}