org.eclipse.objectteams.otdt.internal.ui.callinmarkers.UpdateRulerAction.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.objectteams.otdt.internal.ui.callinmarkers.UpdateRulerAction.java

Source

/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2004, 2008 Fraunhofer Gesellschaft, Munich, Germany,
 * for its Fraunhofer Institute for Computer Architecture and Software
 * Technology (FIRST), Berlin, Germany and Technical University Berlin,
 * Germany.
 * 
 * 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
 * $Id: UpdateRulerAction.java 23435 2010-02-04 00:14:38Z stephan $
 * 
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 * Fraunhofer FIRST - Initial API and implementation
 * Technical University Berlin - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otdt.internal.ui.callinmarkers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.javaeditor.IClassFileEditorInput;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.IVerticalRulerInfo;
import org.eclipse.objectteams.otdt.core.IOTType;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.internal.ui.OTDTUIPluginConstants;
import org.eclipse.objectteams.otdt.ui.IUpdateRulerActionExtender;
import org.eclipse.objectteams.otdt.ui.OTDTUIPlugin;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
import org.eclipse.ui.texteditor.ITextEditor;

/**
 * Action that is executed when the user right clicks on a binding marker at
 * the vertical ruler and chooses a mapping (bound role class or callin mapping)
 * from the ObjectTeams submenu.
 *
 * @author brcan
 * @version $Id: UpdateRulerAction.java 23435 2010-02-04 00:14:38Z stephan $
 */
public class UpdateRulerAction extends AbstractRulerActionDelegate {
    public final static String OT_PLAYEDBY_MENU_LABEL = OTDTUIPlugin
            .getResourceString("CallinMarker.menu_playedby_title"); //$NON-NLS-1$
    public final static String OT_CALLIN_MENU_LABEL = OTDTUIPlugin
            .getResourceString("CallinMarker.menu_callin_title"); //$NON-NLS-1$
    public final static String OT_CALLOUT_MENU_LABEL = OTDTUIPlugin
            .getResourceString("CallinMarker.menu_callout_title"); //$NON-NLS-1$

    private IEditorPart _editor = null;
    private IVerticalRulerInfo _rulerInfo = null;

    private List<IUpdateRulerActionExtender> extenders = null;

    public UpdateRulerAction() {
    }

    public void setActiveEditor(IAction callerAction, IEditorPart targetEditor) {
        _editor = targetEditor;

        super.setActiveEditor(callerAction, targetEditor);
    }

    protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {
        _rulerInfo = rulerInfo;

        return null;
    }

    public void menuAboutToShow(IMenuManager contextMenu) {
        IDocument document = null;
        int clickedLine = _rulerInfo.getLineOfLastMouseButtonActivity();
        if (this._editor instanceof ITextEditor) {
            ITextEditor textEditor = (ITextEditor) this._editor;
            document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
        }
        try {
            IMarker[] markers = findCallinMarkers();

            if (markers != null && markers.length != 0) {
                for (int idx = 0; idx < markers.length; idx++) {
                    IMarker curMarker = markers[idx];

                    int line = curMarker.getAttribute(IMarker.LINE_NUMBER, -1);
                    if (line != -1) {
                        if (line - 1 == clickedLine) // IMarker.LINE_NUMBER is 1-based, others are 0-based
                            insertTeamMenus(contextMenu, curMarker);
                    } else if (document != null) {
                        // markers in ClassFileEditor have no line number, must go via position:
                        int start = curMarker.getAttribute(IMarker.CHAR_START, -1);
                        try {
                            if (clickedLine == document.getLineOfOffset(start))
                                insertTeamMenus(contextMenu, curMarker);
                        } catch (BadLocationException e) {
                            /* nop */ }
                    }
                }
            }
        } catch (CoreException ex) {
            OTDTUIPlugin.logException("Problems extending ruler context menu", ex); //$NON-NLS-1$
        }
        // load and notify extenders:
        if (this.extenders == null)
            loadExtenders();
        for (IUpdateRulerActionExtender extender : this.extenders)
            extender.menuAboutToShow(contextMenu, document, this._editor, clickedLine);
    }

    private IMarker[] findCallinMarkers() throws CoreException {

        final IEditorInput editorInput = _editor.getEditorInput();
        if (editorInput instanceof IFileEditorInput) {
            IFileEditorInput fileEditorInput = (IFileEditorInput) editorInput;
            IFile file = fileEditorInput.getFile();

            IMarker[] result = CallinMarker.getAllBindingMarkers(file);
            return result;
        } else if (editorInput instanceof IClassFileEditorInput) {
            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            IMarker[] allMarkers = CallinMarker.getAllBindingMarkers(root);

            // now we have all CallinMarkers for all class files in the workspace, need to filter now: 
            IClassFile classFile = ((IClassFileEditorInput) editorInput).getClassFile();
            List<IMarker> filteredMarkers = new ArrayList<IMarker>(13);
            for (IMarker marker : allMarkers)
                if (JavaCore.isReferencedBy(classFile, marker))
                    filteredMarkers.add(marker);
            return filteredMarkers.toArray(new IMarker[filteredMarkers.size()]);
        }
        return null;
    }

    /** Get the context menu of kind 'markerKind', creating it if ondemand. */
    private IMenuManager getObjectTeamsMenu(IMenuManager contextMenu, String markerKind) {
        String label;
        if (CallinMarker.CALLIN_ID.equals(markerKind))
            label = OT_CALLIN_MENU_LABEL;
        else if (CallinMarker.CALLOUT_ID.equals(markerKind))
            label = OT_CALLOUT_MENU_LABEL;
        else
            label = OT_PLAYEDBY_MENU_LABEL;

        IMenuManager subMenu = getSubMenu(contextMenu, label);
        if (subMenu != null)
            return subMenu;

        MenuManager otMenu = new MenuManager(label, markerKind); // id cannot be null, re-use the markerKind
        if (contextMenu.isEmpty())
            contextMenu.add(otMenu);
        else // insert on top
            contextMenu.insertBefore(contextMenu.getItems()[0].getId(), otMenu);
        return otMenu;
    }

    private IAction createOpenEditorAction(String label, final IJavaElement target) {
        Action result = new Action(label) {
            public void run() {
                try {
                    IEditorPart part = EditorUtility.openInEditor(target);
                    if (target.exists()) // also initializes source positions if necessary
                        EditorUtility.revealInEditor(part, target);
                } catch (PartInitException ex) {
                    OTDTUIPlugin.logException("Problems initializing editor", ex); //$NON-NLS-1$
                }
            }
        };

        return result;
    }

    List<IMember> getMappings(IMarker marker) throws CoreException {
        Object attr = marker.getAttribute(CallinMarker.ATTR_ROLE_ELEMENTS);
        if (attr == null || !(attr instanceof String))
            return null;
        String str = (String) attr;
        List<IMember> result = new ArrayList<IMember>();
        int start = 0;
        int pos;
        while ((pos = str.indexOf('\n', start)) != -1) {
            result.add((IMember) JavaCore.create(str.substring(start, pos)));
            start = pos + 1;
        }
        return result;
    }

    private void insertTeamMenus(IMenuManager contextMenu, IMarker marker) throws CoreException {
        List<IMember> mappings = getMappings(marker);
        if (mappings == null)
            return;

        IMenuManager otMenu = getObjectTeamsMenu(contextMenu, marker.getType());

        for (IMember curMapping : mappings) {
            IType type = (IType) (curMapping.getAncestor(IJavaElement.TYPE));
            IOTType otType = OTModelManager.getOTElement(type); // FIXME(SH): doesn't find role files??? (try StubUtility2)
            if (otType == null || !otType.isRole())
                continue;

            IOTType teamType = ((IRoleType) otType).getTeam();

            IMenuManager curTeamMenu = null;

            if (!isSubMenuContained(otMenu, teamType.getElementName())) {
                curTeamMenu = new MenuManager(teamType.getElementName());
                otMenu.add(curTeamMenu);
            } else {
                curTeamMenu = getSubMenu(otMenu, teamType.getElementName());
            }
            String actLabel = getMappingLabel(type, curMapping);
            curTeamMenu.add(createOpenEditorAction(actLabel, curMapping));
        }
    }

    private String getMappingLabel(IType type, IMember mapping) {
        if (type.equals(mapping))
            return type.getElementName();

        return type.getElementName() + ": " + mapping.getElementName(); //$NON-NLS-1$
    }

    private IMenuManager getSubMenu(IMenuManager otMenu, String subMenuName) {
        if (otMenu == null)
            return null;

        IContributionItem[] items = otMenu.getItems();

        for (int idx = 0; idx < items.length; idx++) {
            if (items[idx] instanceof IMenuManager) {
                MenuManager cur = (MenuManager) items[idx];
                if (cur.getMenuText().equals(subMenuName)) {
                    return cur;
                }
            }
        }

        return null;
    }

    private boolean isSubMenuContained(IMenuManager menu, String subMenuName) {
        return getSubMenu(menu, subMenuName) != null;
    }

    private void loadExtenders() {
        this.extenders = new ArrayList<IUpdateRulerActionExtender>();
        IConfigurationElement[] configs = RegistryFactory.getRegistry().getConfigurationElementsFor(
                OTDTUIPluginConstants.UIPLUGIN_ID, OTDTUIPluginConstants.UPDATE_RULER_ACTION_EXTENDER_ID);
        for (IConfigurationElement config : configs) {
            try {
                if (this._editor.getClass().getName().equals(
                        config.getAttribute(OTDTUIPluginConstants.UPDATE_RULER_ACTION_EXTENDER_EDITORCLASS)))
                    this.extenders.add((IUpdateRulerActionExtender) config
                            .createExecutableExtension(OTDTUIPluginConstants.UPDATE_RULER_ACTION_EXTENDER_CLASS));
            } catch (CoreException e) {
                OTDTUIPlugin.log(e);
            }
        }
    }
}