org.eclipse.wst.jsdt.internal.ui.compare.JavaHistoryActionImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wst.jsdt.internal.ui.compare.JavaHistoryActionImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.jsdt.internal.ui.compare;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import org.eclipse.compare.HistoryItem;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.ResourceNode;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFileState;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.RewriteSessionEditProcessor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.IMember;
import org.eclipse.wst.jsdt.core.ISourceRange;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.dom.AST;
import org.eclipse.wst.jsdt.core.dom.ASTNode;
import org.eclipse.wst.jsdt.core.dom.ASTParser;
import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
import org.eclipse.wst.jsdt.core.dom.TypeDeclaration;
import org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.wst.jsdt.internal.corext.dom.NodeFinder;
import org.eclipse.wst.jsdt.internal.corext.util.Strings;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.actions.SelectionConverter;
import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaEditor;

/**
 * Base class for the "Replace with local history"
 * and "Add from local history" actions.
 */
abstract class JavaHistoryActionImpl /* extends Action implements IActionDelegate*/ {

    private boolean fModifiesFile;
    private ISelection fSelection;

    JavaHistoryActionImpl(boolean modifiesFile) {
        fModifiesFile = modifiesFile;
    }

    ISelection getSelection() {
        return fSelection;
    }

    final IFile getFile(Object input) {
        return JavaElementHistoryPageSource.getInstance().getFile(input);
    }

    final ITypedElement[] buildEditions(ITypedElement target, IFile file) {

        // setup array of editions
        IFileState[] states = null;
        // add available editions
        try {
            states = file.getHistory(null);
        } catch (CoreException ex) {
            JavaScriptPlugin.log(ex);
        }

        int count = 1;
        if (states != null)
            count += states.length;

        ITypedElement[] editions = new ITypedElement[count];
        editions[0] = new ResourceNode(file);
        if (states != null)
            for (int i = 0; i < states.length; i++)
                editions[i + 1] = new HistoryItem(target, states[i]);
        return editions;
    }

    final Shell getShell() {
        if (fEditor != null)
            return fEditor.getEditorSite().getShell();
        return JavaScriptPlugin.getActiveWorkbenchShell();
    }

    /**
     * Tries to find the given element in a working copy.
     */
    final IJavaScriptElement getWorkingCopy(IJavaScriptElement input) {
        // TODO: With new working copy story: original == working copy.
        // Note that the previous code could result in a reconcile as side effect. Should check if that
        // is still required.
        return input;
    }

    final ASTNode getBodyContainer(JavaScriptUnit root, IMember parent) throws JavaScriptModelException {
        ISourceRange sourceRange = parent.getNameRange();
        ASTNode parentNode = NodeFinder.perform(root, sourceRange);
        do {
            if (parentNode instanceof TypeDeclaration)
                return parentNode;
            parentNode = parentNode.getParent();
        } while (parentNode != null);
        return null;
    }

    /**
     * Returns true if the given file is open in an editor.
     */
    final boolean beingEdited(IFile file) {
        IDocumentProvider dp = JavaScriptPlugin.getDefault().getCompilationUnitDocumentProvider();
        FileEditorInput input = new FileEditorInput(file);
        return dp.getDocument(input) != null;
    }

    /**
     * Returns an IMember or null.
     */
    final IMember getEditionElement(ISelection selection) {

        if (selection instanceof IStructuredSelection) {
            IStructuredSelection ss = (IStructuredSelection) selection;
            if (ss.size() == 1) {
                Object o = ss.getFirstElement();
                if (o instanceof IMember) {
                    IMember m = (IMember) o;
                    if (m.exists() && !m.isBinary() && JavaStructureCreator.hasEdition(m))
                        return m;
                }
            }
        }
        return null;
    }

    final boolean isEnabled(IFile file) {
        if (file == null || !file.exists())
            return false;
        if (fModifiesFile) {
            // without validate/edit we would do this:
            //    return !file.isReadOnly();
            // with validate/edit we have to return true
            return true;
        }
        return true;
    }

    boolean isEnabled(ISelection selection) {
        IMember m = getEditionElement(selection);
        if (m == null)
            return false;
        IFile file = getFile(m);
        if (!isEnabled(file))
            return false;
        return true;
    }

    void applyChanges(ASTRewrite rewriter, final IDocument document, final ITextFileBuffer textFileBuffer,
            Shell shell, boolean inEditor, Map options)
            throws CoreException, InvocationTargetException, InterruptedException {

        MultiTextEdit edit = new MultiTextEdit();
        try {
            TextEdit res = rewriter.rewriteAST(document, options);
            edit.addChildren(res.removeChildren());
        } catch (IllegalArgumentException e) {
            JavaScriptPlugin.log(e);
        }

        try {
            new RewriteSessionEditProcessor(document, edit, TextEdit.UPDATE_REGIONS).performEdits();
        } catch (BadLocationException e) {
            JavaScriptPlugin.log(e);
        }

        IRunnableWithProgress r = new IRunnableWithProgress() {
            public void run(IProgressMonitor pm) throws InvocationTargetException {
                try {
                    textFileBuffer.commit(pm, false);
                } catch (CoreException ex) {
                    throw new InvocationTargetException(ex);
                }
            }
        };

        if (inEditor) {
            // we don't show progress
            r.run(new NullProgressMonitor());
        } else {
            PlatformUI.getWorkbench().getProgressService().run(true, false, r);
        }
    }

    static String trimTextBlock(String content, String delimiter, IJavaScriptProject currentProject) {
        if (content != null) {
            String[] lines = Strings.convertIntoLines(content);
            if (lines != null) {
                Strings.trimIndentation(lines, currentProject);
                return Strings.concatenate(lines, delimiter);
            }
        }
        return null;
    }

    final JavaEditor getEditor(IFile file) {
        FileEditorInput fei = new FileEditorInput(file);
        IWorkbench workbench = JavaScriptPlugin.getDefault().getWorkbench();
        IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
        for (int i = 0; i < windows.length; i++) {
            IWorkbenchPage[] pages = windows[i].getPages();
            for (int x = 0; x < pages.length; x++) {
                IEditorPart[] editors = pages[x].getDirtyEditors();
                for (int z = 0; z < editors.length; z++) {
                    IEditorPart ep = editors[z];
                    if (ep instanceof JavaEditor) {
                        JavaEditor je = (JavaEditor) ep;
                        if (fei.equals(je.getEditorInput()))
                            return (JavaEditor) ep;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Executes this action with the given selection.
     */
    public abstract void run(ISelection selection);

    //---- Action

    private JavaEditor fEditor;
    private String fTitle;
    private String fMessage;

    void init(JavaEditor editor, String title, String message) {
        fEditor = editor;
        fTitle = title;
        fMessage = message;
    }

    final JavaEditor getEditor() {
        return fEditor;
    }

    final public void runFromEditor(IAction uiProxy) {

        // this run is called from Editor
        IJavaScriptElement element = null;
        try {
            element = SelectionConverter.getElementAtOffset(fEditor);
        } catch (JavaScriptModelException e) {
            // ignored
        }

        fSelection = element != null ? new StructuredSelection(element) : StructuredSelection.EMPTY;
        boolean isEnabled = isEnabled(fSelection);
        uiProxy.setEnabled(isEnabled);

        if (!isEnabled) {
            MessageDialog.openInformation(getShell(), fTitle, fMessage);
            return;
        }
        run(fSelection);
    }

    boolean checkEnabled() {
        IJavaScriptUnit unit = SelectionConverter.getInputAsCompilationUnit(fEditor);
        IFile file = getFile(unit);
        return isEnabled(file);
    }

    final public void update(IAction uiProxy) {
        uiProxy.setEnabled(checkEnabled());
    }

    //---- IActionDelegate

    final public void selectionChanged(IAction uiProxy, ISelection selection) {
        fSelection = selection;
        uiProxy.setEnabled(isEnabled(selection));
    }

    final public void run(IAction action) {
        run(fSelection);
    }

    static JavaScriptUnit parsePartialCompilationUnit(IJavaScriptUnit unit) {

        if (unit == null) {
            throw new IllegalArgumentException();
        }
        try {
            ASTParser c = ASTParser.newParser(AST.JLS3);
            c.setSource(unit);
            c.setFocalPosition(0);
            c.setResolveBindings(false);
            c.setWorkingCopyOwner(null);
            ASTNode result = c.createAST(null);
            return (JavaScriptUnit) result;
        } catch (IllegalStateException e) {
            // convert ASTParser's complaints into old form
            throw new IllegalArgumentException();
        }
    }
}