com.technophobia.substeps.junit.action.OpenEditorAction.java Source code

Java tutorial

Introduction

Here is the source code for com.technophobia.substeps.junit.action.OpenEditorAction.java

Source

/*******************************************************************************
 * Copyright Technophobia Ltd 2012
 * 
 * This file is part of the Substeps Eclipse Plugin.
 * 
 * The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify
 * it under the terms of the Eclipse Public License v1.0.
 * 
 * The Substeps Eclipse Plugin is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Eclipse Public License for more details.
 * 
 * You should have received a copy of the Eclipse Public License
 * along with the Substeps Eclipse Plugin.  If not, see <http://www.eclipse.org/legal/epl-v10.html>.
 ******************************************************************************/
package com.technophobia.substeps.junit.action;

import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameMatch;
import org.eclipse.jdt.core.search.TypeNameMatchRequestor;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.ITextEditor;

import com.technophobia.eclipse.ui.NotifyingUiUpdater;
import com.technophobia.substeps.FeatureRunnerPlugin;
import com.technophobia.substeps.junit.ui.SubstepsFeatureMessages;
import com.technophobia.substeps.junit.ui.SubstepsRunSession;
import com.technophobia.substeps.supplier.Supplier;

public abstract class OpenEditorAction extends Action {
    protected String className;
    private final boolean activate;
    private final Supplier<SubstepsRunSession> substepsRunSessionSupplier;
    private final NotifyingUiUpdater<String> infoMessageUpdater;
    private final Shell shell;

    protected OpenEditorAction(final Supplier<SubstepsRunSession> substepsRunSessionSupplier,
            final NotifyingUiUpdater<String> infoMessageUpdater, final Shell shell, final String testClassName) {
        this(substepsRunSessionSupplier, infoMessageUpdater, shell, testClassName, true);
    }

    public OpenEditorAction(final Supplier<SubstepsRunSession> substepsRunSessionSupplier,
            final NotifyingUiUpdater<String> infoMessageUpdater, final Shell shell, final String className,
            final boolean activate) {
        super(SubstepsFeatureMessages.OpenEditorAction_action_label);
        this.substepsRunSessionSupplier = substepsRunSessionSupplier;
        this.infoMessageUpdater = infoMessageUpdater;
        this.shell = shell;
        this.className = className;
        this.activate = activate;
    }

    /*
     * @see IAction#run()
     */
    @Override
    public void run() {
        IEditorPart editor = null;
        try {
            final IJavaElement element = findElement(getLaunchedProject(), className);
            if (element == null) {
                MessageDialog.openError(getShell(), SubstepsFeatureMessages.OpenEditorAction_error_cannotopen_title,
                        SubstepsFeatureMessages.OpenEditorAction_error_cannotopen_message);
                return;
            }
            editor = JavaUI.openInEditor(element, activate, false);
        } catch (final CoreException e) {
            ErrorDialog.openError(getShell(), SubstepsFeatureMessages.OpenEditorAction_error_dialog_title,
                    SubstepsFeatureMessages.OpenEditorAction_error_dialog_message, e.getStatus());
            return;
        }
        if (!(editor instanceof ITextEditor)) {
            infoMessageUpdater.notify(SubstepsFeatureMessages.OpenEditorAction_message_cannotopen);
            return;
        }
        reveal((ITextEditor) editor);
    }

    protected Shell getShell() {
        return shell;
    }

    /**
     * @return the Java project, or <code>null</code>
     */
    protected IJavaProject getLaunchedProject() {
        return substepsRunSessionSupplier.get().getLaunchedProject();
    }

    protected String getClassName() {
        return className;
    }

    protected abstract IJavaElement findElement(IJavaProject project, String testClassName) throws CoreException;

    protected abstract void reveal(ITextEditor editor);

    protected final IType findType(final IJavaProject project, final String testClassName) {
        final IType[] result = { null };
        final String dottedName = testClassName.replace('$', '.'); // for nested
        // classes...
        try {
            PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
                @Override
                public void run(final IProgressMonitor monitor)
                        throws InvocationTargetException, InterruptedException {
                    try {
                        if (project != null) {
                            result[0] = internalFindType(project, dottedName, new HashSet<IJavaProject>(), monitor);
                        }
                        if (result[0] == null) {
                            final int lastDot = dottedName.lastIndexOf('.');
                            final TypeNameMatchRequestor nameMatchRequestor = new TypeNameMatchRequestor() {
                                @Override
                                public void acceptTypeNameMatch(final TypeNameMatch match) {
                                    result[0] = match.getType();
                                }
                            };
                            new SearchEngine().searchAllTypeNames(
                                    lastDot >= 0 ? dottedName.substring(0, lastDot).toCharArray() : null,
                                    SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
                                    (lastDot >= 0 ? dottedName.substring(lastDot + 1) : dottedName).toCharArray(),
                                    SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
                                    IJavaSearchConstants.TYPE, SearchEngine.createWorkspaceScope(),
                                    nameMatchRequestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
                        }
                    } catch (final JavaModelException e) {
                        throw new InvocationTargetException(e);
                    }
                }
            });
        } catch (final InvocationTargetException e) {
            FeatureRunnerPlugin.log(e);
        } catch (final InterruptedException e) {
            // user cancelled
        }
        return result[0];
    }

    private IType internalFindType(final IJavaProject project, final String testClassName,
            final Set<IJavaProject> visitedProjects, final IProgressMonitor monitor) throws JavaModelException {
        try {
            if (visitedProjects.contains(project))
                return null;
            monitor.beginTask("", 2); //$NON-NLS-1$
            IType type = project.findType(testClassName, new SubProgressMonitor(monitor, 1));
            if (type != null)
                return type;
            // fix for bug 87492: visit required projects explicitly to also
            // find not exported types
            visitedProjects.add(project);
            final IJavaModel javaModel = project.getJavaModel();
            final String[] requiredProjectNames = project.getRequiredProjectNames();
            final IProgressMonitor reqMonitor = new SubProgressMonitor(monitor, 1);
            reqMonitor.beginTask("", requiredProjectNames.length); //$NON-NLS-1$
            for (final String requiredProjectName : requiredProjectNames) {
                final IJavaProject requiredProject = javaModel.getJavaProject(requiredProjectName);
                if (requiredProject.exists()) {
                    type = internalFindType(requiredProject, testClassName, visitedProjects,
                            new SubProgressMonitor(reqMonitor, 1));
                    if (type != null)
                        return type;
                }
            }
            return null;
        } finally {
            monitor.done();
        }
    }
}