org.springframework.ide.eclipse.quickfix.processors.ClassAttributeQuickAssistProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.ide.eclipse.quickfix.processors.ClassAttributeQuickAssistProcessor.java

Source

/*******************************************************************************
 *  Copyright (c) 2012 VMware, Inc.
 *  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:
 *      VMware, Inc. - initial API and implementation
 *******************************************************************************/
package org.springframework.ide.eclipse.quickfix.processors;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.ClassFile;
import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.PackageFragment;
import org.eclipse.jdt.internal.ui.text.correction.NameMatcher;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
import org.springframework.ide.eclipse.quickfix.Activator;
import org.springframework.ide.eclipse.quickfix.proposals.CreateNewClassQuickFixProposal;
import org.springframework.ide.eclipse.quickfix.proposals.RenameToSimilarNameQuickFixProposal;
import org.springsource.ide.eclipse.commons.core.StatusHandler;

/**
 * Quick assist processor for bean class attribute in beans XML editor.
 * @author Terry Denney
 * @author Leo Dos Santos
 * @author Christian Dupuis
 * @since 2.0
 */
public class ClassAttributeQuickAssistProcessor extends BeanQuickAssistProcessor {

    private class SimilarCUFindingVisitor implements IResourceVisitor {

        private final Set<String> suggestedClassNames = new HashSet<String>();

        private final String toMatch;

        private SimilarCUFindingVisitor(String toMatch) {
            this.toMatch = toMatch;
        }

        public List<String> getSuggestedClassNames() {
            List<String> result = new ArrayList<String>(suggestedClassNames);
            Collections.sort(result, new NameSuggestionComparator(toMatch));
            return result;
        }

        public boolean visit(IResource resource) throws CoreException {
            if (resource instanceof IFile) {
                IFile file = (IFile) resource;
                String fileExtension = file.getFullPath().getFileExtension();
                if (fileExtension == null) {
                    return false;
                }

                if (fileExtension.equals("java")) {
                    ICompilationUnit cu = JavaCore.createCompilationUnitFrom(file);

                    if (cu instanceof CompilationUnit) {
                        CompilationUnit c = (CompilationUnit) cu;
                        IType[] types = c.getAllTypes();
                        for (IType type : types) {
                            if (NameMatcher.isSimilarName(type.getElementName(), toMatch)) {
                                suggestedClassNames.add(type.getFullyQualifiedName());
                            }
                        }
                    }
                    return false;
                } else if (fileExtension.equals("class")) {
                    IClassFile classFile = JavaCore.createClassFileFrom(file);
                    IType type = classFile.getType();
                    if (type != null) {
                        if (NameMatcher.isSimilarName(type.getElementName(), toMatch)) {
                            suggestedClassNames.add(type.getFullyQualifiedName());
                        }
                    }
                    return false;
                }
                return true;
            }
            return true;
        }

        public void visitJar(JarPackageFragmentRoot jarRoot) throws CoreException {
            IJavaElement[] children = jarRoot.getChildren();
            for (IJavaElement child : children) {
                if (child instanceof PackageFragment) {
                    visitPackageFragment((PackageFragment) child);
                }
            }
        }

        public void visitPackageFragment(PackageFragment fragment) throws JavaModelException {
            IJavaElement[] grandChildren = fragment.getChildren();
            for (IJavaElement grandChild : grandChildren) {
                if (grandChild instanceof ClassFile) {
                    ClassFile classFile = (ClassFile) grandChild;
                    IType type = classFile.getType();
                    if (NameMatcher.isSimilarName(type.getElementName(), toMatch)) {
                        suggestedClassNames.add(type.getFullyQualifiedName());
                    }
                }
            }

        }

    }

    private final Set<String> propertyNames;

    private final int numConstructorArgs;

    private final IJavaProject javaProject;

    public ClassAttributeQuickAssistProcessor(int offset, int length, String text, IProject project,
            boolean missingEndQuote, Set<String> propertyNames, int numConstructorArgs) {
        super(offset, length, text, missingEndQuote);

        this.propertyNames = propertyNames;
        this.numConstructorArgs = numConstructorArgs;

        this.javaProject = JavaCore.create(project).getJavaProject();
    }

    public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
        List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();

        // find similar classes and add as proposals
        String className;
        int lastDotPos = text.lastIndexOf(".");
        if (lastDotPos < 0) {
            className = text;
        } else {
            className = text.substring(lastDotPos + 1);
        }

        try {
            SimilarCUFindingVisitor visitor = new SimilarCUFindingVisitor(className);
            IPackageFragmentRoot[] fragmentRoots = javaProject.getAllPackageFragmentRoots();
            for (IPackageFragmentRoot fragmentRoot : fragmentRoots) {
                if (fragmentRoot instanceof JarPackageFragmentRoot) {
                    visitor.visitJar((JarPackageFragmentRoot) fragmentRoot);
                }
                IResource resource = fragmentRoot.getResource();
                if (resource != null) {
                    resource.accept(visitor);
                }
            }
            List<String> suggestedClassNames = visitor.getSuggestedClassNames();
            for (String suggestedClassName : suggestedClassNames) {
                proposals.add(new RenameToSimilarNameQuickFixProposal(suggestedClassName, offset, length,
                        missingEndQuote));
            }

            proposals.add(new CreateNewClassQuickFixProposal(offset, length, text, missingEndQuote, javaProject,
                    propertyNames, numConstructorArgs));

            return proposals.toArray(new ICompletionProposal[proposals.size()]);
        } catch (CoreException e1) {
            StatusHandler.log(new Status(Status.ERROR, Activator.PLUGIN_ID, "Cound not compute proposals."));
        }

        return new ICompletionProposal[0];
    }

}