com.google.gwt.eclipse.core.clientbundle.ui.AddResourcesToClientBundleAction.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.eclipse.core.clientbundle.ui.AddResourcesToClientBundleAction.java

Source

/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package com.google.gwt.eclipse.core.clientbundle.ui;

import com.google.gdt.eclipse.core.AdapterUtilities;
import com.google.gdt.eclipse.core.JavaASTUtils;
import com.google.gdt.eclipse.core.ResourceUtils;
import com.google.gdt.eclipse.core.StatusUtilities;
import com.google.gwt.eclipse.core.GWTPlugin;
import com.google.gwt.eclipse.core.GWTPluginLog;
import com.google.gwt.eclipse.core.clientbundle.ClientBundleResource;
import com.google.gwt.eclipse.core.clientbundle.ClientBundleUtilities;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.PlatformUI;

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

/**
 * Adds resources to an existing ClientBundle subtype.
 */
@SuppressWarnings("restriction")
public class AddResourcesToClientBundleAction extends Action implements IActionDelegate {

    private static class AddResourcesJob implements IWorkspaceRunnable {

        private final IType clientBundle;

        private final List<ClientBundleResource> resources;

        public AddResourcesJob(IType clientBundle, List<ClientBundleResource> resources) {
            this.clientBundle = clientBundle;
            this.resources = resources;
        }

        public void run(IProgressMonitor monitor) throws CoreException {
            ICompilationUnit icu = clientBundle.getCompilationUnit();
            CompilationUnit cu = JavaASTUtils.parseCompilationUnit(icu);
            ImportRewrite importRewrite = StubUtility.createImportRewrite(cu, true);

            // Find the target type declaration
            TypeDeclaration typeDecl = JavaASTUtils.findTypeDeclaration(cu, clientBundle.getFullyQualifiedName());
            if (typeDecl == null) {
                throw new CoreException(StatusUtilities.newErrorStatus(
                        "Missing ClientBundle type " + clientBundle.getFullyQualifiedName(), GWTPlugin.PLUGIN_ID));
            }

            // We need to rewrite the AST of the ClientBundle type declaration
            ASTRewrite astRewrite = ASTRewrite.create(cu.getAST());
            ChildListPropertyDescriptor property = ASTNodes.getBodyDeclarationsProperty(typeDecl);
            ListRewrite listRewriter = astRewrite.getListRewrite(typeDecl, property);

            // Add the new resource methods
            boolean addComments = StubUtility.doAddComments(icu.getJavaProject());
            for (ClientBundleResource resource : resources) {
                listRewriter.insertLast(
                        resource.createMethodDeclaration(clientBundle, astRewrite, importRewrite, addComments),
                        null);
            }

            // Create the edit to add the methods and update the imports
            TextEdit rootEdit = new MultiTextEdit();
            rootEdit.addChild(astRewrite.rewriteAST());
            rootEdit.addChild(importRewrite.rewriteImports(null));

            // Apply the change to the compilation unit
            CompilationUnitChange cuChange = new CompilationUnitChange("Update ClientBundle", icu);
            cuChange.setSaveMode(TextFileChange.KEEP_SAVE_STATE);
            cuChange.setEdit(rootEdit);
            cuChange.perform(new NullProgressMonitor());
        }
    }

    private static IType findFirstTopLevelClientBundleType(IFile file) {
        try {
            IJavaElement element = JavaCore.create(file);
            if (element instanceof ICompilationUnit) {
                ICompilationUnit cu = (ICompilationUnit) element;
                if (cu.exists()) {
                    for (IType type : cu.getTypes()) {
                        if (ClientBundleUtilities.isClientBundle(cu.getJavaProject(), type)) {
                            return type;
                        }
                    }
                }
            }
        } catch (JavaModelException e) {
            GWTPluginLog.logError(e);
        }
        return null;
    }

    private IType clientBundleType;

    private IFile[] files;

    private IProject project;

    public void run(IAction action) {
        AddResourcesToClientBundleDialog dlg = new AddResourcesToClientBundleDialog(getShell(), project,
                clientBundleType, files);
        if (dlg.open() != Window.OK) {
            return;
        }

        IType clientBundle = dlg.getClientBundleType();
        try {
            // Update the type and open it
            addResourcesToClientBundle(clientBundle, dlg.getResources());
            ResourceUtils.openInDefaultEditor(getShell(), (IFile) clientBundle.getResource(), true);
        } catch (CoreException e) {
            ErrorDialog.openError(getShell(), "Error Adding Resources",
                    "One or more selected resources could not be added to the ClientBundle.", e.getStatus());
        }
    }

    public void selectionChanged(IAction action, ISelection selection) {
        // Reset our old initial selections
        project = null;
        clientBundleType = null;
        List<IFile> selectedFiles = new ArrayList<IFile>();

        if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
            IStructuredSelection structuredSelection = (IStructuredSelection) selection;
            Iterator<?> iter = structuredSelection.iterator();
            while (iter.hasNext()) {
                Object element = iter.next();

                IFile file = AdapterUtilities.getAdapter(element, IFile.class);
                if (file != null) {
                    // Set initial project if it's not already set
                    if (project == null) {
                        project = file.getProject();
                    }

                    // Try to set the initial ClientBundle type if it's not already set
                    if (clientBundleType == null) {
                        clientBundleType = findFirstTopLevelClientBundleType(file);
                        if (clientBundleType != null) {
                            // Ensure that initial project is the one containing the initial
                            // ClientBundle type
                            project = clientBundleType.getJavaProject().getProject();
                        }
                    }

                    // If the file looks like a ClientBundle resource, add it
                    if (ClientBundleResource.isProbableClientBundleResource(file)) {
                        selectedFiles.add(file);
                    }
                }
            }
        }
        files = selectedFiles.toArray(new IFile[0]);
    }

    private void addResourcesToClientBundle(IType clientBundle, List<ClientBundleResource> resources)
            throws CoreException {
        IWorkspaceRunnable op = new AddResourcesJob(clientBundle, resources);
        // Need to lock on the package fragment since we might have to create new
        // CssResource subtypes in addition to the ClientBundle interface.
        ISchedulingRule lock = clientBundle.getPackageFragment().getResource();
        ResourcesPlugin.getWorkspace().run(op, lock, IWorkspace.AVOID_UPDATE, null);
    }

    private Shell getShell() {
        return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
    }

}