de.topicmapslab.tmcledit.model.views.ModelView.java Source code

Java tutorial

Introduction

Here is the source code for de.topicmapslab.tmcledit.model.views.ModelView.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2009 Topic Maps Lab and others.
 * 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:
 *     Hannes Niederhausen - initial API and implementation
 *******************************************************************************/
package de.topicmapslab.tmcledit.model.views;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.ui.action.RedoAction;
import org.eclipse.emf.edit.ui.action.UndoAction;
import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory;
import org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreePathViewerSorter;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

import de.topicmapslab.onotoa.selection.service.IOnotoaSelectionService;
import de.topicmapslab.tmcledit.model.AssociationTypeConstraint;
import de.topicmapslab.tmcledit.model.Diagram;
import de.topicmapslab.tmcledit.model.DomainDiagram;
import de.topicmapslab.tmcledit.model.File;
import de.topicmapslab.tmcledit.model.ModelFactory;
import de.topicmapslab.tmcledit.model.ModelPackage;
import de.topicmapslab.tmcledit.model.TmcleditEditPlugin;
import de.topicmapslab.tmcledit.model.TopicMapSchema;
import de.topicmapslab.tmcledit.model.TopicType;
import de.topicmapslab.tmcledit.model.actions.CloseAction;
import de.topicmapslab.tmcledit.model.actions.CreateDiagramAction;
import de.topicmapslab.tmcledit.model.actions.CreateDomainDiagramAction;
import de.topicmapslab.tmcledit.model.actions.CreateItemIdenifierConstraintAction;
import de.topicmapslab.tmcledit.model.actions.CreateNameConstraintAction;
import de.topicmapslab.tmcledit.model.actions.CreateOccurrenceConstraintAction;
import de.topicmapslab.tmcledit.model.actions.CreateSubjectIdenifierConstraintAction;
import de.topicmapslab.tmcledit.model.actions.CreateSubjectLocatorConstraintAction;
import de.topicmapslab.tmcledit.model.actions.CreateTopicAction;
import de.topicmapslab.tmcledit.model.actions.DeleteDiagramAction;
import de.topicmapslab.tmcledit.model.actions.DeleteTMCLConstruct;
import de.topicmapslab.tmcledit.model.actions.RedoActionWrapper;
import de.topicmapslab.tmcledit.model.actions.RenameAction;
import de.topicmapslab.tmcledit.model.actions.UndoActionWrapper;
import de.topicmapslab.tmcledit.model.actions.UpdateAction;
import de.topicmapslab.tmcledit.model.actions.ValidateAction;
import de.topicmapslab.tmcledit.model.index.ModelIndexer;
import de.topicmapslab.tmcledit.model.preferences.PreferenceConstants;
import de.topicmapslab.tmcledit.model.preferences.RecentUsedManager;
import de.topicmapslab.tmcledit.model.util.TMCLEditorInput;
import de.topicmapslab.tmcledit.model.util.extension.ModelViewExtensionInfo;
import de.topicmapslab.tmcledit.model.util.io.FileUtil;
import de.topicmapslab.tmcledit.model.validation.ModelValidator;
import de.topicmapslab.tmcledit.model.validation.ValidationResult;
import de.topicmapslab.tmcledit.model.views.treenodes.AbstractModelViewNode;
import de.topicmapslab.tmcledit.model.views.treenodes.TreeName;
import de.topicmapslab.tmcledit.model.views.treenodes.TreeObject;
import de.topicmapslab.tmcledit.model.views.treenodes.TreeOccurrence;
import de.topicmapslab.tmcledit.model.views.treenodes.TreeSubjectIdentifier;
import de.topicmapslab.tmcledit.model.views.treenodes.TreeSubjectLocator;
import de.topicmapslab.tmcledit.model.views.treenodes.TreeTopic;

/**
 * @author Hannes Niederhausen
 */

public class ModelView extends ViewPart implements IEditingDomainProvider, ISelectionProvider, CommandStackListener,
        ISaveablePart, IResourceChangeListener, ISelectionChangedListener {

    /**
     * The ID of the view
     */
    public static final String ID = "de.topicmapslab.tmcledit.extensions.views.ModelView";

    TreeViewer viewer;
    private ModelViewContentProvider contentProvider;
    private Action validationAction;
    private Action doubleClickAction;

    private EditingDomain editingDomain;
    private ValidateJob validateJob = new ValidateJob();
    private File currFile;

    /* flag witch indicates if the view should have the global selection, or not */
    private boolean syncView = false;

    private List<ISelectionChangedListener> selectionListeners;
    private ISelection currentSelection;

    // private Map<String, IAction> actionRegistry;
    private ActionRegistry actionRegistry;

    private AdapterImpl dirtyListener = new AdapterImpl() {
        @Override
        public void notifyChanged(Notification msg) {
            if (msg.getFeatureID(Boolean.class) == ModelPackage.FILE__DIRTY) {
                firePropertyChange(PROP_DIRTY);
            }
        }
    };

    private RenameAction renameAction;

    private CreateDiagramAction createDiagramAction;

    private CreateDomainDiagramAction createDomainDiagramAction;

    private CreateTopicAction createTopicAction;

    private DeleteTMCLConstruct deleteConstructAction;

    private DeleteDiagramAction deleteDiagramAction;

    private CreateNameConstraintAction createNameConstraintAction;

    private CreateOccurrenceConstraintAction createOccurrenceConstraintAction;

    private CreateSubjectIdenifierConstraintAction createSubjectIdenifierConstraintAction;

    private CreateItemIdenifierConstraintAction createItemIdenifierConstraintAction;

    private CreateSubjectLocatorConstraintAction createSubjectLocatorConstraintAction;

    private IAction saveAction;

    private CloseAction closeAction;

    private RedoActionWrapper redoAction;

    private UndoActionWrapper undoAction;

    /**
     * Helper method to retrieve the view from the PlatformUI
     * @return the instance of the {@link ModelView} or <code>null</code>
     */
    public static final ModelView getInstance() {
        return (ModelView) TmcleditEditPlugin.getPlugin().getWorkbench().getActiveWorkbenchWindow().getActivePage()
                .findView(ID);
    }

    /**
     * The constructor.
     */
    public ModelView() {
    }

    /**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
    @Override
    public void createPartControl(Composite parent) {
        viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);

        contentProvider = new ModelViewContentProvider(this);
        viewer.setContentProvider(contentProvider);
        viewer.setLabelProvider(new ViewLabelProvider());
        viewer.setSorter(new NameSorter());

        viewer.setInput(getViewSite());
        viewer.expandToLevel(2);
        // Create the help context id for the viewer's control
        PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(),
                "de.topicmapslab.tmcledit.extensions.viewer");
        makeActions();
        hookContextMenu();
        hookDoubleClickAction();
        hookKeyListener();
        contributeToActionBars();

        getSite().setSelectionProvider(this);

        viewer.addSelectionChangedListener(new ISelectionChangedListener() {

            @SuppressWarnings("unchecked")
            public void selectionChanged(SelectionChangedEvent event) {
                if (currFile == null) {
                    currentSelection = new StructuredSelection();
                    return;
                }

                IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();

                // notify all selectionListeners in this 
                fireSelectionChanged(sel);
                // getting element for selection service

                if (sel.isEmpty()) {
                    currentSelection = new StructuredSelection(currFile);
                    createTopicAction.setEnabled(false);
                } else {

                    AbstractModelViewNode to = (AbstractModelViewNode) sel.getFirstElement();
                    createTopicAction.setEnabled(false);
                    createDiagramAction.setEnabled(false);
                    createDomainDiagramAction.setEnabled(false);
                    switch (to.getId()) {
                    case TreeObject.DIAGRAMS:
                        createDiagramAction.setEnabled(true);
                        createDomainDiagramAction.setEnabled(true);
                        break;
                    }

                    if (to instanceof TreeObject) {
                        createTopicAction.setKindOfTopicType(((TreeObject) to).getKindOfTopicType());
                        if (to.getModel() == null)
                            currentSelection = new StructuredSelection(currFile);
                    }
                    Iterator<Object> it = sel.iterator();
                    List<Object> list = new ArrayList<Object>();
                    while (it.hasNext()) {
                        to = (AbstractModelViewNode) it.next();
                        if (to.getModel() != null)
                            list.add((Object) to.getModel());
                    }
                    currentSelection = new StructuredSelection(list);
                }
                TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().setSelection(currentSelection,
                        ModelView.this);
            }

        });
        initDragAndDrop();
    }

    @Override
    public void init(IViewSite site, IMemento memento) throws PartInitException {
        init(site);

        IPreferenceStore pref = TmcleditEditPlugin.getPlugin().getPreferenceStore();
        String filename = pref.getString(PreferenceConstants.P_LOADFILE);
        if ((filename != null) && (filename.length() > 0) && (filename.endsWith(".ono"))) {
            // check if the parameter is really a file
            java.io.File f = new java.io.File(filename);
            if (!f.exists()) {
                // try to add working directory because filename is a relative path
                String tmp = System.getProperty("user.dir") + "/" + filename;
                f = new java.io.File(tmp);
            }
            if (filename.endsWith(".ono") && (f.exists())) {
                setFilename(filename, false);
                pref.setValue(PreferenceConstants.P_LOADFILE, "");
                return;
            }
        }

        if (memento == null)
            return;

        String text = memento.getTextData();
        if ((text == null) || ("null".equals(text)))
            return;

        setFilename(text, false);

        for (IMemento children : memento.getChildren("editor")) {
            text = children.getTextData();

            Diagram currDiagram = null;
            for (Diagram d : currFile.getDiagrams()) {
                if (d.getName().equals(text))
                    currDiagram = d;
            }
            if (currDiagram != null) {
                String id = (currDiagram instanceof DomainDiagram) ? TmcleditEditPlugin.DOMAIN_DIAGRAMEDITOR_ID
                        : TmcleditEditPlugin.DIAGRAMEDITOR_ID;

                getViewSite().getPage().openEditor(
                        new TMCLEditorInput(currDiagram, getEditingDomain(), getActionRegistry(), this), id);
            }
        }

    }

    @Override
    public void init(IViewSite site) throws PartInitException {
        super.init(site);

        actionRegistry = new ActionRegistry();
        createActions();
        ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);

        TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().addSelectionChangedListener(this);

    }

    private void createActions() {
        IActionBars actionBars = getViewSite().getActionBars();
        ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();

        undoAction = new UndoActionWrapper();
        undoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO));

        redoAction = new RedoActionWrapper();
        redoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO));

        closeAction = new CloseAction(this);
        addPropertyListener(closeAction);

        saveAction = ActionFactory.SAVE.create(getViewSite().getWorkbenchWindow());

        actionRegistry.registerAction(saveAction);
        actionRegistry.registerAction(closeAction);
        actionRegistry.registerAction(undoAction);
        actionRegistry.registerAction(redoAction);

        actionBars.updateActionBars();

        actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction);
        actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction);
        actionBars.setGlobalActionHandler(ActionFactory.CLOSE.getId(), closeAction);

        undoAction.setEnabled(false);
        redoAction.setEnabled(false);
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus() {
        viewer.getControl().setFocus();
        if (currentSelection != null)
            TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().setSelection(currentSelection,
                    ModelView.this);
    }

    public EditingDomain getEditingDomain() {
        if (editingDomain == null) {
            editingDomain = WorkspaceEditingDomainFactory.INSTANCE.createEditingDomain();
            IAction action = actionRegistry.getAction(ActionFactory.UNDO.getId());
            ((UndoAction) action).setEditingDomain(editingDomain);

            action = actionRegistry.getAction(ActionFactory.REDO.getId());
            ((RedoAction) action).setEditingDomain(editingDomain);
            editingDomain.getCommandStack().addCommandStackListener(this);
            updateActions();
        }

        return editingDomain;
    }

    /**
     * 
     * @return the {@link CommandStack} used to execute the modification operations
     */
    public CommandStack getCommandStack() {
        return getEditingDomain().getCommandStack();
    }

    private List<ISelectionChangedListener> getSelectionListeners() {
        if (selectionListeners == null)
            return Collections.emptyList();
        return selectionListeners;
    }

    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        if (selectionListeners == null)
            selectionListeners = new ArrayList<ISelectionChangedListener>();
        selectionListeners.add(listener);
    }

    public ISelection getSelection() {
        if (currentSelection == null)
            if (currFile != null)
                currentSelection = new StructuredSelection(currFile);
            else
                currentSelection = new StructuredSelection();
        return currentSelection;
    }

    /**
     * 
     * @return the current {@link TopicMapSchema} or <code>null</code> if not loaded
     * @deprecated Use the {@link IOnotoaSelectionService} instead
     */
    public TopicMapSchema getCurrentTopicMapSchema() {
        File currFile = TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().getOnotoaFile();
        if (currFile != null)
            return currFile.getTopicMapSchema();
        return null;
    }

    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        if (selectionListeners != null)
            selectionListeners.remove(listener);
    }

    public void setSelection(ISelection selection) {
        if (!syncView)
            return;

        if (viewer != null) {
            if (selection.isEmpty())
                viewer.setSelection(selection);
            else {
                List<AbstractModelViewNode> nodes = new ArrayList<AbstractModelViewNode>();
                Iterator<?> it = ((IStructuredSelection) selection).iterator();
                while (it.hasNext()) {
                    IContentProvider cp = viewer.getContentProvider();
                    AbstractModelViewNode n = ((ModelViewContentProvider) cp).findNodeFor(it.next());
                    if (n != null)
                        nodes.add(n);
                }
                StructuredSelection nodeSel = new StructuredSelection(nodes);
                viewer.setSelection(nodeSel);
                fireSelectionChanged(nodeSel);
            }
        }
        currentSelection = selection;
        TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().setSelection(currentSelection, ModelView.this);
    }

    /**
     * Sets the filename and loads the file 
     * @param filename the name of a new file
     * @param newFile flag if the file is new or should be loaded
     */
    public void setFilename(String filename, boolean newFile) {
        setFilename(filename, newFile, null);
        if (filename != null && filename.length() > 0)
            RecentUsedManager.addFile(filename);
    }

    /**
     * Sets the filename and loads the file 
     * @param filename the name of a new file
     * @param newFile flag if the file is new or should be loaded
     * @param newOnotoaFile a file which is already opened and set to this {@link ModelView}
     */
    // TODO refactor me PLEEEEAAASSE!!!
    public void setFilename(String filename, boolean newFile, File newOnotoaFile) {
        IViewSite viewSite = getViewSite();
        if (viewSite != null) {

            IWorkbenchPage page = viewSite.getPage();
            if (currFile != null) {
                // if ( (!currFile.isDirty()) &&
                // (currFile.getFilename().equals(filename))
                // return;

                currFile.eAdapters().remove(dirtyListener);

                for (IEditorReference ref : page.getEditorReferences()) {
                    try {
                        if (ref.getEditorInput() instanceof TMCLEditorInput) {
                            IEditorPart part = ref.getEditor(false);
                            page.closeEditor(part, false);
                        }
                    } catch (PartInitException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            checkSavedState();
        }
        updateTitle(filename);

        if (contentProvider != null)
            contentProvider.uninitialize();

        if (editingDomain != null)
            editingDomain.getCommandStack().removeCommandStackListener(this);

        editingDomain = null; // clear it for new creation in getter
        if (filename != null) {
            if (!newFile) {
                try {
                    currFile = FileUtil.loadFile(filename);
                } catch (Exception e) {
                    TmcleditEditPlugin.getPlugin().log(e);
                    currFile = null;
                }
            } else if (newOnotoaFile != null) {
                currFile = newOnotoaFile;
            } else {
                currFile = ModelFactory.eINSTANCE.createFile();
                currFile.setTopicMapSchema(ModelFactory.eINSTANCE.createTopicMapSchema());
                if (filename.length() > 0)
                    currFile.setFilename(filename);
            }
            currFile.eAdapters().add(dirtyListener);

            // initialize indexer
            ModelIndexer.createInstance(currFile);
        } else {
            currFile = null;
        }

        // tell the selection service about the new file
        TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().setOnotoaFile(currFile);

        if (contentProvider != null)
            contentProvider.initialize();

        if (currFile != null)
            setSelection(new StructuredSelection(currFile));
        else
            setSelection(new StructuredSelection());

        firePropertyChange(PROP_DIRTY);

        if (viewer != null) {
            viewer.refresh();
            viewer.expandToLevel(2);
        }

        // update actions of modelview
        updateModelViewActions();

        //      // inform NotesView
        //      if (viewSite != null) {
        //         IWorkbenchWindow workbenchWindow = viewSite.getWorkbenchWindow();
        //         IWorkbenchPage activePage = workbenchWindow.getActivePage();
        //         if (activePage != null) {
        //            IViewPart notesView = activePage.findView(NotesView.ID);
        //            if (notesView != null)
        //               ((NotesView) notesView).update();
        //         }
        //      }

    }

    /**
     * Refreshes the {@link TreeViewer}. If recreate is <code>true</code> the content provider is reinitialized, else
     * the view will just refresh.
     * @param recreate flag whether the contentProvider should be reinitialzed
     */
    public void refreshView(boolean recreate) {
        if (recreate) {
            contentProvider.initialize();
        } else {
            getViewer().refresh();
        }
        viewer.refresh();
        viewer.expandToLevel(2);
    }

    private void updateActions() {
        @SuppressWarnings("unchecked")
        Iterator<IAction> it = actionRegistry.getActions();
        while (it.hasNext()) {
            IAction a = it.next();
            if (a instanceof UpdateAction)
                ((UpdateAction) a).update();
        }
        // updating export selection

        List<ModelViewExtensionInfo> mveInfos = TmcleditEditPlugin.getExtensionManager()
                .getModelViewExtensionInfos();
        for (ModelViewExtensionInfo mve : mveInfos) {
            for (UpdateAction a : mve.getProvider().getActions()) {
                a.update();
            }
        }

        getViewSite().getActionBars().getGlobalActionHandler(ActionFactory.EXPORT.getId());
    }

    /**
     * 
     * @return the {@link ActionRegistry} of this view containing all actions of the context menu
     */
    public ActionRegistry getActionRegistry() {
        return actionRegistry;
    }

    @Override
    public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
        if (adapter == ActionRegistry.class)
            return getActionRegistry();

        if (adapter == File.class)
            return currFile;

        if (adapter == CommandStack.class)
            return getEditingDomain().getCommandStack();

        return super.getAdapter(adapter);
    }

    /**
     * 
     * @return the {@link TreeViewer} representing the model
     */
    public TreeViewer getViewer() {
        return viewer;
    }

    public void commandStackChanged(EventObject event) {
        updateActions();
        WorkspaceCommandStackImpl cmdStack = (WorkspaceCommandStackImpl) getEditingDomain().getCommandStack();
        currFile.setDirty(cmdStack.isSaveNeeded());

        if (!validateJob.isRunning())
            validateJob.schedule();
    }

    /**
     * Closes the model
     */
    public void close() {
        setFilename(null, false);
        IWorkbenchPage activePage = getViewSite().getWorkbenchWindow().getActivePage();
        for (IEditorReference ref : activePage.getEditorReferences()) {
            if (ref.getId().equals(TmcleditEditPlugin.DIAGRAMEDITOR_ID)) {
                activePage.closeEditor(ref.getEditor(false), false);
            }
        }

        // notify extensions
        List<ModelViewExtensionInfo> mveInfos = TmcleditEditPlugin.getExtensionManager()
                .getModelViewExtensionInfos();
        for (ModelViewExtensionInfo mve : mveInfos) {
            mve.getProvider().close();
        }

        TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().setSelection(new StructuredSelection(), this);

        firePropertyChange(PROP_DIRTY);
        updateActions();
        viewer.refresh();
        setSelection(new StructuredSelection());

        actionRegistry.getAction(ActionFactory.UNDO.getId()).setEnabled(false);
        actionRegistry.getAction(ActionFactory.REDO.getId()).setEnabled(false);

    }

    @Override
    public void saveState(IMemento memento) {
        String text = "null";

        if ((currFile != null) && (currFile.getFilename() != null)) {
            java.io.File file = new java.io.File(currFile.getFilename());
            if (file.exists())
                text = currFile.getFilename();
            file = null;
        } else {
            return;
        }

        memento.putTextData(text);
        int i = 0;
        for (IEditorReference ref : getViewSite().getPage().getEditorReferences()) {
            IEditorPart part = ref.getEditor(false);
            if (part != null) {
                if ((ref.getId().equals(TmcleditEditPlugin.DIAGRAMEDITOR_ID))
                        || (ref.getId().equals(TmcleditEditPlugin.DOMAIN_DIAGRAMEDITOR_ID))) {
                    i++;
                    TMCLEditorInput ei = (TMCLEditorInput) part.getEditorInput();
                    IMemento partChild = memento.createChild("editor");
                    partChild.putTextData(ei.getDiagram().getName());
                }
            }
        }
    }

    @Override
    public void dispose() {
        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
        TmcleditEditPlugin.getPlugin().getOnotoaSelectionService().removeSelectionChangedListener(this);
        super.dispose();
    }

    public void doSave(IProgressMonitor monitor) {
        try {
            if (currFile.getFilename() == null) {
                doSaveAs();
                return;
            }

            FileUtil.saveFile((File) currFile, getEditingDomain());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    public void doSaveAs() {
        FileDialog dlg = new FileDialog(getSite().getShell(), SWT.SAVE);
        dlg.setText("Save As..");
        List<String> filesList = RecentUsedManager.getFilesList();
        if (!filesList.isEmpty()) {
            String file = filesList.get(0);
            int idx = file.lastIndexOf("/");
            if (idx != -1)
                dlg.setFilterPath(file.substring(0, idx));
        }
        String result = dlg.open();
        if (result != null) {
            if ((!result.endsWith(".ono")) && (!result.endsWith(".tmcl")))
                result += ".ono";
            currFile.setFilename(result);
            updateTitle(currFile.getFilename());
            RecentUsedManager.addFile(currFile.getFilename());
            doSave(new NullProgressMonitor());

        }
    }

    public boolean isDirty() {
        if (currFile == null)
            return false;
        return currFile.isDirty();
    }

    public boolean isSaveAsAllowed() {
        return (currFile != null);
    }

    public boolean isSaveOnCloseNeeded() {
        return isDirty();
    }

    @Override
    public void setPartProperty(String key, String value) {
        if ("newfilename".equals(key))
            setFilename(value, true);
        else if ("filename".equals(key))
            setFilename(value, false);
        else
            super.setPartProperty(key, value);
    }

    public void resourceChanged(IResourceChangeEvent event) {
        if (currFile == null)
            return;
        String filename = currFile.getFilename();
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IFile file = workspace.getRoot().getFileForLocation(new Path(filename));
        assert (file != null);
        IProject project = file.getProject();
        if (project == null)
            return;
        String projectPath = project.getLocation().toOSString();
        if (filename.startsWith(projectPath)) {
            filename = project.getName() + "/" + filename.substring(projectPath.length() + 1);

        }

        IResourceDelta delta = event.getDelta().findMember(new Path(filename));
        if (delta == null)
            return;

        if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
            String newPath = workspace.getRoot().getLocation().toOSString() + delta.getMovedToPath().toOSString();
            currFile.setFilename(newPath);
        }
    }

    private void initDragAndDrop() {
        DragSource dragSource = new DragSource(viewer.getTree(), DND.DROP_COPY);
        dragSource.setTransfer(new Transfer[] { TextTransfer.getInstance() });
        dragSource.addDragListener(new DragSourceAdapter() {

            @Override
            public void dragStart(DragSourceEvent event) {

                IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
                StringBuffer tmp = prepareTopicTypes(sel);

                if (tmp.length() > 0) {
                    event.doit = true;
                    event.data = tmp.toString();
                } else {
                    event.doit = false;
                }

            }

            @Override
            public void dragSetData(DragSourceEvent event) {
                if (viewer == null)
                    return;

                IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();

                StringBuffer tmp = prepareTopicTypes(sel);
                if (tmp.length() > 0) {
                    event.data = tmp.toString();
                } else {
                    event.data = null;
                }
            }

            @SuppressWarnings("unchecked")
            private StringBuffer prepareTopicTypes(IStructuredSelection sel) {
                // concat every model string and ignore other nodes..
                StringBuffer tmp = new StringBuffer();

                if (sel.size() == 1) {
                    TreeObject selObj = (TreeObject) sel.getFirstElement();

                    if ((selObj.getModel() instanceof AssociationTypeConstraint)
                            || (selObj.getModel() instanceof TopicType)) {
                        tmp.append(selObj.getModel().toString());
                    }
                } else {
                    Iterator<Object> it = sel.iterator();
                    while (it.hasNext()) {
                        Object obj = it.next();
                        if (obj instanceof TreeTopic) {
                            tmp.append(((TreeTopic) obj).getModel().toString());
                            tmp.append("--_--");
                        }
                    }
                }
                return tmp;
            }

        });
    }

    /**
     * Notifies the selection service that a viewer has a new selection
     */
    private void fireSelectionChanged(ISelection selection) {
        SelectionChangedEvent e = new SelectionChangedEvent(this, selection);
        for (ISelectionChangedListener l : getSelectionListeners()) {
            l.selectionChanged(e);
        }
    }

    private void updateModelViewActions() {
        // the actions aren't initialized therefore we return
        if (createDiagramAction == null)
            return;

        boolean enabled = (currFile != null);

        createDiagramAction.setEnabled(enabled);
        createDomainDiagramAction.setEnabled(enabled);
        validationAction.setEnabled(enabled);
    }

    private void updateTitle(String filename) {
        if (filename != null) {
            if (filename.length() == 0)
                filename = "New File...";
            getSite().getShell().setText("Onotoa - " + filename);
        } else {
            getSite().getShell().setText("Onotoa");
        }
    }

    private void checkSavedState() {
        if (currFile != null) {
            currFile.eAdapters().remove(dirtyListener);
            WorkspaceCommandStackImpl cmdStack = (WorkspaceCommandStackImpl) getEditingDomain().getCommandStack();
            if (cmdStack.isSaveNeeded()) {
                if (MessageDialog.openQuestion(getViewSite().getShell(), "Unsaved model",
                        "Your model is not saved. Do you want to save now?")) {
                    doSave(null);
                }
            }
        }
    }

    private void hookContextMenu() {
        MenuManager menuMgr = new MenuManager("#PopupMenu");
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                ModelView.this.fillContextMenu(manager);
            }
        });
        Menu menu = menuMgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);
        getSite().registerContextMenu(menuMgr, viewer);
    }

    private void contributeToActionBars() {
        IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
    }

    private void fillLocalPullDown(IMenuManager manager) {
        manager.add(createDiagramAction);
        manager.add(createDomainDiagramAction);
        manager.add(validationAction);

        manager.add(new Separator());
    }

    private void fillContextMenu(IMenuManager manager) {
        if (currFile == null) {
            return;
        }

        if (createDiagramAction.isEnabled())
            manager.add(createDiagramAction);

        if (createDomainDiagramAction.isEnabled())
            manager.add(createDomainDiagramAction);

        if (createTopicAction.isEnabled())
            manager.add(createTopicAction);

        if (renameAction.isEnabled()) {
            manager.add(renameAction);
        }

        if (deleteDiagramAction.isEnabled())
            manager.add(deleteDiagramAction);

        if (deleteConstructAction.isEnabled())
            manager.add(deleteConstructAction);

        manager.add(new Separator());

        if (createNameConstraintAction.isEnabled())
            manager.add(createNameConstraintAction);
        if (createOccurrenceConstraintAction.isEnabled())
            manager.add(createOccurrenceConstraintAction);
        if (createItemIdenifierConstraintAction.isEnabled())
            manager.add(createItemIdenifierConstraintAction);
        if (createSubjectIdenifierConstraintAction.isEnabled())
            manager.add(createSubjectIdenifierConstraintAction);
        if (createSubjectLocatorConstraintAction.isEnabled())
            manager.add(createSubjectLocatorConstraintAction);

        // add enabled actions from extensions
        List<ModelViewExtensionInfo> mveInfos = TmcleditEditPlugin.getExtensionManager()
                .getModelViewExtensionInfos();
        for (ModelViewExtensionInfo mve : mveInfos) {
            for (UpdateAction a : mve.getProvider().getActions()) {
                if (a.isEnabled())
                    manager.add(a);
            }
        }

    }

    private void fillLocalToolBar(IToolBarManager manager) {
        validationAction.setEnabled(currFile != null);
        manager.add(validationAction);
        manager.add(new SyncAction("Syncronize", IAction.AS_CHECK_BOX, syncView));
        manager.add(new Separator());
        manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));

    }

    private void makeActions() {
        validationAction = new ValidateAction(getSite());

        doubleClickAction = new Action() {
            @Override
            public void run() {
                ISelection selection = viewer.getSelection();
                Object obj = ((IStructuredSelection) selection).getFirstElement();
                ((AbstractModelViewNode) obj).handleDoubleClick();
            }
        };
        deleteDiagramAction = new DeleteDiagramAction(this);
        deleteConstructAction = new DeleteTMCLConstruct(this);
        createDiagramAction = new CreateDiagramAction(this);
        createDomainDiagramAction = new CreateDomainDiagramAction(this);
        createTopicAction = new CreateTopicAction(this);
        renameAction = new RenameAction(this);

        createNameConstraintAction = new CreateNameConstraintAction(this);
        createOccurrenceConstraintAction = new CreateOccurrenceConstraintAction(this);
        createItemIdenifierConstraintAction = new CreateItemIdenifierConstraintAction(this);
        createSubjectIdenifierConstraintAction = new CreateSubjectIdenifierConstraintAction(this);
        createSubjectLocatorConstraintAction = new CreateSubjectLocatorConstraintAction(this);

        boolean enabled = (currFile != null);
        createDiagramAction.setEnabled(enabled);
        createDomainDiagramAction.setEnabled(enabled);
        validationAction.setEnabled(enabled);

        // add enabled actions from extensions
        List<ModelViewExtensionInfo> mveInfos = TmcleditEditPlugin.getExtensionManager()
                .getModelViewExtensionInfos();
        for (ModelViewExtensionInfo mve : mveInfos) {
            mve.getProvider().createActions(this);
        }
    }

    private void hookDoubleClickAction() {
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                doubleClickAction.run();
            }
        });
    }

    private void hookKeyListener() {
        viewer.getTree().addKeyListener(new org.eclipse.swt.events.KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
                if (sel.isEmpty())
                    return;

                AbstractModelViewNode obj = (AbstractModelViewNode) sel.getFirstElement();

                if (e.keyCode == SWT.F2) {
                    obj.handleRename();
                } else if (e.keyCode == SWT.ARROW_RIGHT) {
                    viewer.expandToLevel(obj, 1);
                } else if (e.keyCode == SWT.ARROW_LEFT) {
                    viewer.collapseToLevel(obj, AbstractTreeViewer.ALL_LEVELS);
                } else if (e.keyCode == SWT.DEL) {
                    if (deleteConstructAction.isEnabled()) {
                        deleteConstructAction.run();
                    } else if (deleteDiagramAction.isEnabled()) {
                        deleteDiagramAction.run();
                    }

                }
                e.doit = false;
            }
        });
    }

    private final class SyncAction extends Action {
        private SyncAction(String text, int style, boolean checked) {
            super(text, style);
            setChecked(checked);
        }

        @Override
        public void run() {
            syncView = this.isChecked();
        }

        @Override
        public ImageDescriptor getImageDescriptor() {
            return PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_ELCL_SYNCED);
        }
    }

    class ViewLabelProvider extends LabelProvider {

        @Override
        public String getText(Object obj) {
            return ((AbstractModelViewNode) obj).getName();
        }

        @Override
        public Image getImage(Object obj) {
            return ((AbstractModelViewNode) obj).getImage();
        }
    }

    class NameSorter extends TreePathViewerSorter {
        @Override
        public int category(Object element) {
            if (element instanceof TreeSubjectIdentifier) {
                return 4;
            }
            if (element instanceof TreeSubjectLocator) {
                return 5;
            }
            if (element instanceof TreeOccurrence) {
                return 3;
            }
            if (element instanceof TreeName) {
                return 2;
            }

            // extensions to the topic map schema should be the first nodes,
            // else the extension nodes are at the and of the list
            AbstractModelViewNode n = (AbstractModelViewNode) element;
            if (!(n instanceof TreeObject)) {
                if (n.getParent().getModel() instanceof TopicMapSchema)
                    return 0;
                else
                    return 6;
            }

            return 1;
        }
    }

    class ValidateJob extends UIJob {
        private boolean running = false;

        private FeedbackRunnable feedBackRunnable = new FeedbackRunnable();

        public ValidateJob() {
            super("Validate...");
        }

        @Override
        public IStatus runInUIThread(IProgressMonitor monitor) {
            if (currFile == null)
                return Status.OK_STATUS;

            running = true;

            IWorkbenchWindow activeWorkbenchWindow = getViewSite().getWorkbenchWindow();
            IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();

            File file = currFile;

            ModelValidator validator = new ModelValidator(file);

            List<ValidationResult> list = validator.validate(getEditingDomain().getCommandStack());

            try {
                ValidationErrorView vew = (ValidationErrorView) activePage.findView(ValidationErrorView.ID);

                if (list.size() > 0) {
                    if (vew == null)
                        vew = (ValidationErrorView) activePage.showView(ValidationErrorView.ID);
                }
                if (vew != null) {
                    feedBackRunnable.setList(list);
                    feedBackRunnable.setView(vew);
                    getViewSite().getWorkbenchWindow().getShell().getDisplay().syncExec(feedBackRunnable);
                }

            } catch (PartInitException e) {
                running = false;
                throw new RuntimeException(e);
            } finally {
                running = false;
            }

            return Status.OK_STATUS;
        }

        public boolean isRunning() {
            return running;
        }

        private class FeedbackRunnable implements Runnable {
            private List<ValidationResult> list;
            private ValidationErrorView vew;

            public void run() {
                vew.setValidationResults(list);
            }

            public void setList(List<ValidationResult> list) {
                this.list = list;
            }

            public void setView(ValidationErrorView vew) {
                this.vew = vew;
            }

        }

    }

    public void selectionChanged(SelectionChangedEvent event) {
        if (event.getSelectionProvider() != this)
            setSelection(event.getSelection());
    }

}