org.eclipse.objectteams.otdt.internal.ui.handlers.CompareWithBaseMethodHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.objectteams.otdt.internal.ui.handlers.CompareWithBaseMethodHandler.java

Source

/**********************************************************************
 * This file is part of "Object Teams Development Tooling"-Software
 * 
 * Copyright 2009, Stephan Herrmann.
 * 
 * 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$
 * 
 * Please visit http://www.eclipse.org/objectteams for updates and contact.
 * 
 * Contributors:
 * Stephan Herrmann - Initial API and implementation
 **********************************************************************/
package org.eclipse.objectteams.otdt.internal.ui.handlers;

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

import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.CompareUI;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.objectteams.otdt.core.ICallinMapping;
import org.eclipse.objectteams.otdt.core.IMethodMapping;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.internal.ui.OTDTUIMessages;
import org.eclipse.objectteams.otdt.internal.ui.compare.CompareBoundMethodsEditorInput;
import org.eclipse.objectteams.otdt.ui.OTDTUIPlugin;
import org.eclipse.team.internal.ui.IPreferenceIds;
import org.eclipse.team.internal.ui.TeamUIPlugin;
import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISources;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.handlers.HandlerUtil;

/**
 * This handler implements the "Compare with ... Bound base method" command.
 * 
 * @author stephan
 * @since 1.4.0
 */
public class CompareWithBaseMethodHandler extends AbstractHandler implements IStructuredSelection {

    IMethod roleMethod;
    IMethod baseMethod;
    ICallinMapping callinMapping;
    private IStructuredSelection selection;
    private IWorkbenchPage page;

    // === Implement IStructuredSelection: ===
    public boolean isEmpty() {
        return false;
    }

    public List toList() {
        List<IMethod> result = new ArrayList<IMethod>(2);
        result.add(roleMethod);
        result.add(baseMethod);
        return result;
    }

    public Object[] toArray() {
        return new Object[] { roleMethod, baseMethod };
    }

    public int size() {
        return 2;
    }

    public Iterator iterator() {
        return null;
    } // unused method

    public Object getFirstElement() {
        return null;
    } // unused method
    // === End IStructuredSelection ===

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.AbstractHandler#setEnabled(java.lang.Object)
     */
    @Override
    public void setEnabled(Object evaluationContext) {
        // fetch UI-context:
        IWorkbenchSite site = (IWorkbenchSite) HandlerUtil.getVariable(evaluationContext,
                ISources.ACTIVE_SITE_NAME);
        if (site == null)
            return; // happens on workbench shutdown
        this.page = site.getPage();

        // initialize roleMethod and/or callinMapping from current selection:
        this.roleMethod = null;
        this.callinMapping = null;
        ISelection sel = (ISelection) HandlerUtil.getVariable(evaluationContext,
                ISources.ACTIVE_CURRENT_SELECTION_NAME);
        if (sel instanceof IStructuredSelection) {
            this.selection = (IStructuredSelection) sel;
            if (this.selection.size() == 1) {
                Object element = this.selection.getFirstElement();
                if (element instanceof IMethod) {
                    IMethod method = (IMethod) element;
                    try {
                        if ((method.getFlags() & ExtraCompilerModifiers.AccCallin) != 0) {
                            this.roleMethod = method;
                            setBaseEnabled(true);
                            return;
                        }
                    } catch (JavaModelException e) {
                        // nop, can't read method.getFlags();
                    }
                } else if (element instanceof ICallinMapping) {
                    this.callinMapping = (ICallinMapping) element;
                    setBaseEnabled(true);
                    return;
                }
            }
        }
        setBaseEnabled(false);
    }

    public Object execute(ExecutionEvent event) throws ExecutionException {
        this.baseMethod = null;
        if (this.roleMethod != null && this.callinMapping == null) {
            // find a callin mapping by which this role method is bound:
            IType type = (IType) roleMethod.getParent();
            IRoleType roleType = (IRoleType) OTModelManager.getOTElement(type);
            for (IMethodMapping mapping : roleType.getMethodMappings(IRoleType.CALLINS)) {
                if (mapping.getRoleMethod().equals(this.roleMethod))
                    if (this.callinMapping == null) {
                        this.callinMapping = (ICallinMapping) mapping;
                    } else {
                        MessageDialog.openError(null, // shell 
                                OTDTUIMessages.CompareWithBaseMethodAction_errorTitle,
                                OTDTUIMessages.CompareWithBaseMethodAction_ambiguousBindingsError);
                        return null;
                    }
            }
        }
        if (this.callinMapping != null) {
            // find the methods bound by this callin mapping:
            this.roleMethod = this.callinMapping.getRoleMethod();
            IMethod[] baseMethods;
            try {
                baseMethods = this.callinMapping.getBoundBaseMethods();
            } catch (JavaModelException e) {
                throw new ExecutionException(e.getMessage());
            }
            if (baseMethods.length > 1) {
                MessageDialog.openError(null, // shell 
                        OTDTUIMessages.CompareWithBaseMethodAction_errorTitle,
                        OTDTUIMessages.CompareWithBaseMethodAction_multipleBaseMethodsError);
                return null;
            }
            this.baseMethod = baseMethods[0];
        }

        if (this.roleMethod != null && this.baseMethod != null)
            openCompareEditor();

        return null;
    }

    void openCompareEditor() {
        try {
            CompareEditorInput input = new CompareBoundMethodsEditorInput(this.roleMethod, this.baseMethod,
                    this.page);
            IWorkbenchPage workBenchPage = this.page;
            IEditorPart editor = findReusableCompareEditor(input, workBenchPage);
            if (editor != null) {
                IEditorInput otherInput = editor.getEditorInput();
                if (otherInput.equals(input)) {
                    // simply provide focus to editor
                    if (OpenStrategy.activateOnOpen())
                        workBenchPage.activate(editor);
                    else
                        workBenchPage.bringToTop(editor);
                } else {
                    // if editor is currently not open on that input either re-use
                    // existing
                    CompareUI.reuseCompareEditor(input, (IReusableEditor) editor);
                    if (OpenStrategy.activateOnOpen())
                        workBenchPage.activate(editor);
                    else
                        workBenchPage.bringToTop(editor);
                }
            } else {
                CompareUI.openCompareEditor(input, OpenStrategy.activateOnOpen());
            }
        } catch (CoreException ce) {
            OTDTUIPlugin.log(ce);
        }
    }

    /**
     * Returns an editor that can be re-used. An open compare editor that
     * has un-saved changes cannot be re-used.
     * @param input the input being opened
     * @param page 
     * @return an EditorPart or <code>null</code> if none can be found
     */
    IEditorPart findReusableCompareEditor(CompareEditorInput input, IWorkbenchPage page) {
        IEditorReference[] editorRefs = page.getEditorReferences();
        // first loop looking for an editor with the same input
        for (int i = 0; i < editorRefs.length; i++) {
            IEditorPart part = editorRefs[i].getEditor(false);
            if (part != null && (part.getEditorInput() instanceof CompareBoundMethodsEditorInput)
                    && part instanceof IReusableEditor && part.getEditorInput().equals(input)) {
                return part;
            }
        }

        // if none found and "Reuse open compare editors" preference is on use
        // a non-dirty editor
        if (isReuseOpenEditor()) {
            for (int i = 0; i < editorRefs.length; i++) {
                IEditorPart part = editorRefs[i].getEditor(false);
                if (part != null && (part.getEditorInput() instanceof SaveableCompareEditorInput)
                        && part instanceof IReusableEditor && !part.isDirty()) {
                    return part;
                }
            }
        }

        // no re-usable editor found
        return null;
    }

    boolean isReuseOpenEditor() {
        return TeamUIPlugin.getPlugin().getPreferenceStore().getBoolean(IPreferenceIds.REUSE_OPEN_COMPARE_EDITOR);
    }
}