org.springframework.ide.eclipse.quickfix.hyperlinks.AutowireHyperlinkDetector.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.ide.eclipse.quickfix.hyperlinks.AutowireHyperlinkDetector.java

Source

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

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.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlinkDetector;
import org.eclipse.jdt.ui.actions.SelectionDispatchAction;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.springframework.ide.eclipse.beans.core.BeansCorePlugin;
import org.springframework.ide.eclipse.beans.core.autowire.internal.provider.AutowireDependencyProvider;
import org.springframework.ide.eclipse.beans.core.model.IBean;
import org.springframework.ide.eclipse.beans.core.model.IBeansConfig;
import org.springframework.ide.eclipse.beans.core.model.IBeansModel;
import org.springframework.ide.eclipse.beans.core.model.IBeansProject;
import org.springframework.ide.eclipse.core.java.IProjectClassLoaderSupport;
import org.springframework.ide.eclipse.core.java.IProjectClassLoaderSupport.IProjectClassLoaderAwareCallback;
import org.springframework.ide.eclipse.core.java.JdtUtils;
import org.springsource.ide.eclipse.commons.core.StatusHandler;

/**
 * @author Terry Denney
 * @since 3.3.0
 */
public class AutowireHyperlinkDetector extends JavaElementHyperlinkDetector {

    @Override
    protected void addHyperlinks(List<IHyperlink> hyperlinksCollector, final IRegion wordRegion,
            SelectionDispatchAction openAction, IJavaElement element, boolean qualify, JavaEditor editor) {

        if (element instanceof ILocalVariable) {
            ILocalVariable localVariable = (ILocalVariable) element;
            IJavaElement parent = localVariable.getParent();
            if (parent instanceof IMethod) {
                IMethod parentMethod = (IMethod) parent;
                if (parentMethod.getAnnotation("Autowired") != null) {
                    String typeSignature = localVariable.getTypeSignature();
                    addHyperlinksHelper(typeSignature, localVariable, hyperlinksCollector);
                }
            }
        } else if (element instanceof IField) {
            IField field = (IField) element;
            if (field.getAnnotation("Autowired") != null) {
                try {
                    String typeSignature = field.getTypeSignature();
                    addHyperlinksHelper(typeSignature, field, hyperlinksCollector);
                } catch (JavaModelException e) {
                    StatusHandler.log(e.getStatus());
                }
            }
        }
    }

    private void addHyperlinksHelper(String typeSignature, IJavaElement element,
            List<IHyperlink> hyperlinksCollector) {
        String typeName = Signature.toString(typeSignature);
        try {
            IType type = getParentType(element);
            if (type != null) {
                String[][] qualifiedTypeNames = type.resolveType(typeName);
                if (qualifiedTypeNames != null) {
                    for (String[] typeNameSegments : qualifiedTypeNames) {
                        StringBuilder qualifiedTypeName = new StringBuilder();
                        for (String typeNameSegment : typeNameSegments) {
                            if (qualifiedTypeName.length() > 0) {
                                qualifiedTypeName.append(".");
                            }
                            qualifiedTypeName.append(typeNameSegment);
                        }

                        addHyperlinksHelper(qualifiedTypeName.toString(), element.getJavaProject().getProject(),
                                hyperlinksCollector);
                    }
                }
            }
        } catch (JavaModelException e) {
            StatusHandler.log(e.getStatus());
        }
    }

    private void addHyperlinksHelper(final String typeName, final IProject project,
            final List<IHyperlink> hyperlinksCollector) {
        IBeansModel model = BeansCorePlugin.getModel();
        IBeansProject springProject = model.getProject(project);

        if (springProject == null) {
            return;
        }

        Set<IBeansConfig> configs = springProject.getConfigs();
        Set<AutowireBeanHyperlink> hyperlinks = new HashSet<AutowireBeanHyperlink>();
        for (IBeansConfig config : configs) {
            addHyperlinksHelper(config, typeName, project, hyperlinks);
        }

        if (hyperlinks.size() == 1) {
            hyperlinks.iterator().next().setIsOnlyCandidate(true);
        }
        hyperlinksCollector.addAll(hyperlinks);
    }

    // public for testing
    public void addHyperlinksHelper(IBeansConfig config, final String typeName, final IProject project,
            final Set<AutowireBeanHyperlink> hyperlinks) {
        final AutowireDependencyProvider autowireDependencyProvider = new AutowireDependencyProvider(config,
                config);
        final String[][] beanNamesWrapper = new String[1][];

        try {
            IProjectClassLoaderSupport classLoaderSupport = JdtUtils
                    .getProjectClassLoaderSupport(project.getProject(), null);
            autowireDependencyProvider.setProjectClassLoaderSupport(classLoaderSupport);
            classLoaderSupport.executeCallback(new IProjectClassLoaderAwareCallback() {
                public void doWithActiveProjectClassLoader() throws Throwable {
                    autowireDependencyProvider.preloadClasses();
                    beanNamesWrapper[0] = autowireDependencyProvider.getBeansForType(typeName);
                }
            });
        } catch (Throwable e) {
            BeansCorePlugin.log(e);
        }

        String[] beanNames = beanNamesWrapper[0];
        for (final String beanName : beanNames) {
            IBean bean = autowireDependencyProvider.getBean(beanName);
            final IResource resource = bean.getElementResource();
            final int line = bean.getElementStartLine();
            if (resource instanceof IFile) {
                AutowireBeanHyperlink newHyperlink = new AutowireBeanHyperlink((IFile) resource, line, beanName);
                boolean found = false;

                for (AutowireBeanHyperlink hyperlink : hyperlinks) {
                    if (resource.equals(hyperlink.getFile()) && line == hyperlink.getLine()) {
                        if (!beanName.equals(hyperlink.getBeanName())) {
                            hyperlink.setShowFileName(true);
                            hyperlinks.add(newHyperlink);
                            newHyperlink.setShowFileName(true);
                            break;
                        }
                        found = true;
                    }
                }

                if (!found) {
                    hyperlinks.add(newHyperlink);
                }
            }
        }

    }

    private IType getParentType(IJavaElement element) {
        if (element == null) {
            return null;
        }

        if (element instanceof IType) {
            return (IType) element;
        }

        return getParentType(element.getParent());
    }

}